Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中APK的安裝流程

Android中APK的安裝流程

編輯:關於Android編程

這篇文章,來學習apk的安裝流程,在開始之前,先看看我們在APP中是通過下面代碼來安裝apk的

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + path),"application/vnd.android.package-archive");
context.startActivity(intent);

構造一個intent,並且setDataAndType,然後啟動這個activity,此時系統默認的安裝apk的PackageInstallerActivity界面就出現了。

使用PackageInstallerActivity安裝apk的流程

在PackageInstallerActivity中定義了這樣的字符串

private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";

這個是在PackageManagerService中匹配的。
PackageInstallerActivity也是一個activity,所以當該界面顯示的時候,會首先調用其onCreate方法,我們來看看。

 @Override
protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mPm = getPackageManager(); //是一個PackageManager實例,具體用來執行安裝操作的
        mInstaller = mPm.getPackageInstaller(); // PackageInstaller實例,在該實例中包含了安裝apk的基本信息
        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);

        final Intent intent = getIntent();

        //set view
        setContentView(R.layout.install_start);
        mInstallConfirm = findViewById(R.id.install_confirm_panel);
        mInstallConfirm.setVisibility(View.INVISIBLE);

        // Block the install attempt on the Unknown Sources setting if necessary.
        if (!requestFromUnknownSource) {
            // 為安裝操作,執行一些初始化的工作
            initiateInstall();
            return;
        }
}

可以看到,在onCreate中,主要通過initiateInstall();為安裝操作,執行一些初始化的工作。

private void initiateInstall() {
        // 當前apk的包名
        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;
        }

        try {
            // 通過PackageManager從系統中獲取沒有安裝的apk的信息
            mAppInfo = mPm.getApplicationInfo(pkgName,
                    PackageManager.GET_UNINSTALLED_PACKAGES);
            // 如果已經安裝,在後面會給出用戶是否替換的提示
            if ((mAppInfo.flags& ApplicationInfo.FLAG_INSTALLED) == 0) {
                mAppInfo = null;
            }
        } catch (PackageManager.NameNotFoundException e) {
            mAppInfo = null;
        }
        // 調用startInstallConfirm進行進一步的安裝操作
        startInstallConfirm();
}

上面代碼最終主要該通過startInstallConfirm來進一步安裝apk

private void startInstallConfirm() {
        mInstallConfirm.setVisibility(View.VISIBLE);
        mOk = (Button)findViewById(R.id.ok_button);
        mCancel = (Button)findViewById(R.id.cancel_button);
        mOk.setOnClickListener(this);
        mCancel.setOnClickListener(this);
}
PackageInstallerActivity實現了OnClicklistener
public void onClick(View v) {
        if (v == mOk) {
           startInstall();
        } else if(v == mCancel) {
            // Cancel and finish
            setResult(RESULT_CANCELED);
            finish();
        }
}



private void startInstall() {
        // 安裝apk,構造intent,這裡會跳轉到InstallAppProgress裡
        Intent newIntent = new Intent();
        // 傳遞數據
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
                mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        newIntent.setClass(this, InstallAppProgress.class);
        newIntent.putExtra(InstallAppProgress.EXTRA_MANIFEST_DIGEST, mPkgDigest);
        newIntent.putExtra(
                InstallAppProgress.EXTRA_INSTALL_FLOW_ANALYTICS, mInstallFlowAnalytics);
        String installerPackageName = getIntent().getStringExtra(
                Intent.EXTRA_INSTALLER_PACKAGE_NAME);
        if (mOriginatingURI != null) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
        }
        if (mReferrerURI != null) {
            newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
        }
        if (mOriginatingUid != VerificationParams.NO_UID) {
            newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
        }
        if (installerPackageName != null) {
            newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                    installerPackageName);
        }
        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
            newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        }
        // 進入InstallAppProgress
        startActivity(newIntent);
        finish();
}

可以看到在startInstall方法中,主要構造一個intent,並且傳遞必要的數據,跳轉到InstallAppProgress類,在該類中有一個initView方法

