インストールが完了した後のAndroid 7.1の変更ソースコードは、サイレントインストールアプリ&自動的に開いているアプリケーションがインストールされて実現しています。

本当のサイレントインストールは、ユーザーのクリックを必要とせず、ブログは言った、現在最もサイレントインストールまたはポップアップする必要は確認画面を、インストールを許可するユーザーを求めて、私はそれが本当のサイレント・インストールが操作を決定するために、任意のユーザーを必要としないされるべきだと思います、例えば、それがソフトウェア市場をインストールしたアプリケーションの多くは、今ある現実のサイレントインストールです。

同社はまた、キビや華為Googleは個人のアプリケーション市場があり、このアプリはアプリケーション市場交換を書き込まれないように、例えば、私は、アプリケーション市場のアプリがインストールされキビだろう、我々はそれを見つけ、同様の市場とアプリケーションのインストールを実現したいですHuawei社の携帯電話は、上記のキビの電話の内蔵におけるアプリケーションのようなサイレントインストールされるように達成することはできません。

通常の権限チェックには影響を与えないようにするために、我々は、ライン上のシステムのソースコードを修正インストールするための独自のインターフェースを追加する必要があります

 

次のように具体的な変更点は次のとおりです。

変更パッケージ/アプリケーション/ PackageInstaller / AndroidManifest.xmlを

次の権限を追加します。

<uses-permission android:name="android.permission.MANAGE_DOCUMENT" />

 

以下のレシーバを作成します。 

   <receiver android:name=".SilentInstallerReceiver" android:exported="true" >
            <intent-filter>
                <action android:name="xxx.intent.action.SILENT.INSTALLER" ></action>
                <action android:name="xxx.intent.action.SILENT.INSTALLER.COMMIT"></action>
            </intent-filter>
   </receiver>

以下のドキュメントパッケージを追加/アプリケーション/ PackageInstaller / SRC / COM /アンドロイド/ packageinstaller / SilentInstallerReceiver.java