public void initView() {
        setContentView(R.layout.op_progress);
        int installFlags = 0;
        PackageManager pm = getPackageManager();
        // 判斷當前apk是否已經安裝過
        try {
            PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,
                    PackageManager.GET_UNINSTALLED_PACKAGES);
            if(pi != null) {
                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
            }
        } catch (PackageManager.NameNotFoundException e) {
        }
        // 省略代碼
        // 構造一個PackageInstallObserver,當安裝完成以後,回調對應的方法
        PackageInstallObserver observer = new PackageInstallObserver();

        if ("package".equals(mPackageURI.getScheme())) {
            try {
                // 調用PackageManagerService服務的installExistingPackage進行安裝
                pm.installExistingPackage(mAppInfo.packageName);
                observer.packageInstalled(mAppInfo.packageName,
                        PackageManager.INSTALL_SUCCEEDED);
            } catch (PackageManager.NameNotFoundException e) {
                observer.packageInstalled(mAppInfo.packageName,
                        PackageManager.INSTALL_FAILED_INVALID_APK);
            }
        } else {
            pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
                    installerPackageName, verificationParams, null);
        }
}

這裡具體的PackageManagerService服務安裝的過程我們稍後會進行學習,先看下當安裝完成以後通過PackageInstallObserver執行的回調方法

class PackageInstallObserver extends IPackageInstallObserver.Stub {
        public void packageInstalled(String packageName, int returnCode) {
            Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
            msg.arg1 = returnCode;
            mHandler.sendMessage(msg);
        }
}

發送”INSTALL_COMPLETE”這樣的消息到自身,在handleMessage中主要做了下面的操作:

mLaunchIntent = getPackageManager().getLaunchIntentForPackage(
                                mAppInfo.packageName);
mLaunchButton.setOnClickListener(InstallAppProgress.this);
mDoneButton.setOnClickListener(InstallAppProgress.this);

獲取啟動當前apk的intent,並且為done和lunch按鈕設置點擊事件

 public void onClick(View v) {
        if(v == mDoneButton) {
            if (mAppInfo.packageName != null) {
                Log.i(TAG, "Finished installing "+mAppInfo.packageName);
            }
            finish();
        } else if(v == mLaunchButton) {
            startActivity(mLaunchIntent);
            finish();
        }
}

好了,到現在為止,使用PackageInstallerActivity安裝apk的整個流程已經梳理完畢,實際上真正執行安裝操作的都是交給了PackageManagerService服務的installExistingPackage進行安裝的

PackageManagerService安裝apk流程

平時我們可以使用下面兩個命令來安裝apk

pm get-install-location 查找安裝apk的位置 一般默認 為0[auto]
pm set-install-location 設置位置

這裡最終都是通過PackageManagerService來實現安裝具體包的操作
調用PackageManagerService#installPackage方法開始apk的安裝過程

public void installPackage(String originPath, IPackageInstallObserver2 observer,
            int installFlags, String installerPackageName, VerificationParams verificationParams,
            String packageAbiOverride) {
        installPackageAsUser(originPath, observer, installFlags, installerPackageName,
                verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
}



@Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
                                     int installFlags, String installerPackageName, VerificationParams verificationParams,
                                     String packageAbiOverride, int userId) {
        // 檢查是否有install權限
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);

        final int callingUid = Binder.getCallingUid();
        enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
        // 判斷當前用戶是否被Restricted,回調onPackageInstalled方法,安裝失敗
        if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            try {
                if (observer != null) {
                    observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
                }
            } catch (RemoteException re) {
            }
            return;
        }

       // 代碼省略,主要是判斷當前安裝的方式設置對應的installFlags


        final File originFile = new File(originPath);
        final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
        // 發送"INIT_COPY" 消息,構造InstallParams參數
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
                null, verificationParams, user, packageAbiOverride, null);
        mHandler.sendMessage(msg);
}

整個PackageHandler是PackageManagerService的一個內部類

witch (msg.what) {
                case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    //這裡獲取當前需要安裝的apk個數,mPendingInstalls保存著所有需要安裝的apk解析出來的HandlerParams參數
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    // 如果沒有綁定DefaultContainerService,則進行那個綁定,DefaultContainerService主要負責計算當前存儲和拷貝工作
                    if (!mBound) {
                        if (!connectToService()) {
                            params.serviceError();
                            return;
                        } else {
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                        mPendingInstalls.add(idx, params);
                        if (idx == 0) {
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
}

繼續發送”MCS_BOUND”參數到自己處理,表示綁定DefaultContainerService服務完成

case MCS_BOUND: {
        if (msg.obj != null) {
            mContainerService = (IMediaContainerService) msg.obj;
        }
        if (mContainerService == null) {
            // 綁定DefaultContainerService服務失敗,回調serviceError方法
            if (!mBound) {
                Slog.e(TAG, "Cannot bind to media container service");
                for (HandlerParams params : mPendingInstalls) {
                    params.serviceError();
                }
                mPendingInstalls.clear();
            } else {
                Slog.w(TAG, "Waiting to connect to media container service");
            }
        } else if (mPendingInstalls.size() > 0) {
            // 總是安裝隊列中的第一個
            HandlerParams params = mPendingInstalls.get(0);
            if (params != null) {
                if (params.startCopy()) { //首先拷貝當前apk到對應的目錄下
                    // We are done...  look for more work or to
                    // go idle.
                    if (mPendingInstalls.size() > 0) { // 將第一個移除當前隊列
                        mPendingInstalls.remove(0);
                    }
                    if (mPendingInstalls.size() == 0) { //size等於0,表示所有的apk都已經安裝完成,unbind當前DefaultContainerService服務
                        if (mBound) {
                            if (DEBUG_SD_INSTALL) Log.i(TAG,
                                    "Posting delayed MCS_UNBIND");
                            removeMessages(MCS_UNBIND);
                            Message ubmsg = obtainMessage(MCS_UNBIND);
                            // Unbind after a little delay, to avoid
                            // continual thrashing.
                            sendMessageDelayed(ubmsg, 10000);
                        }
                    } else {
                        //繼續安裝下一個需要安裝的包
                        mHandler.sendEmptyMessage(MCS_BOUND);
                    }
                }
            }
        } else {
            Slog.w(TAG, "Empty queue");
        }
        break;
    }

可以看到,其實所有的安裝apk的代碼都放到了HandlerParams#startCopy方法中,看下HandlerParams

private abstract class HandlerParams {
    final boolean startCopy() {
            boolean res;
            try {
                if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);

                if (++mRetries > MAX_RETRIES) {
                    Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
                    mHandler.sendEmptyMessage(MCS_GIVE_UP);
                    handleServiceError();
                    return false;
                } else {
                    // 這裡的具體copy處理是由其子類來完成的
                    handleStartCopy();
                    res = true;
                }
            } catch (RemoteException e) {
                if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
                mHandler.sendEmptyMessage(MCS_RECONNECT);
                res = false;
            }
            // handleReturnCode,該方法會在handleStartCopy執行玩拷貝相關動作之後,根據在handleStartCopy中的做進一步處理
            handleReturnCode();
            return res;
        }

        final void serviceError() {
            if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
            handleServiceError();
            handleReturnCode();
        }

        abstract void handleStartCopy() throws RemoteException;
        abstract void handleServiceError();
        abstract void handleReturnCode();
    }

}

這裡是由InstallParams來處理copy操作的。

public void handleStartCopy() throws RemoteException {
        int ret = PackageManager.INSTALL_SUCCEEDED;

        if (origin.staged) {
            if (origin.file != null) {
                installFlags |= PackageManager.INSTALL_INTERNAL;
                installFlags &= ~PackageManager.INSTALL_EXTERNAL;
            } else if (origin.cid != null) {
                installFlags |= PackageManager.INSTALL_EXTERNAL;
                installFlags &= ~PackageManager.INSTALL_INTERNAL;
            } else {
                throw new IllegalStateException("Invalid stage location");
            }
        }
        // 是否安裝到sdcard或者內部存儲中
        final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
        final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;

        PackageInfoLite pkgLite = null;

        if (onInt && onSd) {
            // 用戶同時設置安裝到sdcard和內部存儲
            Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
            ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
        } else {
            pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                    packageAbiOverride);

            .......
            //代碼省略,主要根據存儲情況,釋放當前存儲空間
        }
        // 根據當前InstallParams構造具體的InstallArgs實現類,在該實現類中做具體的拷貝操作
        final InstallArgs args = createInstallArgs(this);
        mArgs = args;

        if (ret == PackageManager.INSTALL_SUCCEEDED) {
                 /*
                 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
                 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
                 */
            int userIdentifier = getUser().getIdentifier();
            if (userIdentifier == UserHandle.USER_ALL
                    && ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {
                userIdentifier = UserHandle.USER_OWNER;
            }

            final int requiredUid = mRequiredVerifierPackage == null ? -1
                    : getPackageUid(mRequiredVerifierPackage, userIdentifier);
            if (!origin.existing && requiredUid != -1
                    && isVerificationEnabled(userIdentifier, installFlags) &&
                    isVerificationRequired()) { // 對當前的包做驗證操作
                final Intent verification = new Intent(
                        Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
                        PACKAGE_MIME_TYPE);
                verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                final List receivers = queryIntentReceivers(verification,
                        PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
                        0 /* TODO: Which userId? */);

                final int verificationId = mPendingVerificationToken++;

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
                        installerPackageName);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
                        installFlags);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
                        pkgLite.packageName);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
                        pkgLite.versionCode);

                if (verificationParams != null) {
                    if (verificationParams.getVerificationURI() != null) {
                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
                                verificationParams.getVerificationURI());
                    }
                    if (verificationParams.getOriginatingURI() != null) {
                        verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
                                verificationParams.getOriginatingURI());
                    }
                    if (verificationParams.getReferrer() != null) {
                        verification.putExtra(Intent.EXTRA_REFERRER,
                                verificationParams.getReferrer());
                    }
                    if (verificationParams.getOriginatingUid() >= 0) {
                        verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
                                verificationParams.getOriginatingUid());
                    }
                    if (verificationParams.getInstallerUid() >= 0) {
                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
                                verificationParams.getInstallerUid());
                    }
                }

                final PackageVerificationState verificationState = new PackageVerificationState(
                        requiredUid, args);

                mPendingVerification.append(verificationId, verificationState);

                final List sufficientVerifiers = matchVerifiers(pkgLite,
                        receivers, verificationState);

                // Apps installed for "all" users use the device owner to verify the app
                UserHandle verifierUser = getUser();
                if (verifierUser == UserHandle.ALL) {
                    verifierUser = UserHandle.OWNER;
                }

                    /*
                     * If any sufficient verifiers were listed in the package
                     * manifest, attempt to ask them.
                     */
                if (sufficientVerifiers != null) {
                    final int N = sufficientVerifiers.size();
                    if (N == 0) {
                        Slog.i(TAG, "Additional verifiers required, but none installed.");
                        ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                    } else {
                        for (int i = 0; i < N; i++) {
                            final ComponentName verifierComponent = sufficientVerifiers.get(i);

                            final Intent sufficientIntent = new Intent(verification);
                            sufficientIntent.setComponent(verifierComponent);
                            mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
                        }
                    }
                }

                final ComponentName requiredVerifierComponent = matchComponentForVerifier(
                        mRequiredVerifierPackage, receivers);
                if (ret == PackageManager.INSTALL_SUCCEEDED
                        && mRequiredVerifierPackage != null) {
                        /*
                         * Send the intent to the required verification agent,
                         * but only start the verification timeout after the
                         * target BroadcastReceivers have run.
                         */
                    verification.setComponent(requiredVerifierComponent);
                    mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
                            android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
                            new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                    final Message msg = mHandler
                                            .obtainMessage(CHECK_PENDING_VERIFICATION);
                                    msg.arg1 = verificationId;
                                    mHandler.sendMessageDelayed(msg, getVerificationTimeout());
                                }
                            }, null, 0, null, null);

                        /*
                         * We don't want the copy to proceed until verification
                         * succeeds, so null out this field.
                         */
                    mArgs = null;
                }
            } else {
                // 執行拷貝操作
                ret = args.copyApk(mContainerService, true);
            }
        }

        mRet = ret;
    }