package com.android.packageinstaller;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.content.PackageHelper;
import com.android.packageinstaller.permission.utils.IoUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SilentInstallerReceiver extends BroadcastReceiver {

    private static final String TAG = "SilentInstallerReceiver";
    private static final String BROADCAST_ACTION = "xxx.intent.action.SILENT.INSTALLER.COMMIT";
    private static final String PACKAGENAME = "slient_name";
    private static final String INSTLLPATH = "instll_path";
    private static final String SCHEME_FILE = "file";
    private static final String SCHEME_CONTENT = "content";
    private static final String SCHEME_PACKAGE = "package";

    private Context mContext;
    private Uri mPackageURI;
    private Intent mLaunchIntent;
    private HandlerThread mInstallThread;
    private Handler mInstallHandler;

    private AsyncTask<Uri, Void, File> mStagingAsynTask;
    private PackageManager mPm;
    private PackageInfo mPkgInfo;

    @Override
    public void onReceive(Context context, Intent intent) {

        mContext = context;
        boolean wasSetUp = false;
        mInstallThread = new HandlerThread("InstallThread");
        mInstallThread.start();
        mInstallHandler = new Handler(mInstallThread.getLooper());

        mPm = context.getPackageManager();
        String instllpath = intent.getStringExtra(INSTLLPATH);

        // TODO this is  lunch APP
        if (!BROADCAST_ACTION.equals(intent.getAction())) {
            if (TextUtils.isEmpty(instllpath)) {

                return;
            }
            mPackageURI = Uri.parse(instllpath);
            if (mPackageURI.getScheme() == null) {
                instllpath = "file://" + instllpath;
                mPackageURI = Uri.parse(instllpath);
            }
            Log.d(TAG, "  mPackageURI =  " + mPackageURI + " ,  intent getAction =   " + intent.getAction());
            wasSetUp = processPackageUri(mPackageURI);
        }


        if (BROADCAST_ACTION.equals(intent.getAction())) {
            Log.d(TAG, " install app , so  return !!!  ");
            onPackageInstalled(intent);
            return;
        }

        if (mPackageURI == null) {
            Log.d(TAG, " mPackageURI is null , so  return !!!  ");
            return;
        }

        if (!wasSetUp) {
            Log.d(TAG, " wasSetUp is false, return!!!   ");
            return;
        }

        initiateInstall();
    }


    private void initiateInstall() {
        String pkgName = mPkgInfo.packageName;
        // Check if there is already a package on the device with this name
        // but it has been renamed to something else.
        String[] oldName = mPm.canonicalToCurrentPackageNames(new String[]{pkgName});
        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
            pkgName = oldName[0];
            mPkgInfo.packageName = pkgName;
            mPkgInfo.applicationInfo.packageName = pkgName;
        }
        Log.d(TAG, " cdownloaded app uri=  " + mPackageURI);
        startSilentInstaller();
    }


    int getInstallFlags(String packageName) {
        PackageManager pm = mContext.getPackageManager();
        try {
            PackageInfo pi =
                    pm.getPackageInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
            if (pi != null) {
                return PackageManager.INSTALL_REPLACE_EXISTING;
            }
        } catch (PackageManager.NameNotFoundException e) {
        }
        return 0;
    }


    void startSilentInstaller() {
        final PackageManager pm = mContext.getPackageManager();
        final int installFlags = getInstallFlags(mPkgInfo.applicationInfo.packageName);

        if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            Log.w(TAG, "Replacing package:" + mPkgInfo.applicationInfo.packageName);
        }
        Log.d(TAG, " starSilentInstaller    +  packageName  " + mPkgInfo.applicationInfo.packageName);
        final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
        File file = new File(mPackageURI.getPath());

        try {
            PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
            params.setAppPackageName(pkg.packageName);
            params.setInstallLocation(pkg.installLocation);
            params.setSize(
                    PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
        } catch (PackageParser.PackageParserException e) {
            Log.e(TAG, "Cannot parse package " + file + ". Assuming defaults.");
            Log.e(TAG, "Cannot calculate installed size " + file + ". Try only apk size.");
            params.setSize(file.length());
        } catch (IOException e) {
            Log.e(TAG, "Cannot calculate installed size " + file + ". Try only apk size.");
            params.setSize(file.length());
        }

        mInstallHandler.post(new Runnable() {
            @Override
            public void run() {
                doPackageStage(pm, params);
            }
        });
    }


    private void doPackageStage(PackageManager pm, PackageInstaller.SessionParams params) {
        final PackageInstaller packageInstaller = pm.getPackageInstaller();
        PackageInstaller.Session session = null;
        try {
            final String packageLocation = mPackageURI.getPath();
            final File file = new File(packageLocation);
            final int sessionId = packageInstaller.createSession(params);
            final byte[] buffer = new byte[65536];

            session = packageInstaller.openSession(sessionId);

            final InputStream in = new FileInputStream(file);
            final long sizeBytes = file.length();
            final OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes);
            try {
                int c;
                while ((c = in.read(buffer)) != -1) {
                    out.write(buffer, 0, c);
                    if (sizeBytes > 0) {
                        final float fraction = ((float) c / (float) sizeBytes);
                        session.addProgress(fraction);
                    }
                }
                session.fsync(out);
            } finally {
                IoUtils.closeQuietly(in);
                IoUtils.closeQuietly(out);
            }

            // TODO this is  lunch APP  Broast
            // Create a PendingIntent and use it to generate the IntentSender
            Intent broadcastIntent = new Intent(BROADCAST_ACTION);
            broadcastIntent.putExtra(PACKAGENAME, mPkgInfo.applicationInfo.packageName);

            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    mContext /*context*/,
                    sessionId,
                    broadcastIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            session.commit(pendingIntent.getIntentSender());

        } catch (IOException e) {

        } finally {
            IoUtils.closeQuietly(session);
        }

    }


    /**
     * TODO this is  lunch APP  Receiver Broast
     * after app installed ,open the install app
     *
     * @param intent get insalled app name {@param BROADCAST_ACTION}
     */

    void onPackageInstalled(Intent intent) {
        Log.d(TAG, " install app is finishing, start luncher install app");
        mLaunchIntent = mContext.getPackageManager().getLaunchIntentForPackage(
                intent.getStringExtra(PACKAGENAME));
        if (mLaunchIntent == null) return;
        mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(mLaunchIntent);

    }

    /**
     * delete the apk
     */
    private void clearCachedApkIfNeededAndFinish() {
        if ("file".equals(mPackageURI.getScheme()) && mPackageURI.getPath() != null
                && mPackageURI.getPath().startsWith(mContext.getCacheDir().toString())) {
            File file = new File(mPackageURI.getPath());
            file.delete();
        }
    }

    /**
     * Parse the Uri and set up the installer for this package.
     *
     * @param packageUri The URI to parse
     * @return {@code true} iff the installer could be set up
     */
    private boolean processPackageUri(final Uri packageUri) {
        mPackageURI = packageUri;

        final String scheme = packageUri.getScheme();
        Log.d(TAG, " scheme  =  " + scheme + "  packageUri  " + packageUri);
        switch (scheme) {
            case SCHEME_PACKAGE: {
                try {
                    mPkgInfo = mPm.getPackageInfo(packageUri.getSchemeSpecificPart(),
                            PackageManager.GET_PERMISSIONS
                                    | PackageManager.GET_UNINSTALLED_PACKAGES);
                } catch (PackageManager.NameNotFoundException e) {
                }
                if (mPkgInfo == null) {
                    Log.w(TAG, "Requested package " + packageUri.getScheme()
                            + " not available. Discontinuing installation");
                    return false;
                }
            }
            break;

            case SCHEME_FILE: {
                File sourceFile = new File(packageUri.getPath());
                PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);
                // Check for parse errors
                if (parsed == null) {
                    Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
                    return false;
                }
                mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
                        PackageManager.GET_PERMISSIONS, 0, 0, null,
                        new PackageUserState());
            }
            break;

            case SCHEME_CONTENT: {
                mStagingAsynTask = new SilentInstallerReceiver.StagingAsyncTask();
                mStagingAsynTask.execute(packageUri);
                return false;
            }

            default: {
                Log.w(TAG, "Unsupported scheme " + scheme);
                clearCachedApkIfNeededAndFinish();
                return false;
            }
        }
        return true;
    }


    private final class StagingAsyncTask extends AsyncTask<Uri, Void, File> {

        @Override
        protected void onPreExecute() {
            // TODO  nothing to do
        }

        @Override
        protected File doInBackground(Uri... params) {
            if (params == null || params.length <= 0) {
                return null;
            }
            Uri packageUri = params[0];
            File sourceFile = null;
            try {
                sourceFile = File.createTempFile("package", ".apk", mContext.getApplicationContext().getCacheDir());
                try (
                        InputStream in = mContext.getApplicationContext().getContentResolver().openInputStream(packageUri);
                        OutputStream out = (in != null) ? new FileOutputStream(
                                sourceFile) : null;
                ) {
                    // Despite the comments in ContentResolver#openInputStream
                    // the returned stream can be null.
                    if (in == null) {
                        return null;
                    }
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = in.read(buffer)) >= 0) {
                        // Be nice and respond to a cancellation
                        if (isCancelled()) {
                            return null;
                        }
                        out.write(buffer, 0, bytesRead);
                    }
                }
            } catch (IOException ioe) {
                Log.w(TAG, "Error staging apk from content URI", ioe);
                if (sourceFile != null) {
                    sourceFile.delete();
                }
            }
            return sourceFile;
        }

        @Override
        protected void onPostExecute(File file) {
            if (file == null) {
                return;
            }
            Uri fileUri = Uri.fromFile(file);

            boolean wasSetUp = processPackageUri(fileUri);
            if (wasSetUp) {
                initiateInstall();
            }
        }

        @Override
        protected void onCancelled(File file) {
            // TODO  nothing to do
        }
    }

}

作成した後は再コンパイルPackageInstaller APK電話内の電話を再起動するようにプッシュします。

ダウンロードしたファイルが良好な場合、次のようにサイレントインストールの検証作業を使用して、ADBブロードキャスト送信は、発行することができます。

adb shell am broadcast -a xxx.intent.action.SILENT.INSTALLER --es instllpath "apk路径"

徐は、時間と携帯電話のパフォーマンスの関係を待って、より良いパフォーマンス、短い待ち時間を、このコマンド待ち5-10秒を実行します。インストールが完了したら、処置は必要ありません、APKに直接プルアップ、

インストールが完了した後に引き上げることにしたくない場合は、以下のコードインジェクションをコメントアウト。

<action android:name="xxx.intent.action.SILENT.INSTALLER.COMMIT"></action>

 

公開された25元の記事 ウォン称賛13 ビュー10000 +

おすすめ

転載: blog.csdn.net/ChaoLi_Chen/article/details/103576575