上面主要做了這樣的事情:
1. 判斷安裝默認存儲
2. 若當前存儲不夠,則釋放儲存空間
3. 如果需要,對當前包做驗證操作
4. 執行拷貝操作
就安裝而言,最重要的還是最後的執行拷貝操作,這裡是InstallArgs#copyApk

static abstract class InstallArgs

包含三個子類
1. FileInstallArgs apk安裝到內部存儲器時使用。
2. AsecInstallArgs 安裝到sdcard或者ForwardLocked時使用
3. MoveInstallArgs 移動包的位置,比如從內部存儲移動到sdcard上
在構造方法中根據InstallParams會構造出具體類型

private InstallArgs createInstallArgs(InstallParams params) {
        if (params.move != null) {
            return new MoveInstallArgs(params);
        } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
            return new AsecInstallArgs(params);
        } else {
            return new FileInstallArgs(params);
        }
}

這裡我們以AsecInstallArgs為例,進行說明

int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {

            if (origin.staged) {
                if (DEBUG_INSTALL) Slog.d(TAG, origin.cid + " already staged; skipping copy");
                cid = origin.cid;
                setMountPath(PackageHelper.getSdDir(cid));
                return PackageManager.INSTALL_SUCCEEDED;
            }

            if (temp) {
                createCopyFile();
            } else {
                /*
                 * Pre-emptively destroy the container since it's destroyed if
                 * copying fails due to it existing anyway.
                 */
                PackageHelper.destroySdDir(cid);
            }
            //copyPackageToContainer執行真正的拷貝操作
            final String newMountPath = imcs.copyPackageToContainer(
                    origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternalAsec(),
                    isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));

            if (newMountPath != null) {
                setMountPath(newMountPath);
                return PackageManager.INSTALL_SUCCEEDED; //這裡安裝成功之後,會將mRet賦值為PackageManager.INSTALL_SUCCEEDED
            } else {
                return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
            }
}

到現在為止,copyApk的操作已經完成,接下來交給handleReturnCode處理

@Override
void handleReturnCode() {
            // mArgs是在handleStartCopy中創建的
            if (mArgs != null) {
                processPendingInstall(mArgs, mRet);
            }
}




private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        // 由於安裝可能耗時操作,所以這裡開啟了一個線程
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                // Result object to be returned
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.returnCode = currentStatus;
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = new PackageRemovedInfo();
                // 如果之前copyApk正常執行完成,這裡res.returnCode == PackageManager.INSTALL_SUCCEEDED成立
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    args.doPreInstall(res.returnCode); //安裝前的准備工作
                    synchronized (mInstallLock) {
                        installPackageLI(args, res); //執行安裝操作
                    }
                    args.doPostInstall(res.returnCode, res.uid); //安裝完成以後的曹操作
                }

                .........
                Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); // 安裝完成後發送"POST_INSTALL"廣播
                mHandler.sendMessage(msg);
            }
        });
}


看下進一步安裝的相關步驟

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
        ......
        PackageParser pp = new PackageParser();
        pp.setSeparateProcesses(mSeparateProcesses);
        pp.setDisplayMetrics(mMetrics);
        pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages());

        final PackageParser.Package pkg;
        try {
            // PackageParser解析manifest文件
            pkg = pp.parsePackage(tmpPackageFile, parseFlags);
        } catch (PackageParser.PackageParserException e) {
            res.setError("Failed parse during installPackageLI", e);
            return;
        }

        // Mark that we have an install time CPU ABI override.
        pkg.cpuAbiOverride = args.abiOverride;

        String pkgName = res.name = pkg.packageName;

        // Mark that we have an install time CPU ABI override.
        pkg.cpuAbiOverride = args.abiOverride;

        String pkgName = res.name = pkg.packageName;
        // 根據用戶策略,判斷當前用戶是否允許安裝apk,否則直接返回
        boolean installForAllUsers = ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0);
        int user = args.user == null ? -1 : args.user.getIdentifier();
        if (isInstallationBlockedByDevicePolicy(pkgName, installForAllUsers, user)) {
            res.returnCode = PackageManager.INSTALL_FAILED_USER_RESTRICTED;
            return;
        }
        // 簽名相關信息
        try {
            pp.collectCertificates(pkg, parseFlags);
            pp.collectManifestDigest(pkg);
        } catch (PackageParser.PackageParserException e) {
            res.setError("Failed collect during installPackageLI", e);
            return;
        }
        ........
        // 如果已經安裝當前應用,則替換,否則安裝
        if (replace) {
            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                    installerPackageName, volumeUuid, res);
        } else {
            installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
                    args.user, installerPackageName, volumeUuid, res);
        }

}

可以看到上面的代碼主要做了下面操作:
1. 解析manifest文件,並且將解析結果封裝成PackageParser對象
2. 判斷當前安裝條件四是否滿足,否則直接返回,比如:根據用戶策略,判斷當前用戶是否允許安裝apk,否則直接返回
3. 獲取簽名相關信息,並且做校驗
4. 安裝或者替換當前應用installNewPackageLI或者replacePackageLI

PackageParser解析manifest文件,PackageParser#parsePackage —-> PackageParser#parseClusterPackage —> PackageParser#parseBaseApk

private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
            throws PackageParserException {
        final String apkPath = apkFile.getAbsolutePath();

        String volumeUuid = null;
        if (apkPath.startsWith(MNT_EXPAND)) {
            final int end = apkPath.indexOf('/', MNT_EXPAND.length());
            volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
        }

        mParseError = PackageManager.INSTALL_SUCCEEDED;
        mArchiveSourcePath = apkFile.getAbsolutePath();

        if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);

        final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);

        Resources res = null;
        XmlResourceParser parser = null;
        try {
            res = new Resources(assets, mMetrics, null);
            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    Build.VERSION.RESOURCES_SDK_INT);
            // 解析manifest文件
            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

            final String[] outError = new String[1];
            final Package pkg = parseBaseApk(res, parser, flags, outError);
            if (pkg == null) {
                throw new PackageParserException(mParseError,
                        apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
            }

            pkg.volumeUuid = volumeUuid;
            pkg.applicationInfo.volumeUuid = volumeUuid;
            pkg.baseCodePath = apkPath;
            pkg.mSignatures = null;

            return pkg;

        } catch (PackageParserException e) {
            throw e;
        } catch (Exception e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                    "Failed to read manifest from " + apkPath, e);
        } finally {
            IoUtils.closeQuietly(parser);
        }
}

通過installNewPackageLI執行安裝操作

     /*
      * Install a non-existing package.
      */
private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
                                     UserHandle user, String installerPackageName, String volumeUuid,
                                     PackageInstalledInfo res) {
        // Remember this for later, in case we need to rollback this install
        String pkgName = pkg.packageName;

        .......

        try {
            // 核心的調用
            PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
                    System.currentTimeMillis(), user);

            updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);
            //如果安裝失敗,則執行回退操作,刪除創建的文件夾等緩存文件
            if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
                deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
                        dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
                        res.removedInfo, true);
            }

        } catch (PackageManagerException e) {
            res.setError("Package couldn't be installed in " + pkg.codePath, e);
        }
    }




private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        boolean success = false;
        try {
            final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
                    currentTime, user);
            success = true;
            // 程序走到這裡說明安裝成功了,這裡會返回根據解析構建的Package對象,該對象中包含了該apk對應的manifest中的信息
            return res;
        } finally {
            if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                removeDataDirsLI(pkg.volumeUuid, pkg.packageName);
            }
        }
    }


**終於走到了scanPackageDirtyLI方法,安裝apk的核心方法:
在該方法中,會根據之前解析出來的內容,添加到對應的list中,方便以後query查詢**

    // Currently known shared libraries.
    final ArrayMap mSharedLibraries =
            new ArrayMap();

    // All available activities, for your resolving pleasure.
    final ActivityIntentResolver mActivities =
            new ActivityIntentResolver();

    // All available receivers, for your resolving pleasure.
    final ActivityIntentResolver mReceivers =
            new ActivityIntentResolver();

    // All available services, for your resolving pleasure.
    final ServiceIntentResolver mServices = new ServiceIntentResolver();

    // All available providers, for your resolving pleasure.
    final ProviderIntentResolver mProviders = new ProviderIntentResolver();



private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
                                                     int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
            .......

            int N = pkg.providers.size();
            StringBuilder r = null;
            int i;
            for (i=0; i

好了,關於apk的安裝的大致流程就到這裡了。下面畫一張圖來總結一下,如有遺漏或者不對的地方,歡迎指教。
這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved