国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

android應(yīng)用市場點擊下載APK安裝詳解

這篇具有很好參考價值的文章主要介紹了android應(yīng)用市場點擊下載APK安裝詳解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?Android系統(tǒng)啟動篇

1,《android系統(tǒng)啟動流程簡介》

2,《android init進(jìn)程啟動流程》

3,《android zygote進(jìn)程啟動流程》

4,《Android SystemServer進(jìn)程啟動流程》

5,《android launcher啟動流程》

6,《Android Activity啟動過程詳解》

Android系統(tǒng)開發(fā)準(zhǔn)備篇

1,《Android 源碼下載和編譯》

2,《android 11源碼編譯和pixel3 刷機(jī)》

3,《Android Framework代碼IDE加載和調(diào)試》

Android系統(tǒng)開發(fā)實踐篇

1,《android設(shè)置默認(rèn)輸入法》

2,《android framework預(yù)制APK應(yīng)用》

3,《Android系統(tǒng)層面限制應(yīng)用開機(jī)自啟動詳解》

4,《android單獨編譯framework模塊并push》

5,《Android Framework開發(fā)系統(tǒng)問題分析》

Android系統(tǒng)開發(fā)核心知識儲備篇

1,《Android編譯系統(tǒng)-envsetup和lunch代碼篇》

2,《Android編譯系統(tǒng)-概念篇》

3,《android日志系統(tǒng)詳解》

4,《Android系統(tǒng)Handler詳解》

5,《Android系統(tǒng)Binder詳解》

6,《Android中Activity、View和Window關(guān)系詳解》

7,《android view繪制流程詳解》

8,《Android讀取系統(tǒng)屬性詳解》

9,《android 窗口管理機(jī)制詳解》

10,《初識Android系統(tǒng)》

11,《android中AMS進(jìn)程通知Zygote進(jìn)程fork新進(jìn)程的通信方式》

Android核心功能詳解篇

1,《android應(yīng)用市場點擊下載APK安裝詳解》

2,《Android 手勢導(dǎo)航(從下往上滑動進(jìn)入多任務(wù)頁面)》

3,《android手勢分析(應(yīng)用界面左往右邊滑動退出應(yīng)用)》

4,《android應(yīng)用安裝流程詳解》

5,《android11安裝應(yīng)用觸發(fā)桌面圖標(biāo)刷新流程》

6,《Android系統(tǒng)多任務(wù)Recents詳解》

7,《android系統(tǒng)導(dǎo)航欄視圖分析》

———————————————————————————————————————————

目錄

一,背景介紹

二,安裝過程

2.1 流程概述

2.2 PackageInstaller安裝APK

2.3 PMS執(zhí)行安裝


一,背景介紹

android的APK安裝流程,有四種安裝方式:

1,系統(tǒng)應(yīng)用和預(yù)制應(yīng)用安裝,開機(jī)時完成,沒有安裝界面,在PKMS的構(gòu)造函數(shù)中歐冠完成安裝

2,網(wǎng)絡(luò)下載應(yīng)用安裝,通過應(yīng)用商店來完成,調(diào)用PackageManager.installPackages(),有安裝界面

3,ADB工具安裝,沒有安裝界面,它通過啟動pm腳本的形式,然后調(diào)用com.android.commands.pm.Pm類,之后調(diào)用到PMS.installStage()完成安裝

4,第三方應(yīng)用安裝,通過SD卡里的APK文件安裝,有安裝界面,由packageinstaller.apk應(yīng)用處理安裝及卸載過程的界面.

均是通過PackageInstallObserver來監(jiān)聽安裝是否成功。

二,安裝過程

2.1 流程概述

應(yīng)用安裝主要流程:

1,將APK的信息通過IO流的形式寫入到PackageInstaller.Session中。
2,調(diào)用PackageInstaller.Session的commit方法,將APK的信息交由PKMS處理。
3,拷貝APK
4,最后進(jìn)行安裝

????????在應(yīng)用市場點擊一個未安裝的apk后,發(fā)送廣播打開PackageInstallerActivity,拉起com.android.packageinstaller(斷點的進(jìn)程)應(yīng)用,彈出安裝界面,這個主要是由bindUi構(gòu)成,點擊之后就會調(diào)用startInstall()進(jìn)行安裝。

/PackageInstallerActivity.java
private void bindUi() {
        mAlert.setIcon(mAppSnippet.icon);
        mAlert.setTitle(mAppSnippet.label);
        mAlert.setView(R.layout.install_content_view);
        mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
                (ignored, ignored2) -> {
                    if (mOk.isEnabled()) {
                        if (mSessionId != -1) {
                            mInstaller.setPermissionsResult(mSessionId, true);
                            finish();
                        } else {
                          //進(jìn)行APK安裝
                            startInstall();
                        }
                    }
                }, null);
        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
                (ignored, ignored2) -> {
                    // Cancel and finish
                    setResult(RESULT_CANCELED);
                    if (mSessionId != -1) {
                      //如果mSessionId存在,執(zhí)行setPermissionsResult()完成取消安裝
                        mInstaller.setPermissionsResult(mSessionId, false);
                    }
                    finish();
                }, null);
        setupAlert();

       ......
    }

//點擊”安裝“,跳轉(zhuǎn) InstallInstalling - 開始安裝
private void startInstall() {
    // Start subactivity to actually install the application
    Intent newIntent = new Intent();
    newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
    newIntent.setData(mPackageURI);
    newIntent.setClass(this, InstallInstalling.class);
    String installerPackageName = getIntent().getStringExtra( Intent.EXTRA_INSTALLER_PACKAGE_NAME);
    ...
    if (installerPackageName != null) {
        newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
    }
    newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
    startActivity(newIntent);
    finish();
}

其中,R.layout.install_content_view布局視圖如下:

android下載安裝,android,android studio,ide

????????在startInstall方法組裝了一個Intent,并跳轉(zhuǎn)到InstallInstalling這個Activity,并關(guān)閉掉當(dāng)前的PackageInstallerActivity。在InstallInstalling主要用于向包管理器發(fā)送包的信息并處理包管理的回調(diào)。

2.2 PackageInstaller安裝APK

在啟動InstallInstalling后,進(jìn)入onCreate方法:

//InstallInstalling
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ApplicationInfo appInfo = getIntent()
                .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
        mPackageURI = getIntent().getData();

          ......
            setupAlert();
            requireViewById(R.id.installing).setVisibility(View.VISIBLE);

            if (savedInstanceState != null) {
                mSessionId = savedInstanceState.getInt(SESSION_ID);
                mInstallId = savedInstanceState.getInt(INSTALL_ID);

                try {
                  //.根據(jù)mInstallId向InstallEventReceiver注冊一個觀察者,launchFinishBasedOnResult會接收到安裝事件的回調(diào),無論安裝成功或者失敗都會關(guān)閉當(dāng)前的Activity(InstallInstalling)。如果savedInstanceState為null,代碼的邏輯也是類似的
                    InstallEventReceiver.addObserver(this, mInstallId,
                            this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    // Does not happen
                }
            } else {
                ......

                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(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
                    Log.e(LOG_TAG,
                            "Cannot calculate installed size " + file + ". Try only apk size.");
                    params.setSize(file.length());
                } catch (IOException e) {
                    Log.e(LOG_TAG,
                            "Cannot calculate installed size " + file + ". Try only apk size.");
                    params.setSize(file.length());
                }

                try {
                  //向InstallEventReceiver注冊一個觀察者返回一個新的mInstallId,
                  //其中InstallEventReceiver繼承自BroadcastReceiver,用于接收安裝事件并回調(diào)給EventResultPersister。
                    mInstallId = InstallEventReceiver
                            .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                    this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }

                try {
                  //PackageInstaller的createSession方法內(nèi)部會通過IPackageInstaller與PackageInstallerService進(jìn)行進(jìn)程間通信,最終調(diào)用的是PackageInstallerService的createSession方法來創(chuàng)建并返回mSessionId
                    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
                } catch (IOException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }
            }

            mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);

            mSessionCallback = new InstallSessionCallback();
        }
    }

????????在onCreate中通過PackageInstaller通過創(chuàng)建Session并返回mSesionId,接著會在onResume中,會開啟InstallingAsynTask,把包信息寫入mSessionId對應(yīng)的session,然后提交。

//InstallInstalling
protected void onResume() {
        super.onResume();

        // This is the first onResume in a single life of the activity
        if (mInstallingTask == null) {
            PackageInstaller installer = getPackageManager().getPackageInstaller();
          //獲取sessionInfo
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

            if (sessionInfo != null && !sessionInfo.isActive()) {
              //創(chuàng)建內(nèi)部類InstallingAsyncTask的對象,調(diào)用execute(),最終進(jìn)入onPostExecute()
                mInstallingTask = new InstallingAsyncTask();
                mInstallingTask.execute();
            } else {
                // we will receive a broadcast when the install is finished
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            }
        }
    }

  private final class InstallingAsyncTask extends AsyncTask<Void, Void,
            PackageInstaller.Session> {
              
    @Override
    protected PackageInstaller.Session doInBackground(Void... params) {
        
              PackageInstaller.Session session;
            try {
                session = getPackageManager().getPackageInstaller().openSession(mSessionId);
            } catch (IOException e) {
                return null;
            }

            session.setStagingProgress(0);

            try {
                File file = new File(mPackageURI.getPath());

                try (InputStream in = new FileInputStream(file)) {
                    long sizeBytes = file.length();
                  //從session中獲取輸出流
                    try (OutputStream out = session
                            .openWrite("PackageInstaller", 0, sizeBytes)) {
                        byte[] buffer = new byte[1024 * 1024];
                       ......
                    }
                }

                return session;
            } catch (IOException | SecurityException e) {
               ......
        }

        @Override
        protected void onPostExecute(PackageInstaller.Session session) {
            if (session != null) {
                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntent.setPackage(getPackageName());
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        InstallInstalling.this,
                        mInstallId,
                        broadcastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                                //包寫入session進(jìn)行提交
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }  
   }

????????在InstallingAsyncTask的doInBackground()里會根據(jù)包的Uri,將APK的信息通過IO流的形式寫入到PackageInstaller.Session中,最后會在onPostExecute()中調(diào)用PackageInstaller.Session的commit方法,進(jìn)行安裝。

????????在里面會看到一個PackageInstaller,也就是APK安裝器,其實在ApplicationPackageManager的getPackageInstaller中創(chuàng)建的:

//ApplicationPackageManager
@Override
    public PackageInstaller getPackageInstaller() {
        synchronized (mLock) {
            if (mInstaller == null) {
                try {
                    mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
                            mContext.getPackageName(), getUserId());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return mInstaller;
        }
    }

????????在這里會傳入mPM.getPackageInstaller(),也就是IpacageInstaller的實例,其具體實現(xiàn)也就是PackageInstallerService, 其通過IPC的方式。它在初始化的時候會讀取/data/system目錄下的install_sessions文件,這個文件保存了系統(tǒng)未完成的Install Session。PMS則會根據(jù)文件的內(nèi)容創(chuàng)建PackageInstallerSession對象并從插入到mSessions中。

//PackageInstallerService.java
 public PackageInstallerService(Context context, PackageManagerService pm,
            Supplier<PackageParser2> apexParserSupplier) {
        mContext = context;
        mPm = pm;
        mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);

        mInstallThread = new HandlerThread(TAG);
        mInstallThread.start();

        mInstallHandler = new Handler(mInstallThread.getLooper());

        mCallbacks = new Callbacks(mInstallThread.getLooper());

        mSessionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
                "package-session");
   //這個文件保存了系統(tǒng)未完成的`Install Session`
        mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
        mSessionsDir.mkdirs();

        mApexManager = ApexManager.getInstance();
        mStagingManager = new StagingManager(this, context, apexParserSupplier);
    }

????????再來看下Session,是在于mSeesionId綁定的安裝會話,代表著一個在進(jìn)行中的安裝。Session類是對IPackageInstaller.openSession(sessionId) 獲取的 PackageInstallerSession(系統(tǒng)服務(wù)端)的封裝。

????????Session的創(chuàng)建和打開 具體實現(xiàn)是在 PackageInstallerService中,主要是 初始化apk的安裝信息及環(huán)境,并創(chuàng)建一個sessionId,將安裝Session與sessionId 進(jìn)行綁定.

????????接著我們回到InstallingAsyncTask中,在這里調(diào)用了session.commit方法:

//PackageInstaller        
public void commit(@NonNull IntentSender statusReceiver) {
            try {
              //調(diào)用PackageInstallerSession的commit方法,進(jìn)入到j(luò)ava框架層
                mSession.commit(statusReceiver, false);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

//PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
                ......
          //如果尚未調(diào)用,則會話將被密封。此方法可能會被多次調(diào)用以更新狀態(tài)接收者驗證調(diào)用者權(quán)限
        if (!markAsSealed(statusReceiver, forTransfer)) {
            return;
        }
        //不同的包
        if (isMultiPackage()) {
            final SparseIntArray remainingSessions = mChildSessionIds.clone();
            final IntentSender childIntentSender =
                    new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
                            .getIntentSender();
            boolean sealFailed = false;
            for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
                final int childSessionId = mChildSessionIds.keyAt(i);
                // seal all children, regardless if any of them fail; we'll throw/return
                // as appropriate once all children have been processed
                if (!mSessionProvider.getSession(childSessionId)
                        .markAsSealed(childIntentSender, forTransfer)) {
                    sealFailed = true;
                }
            }
            if (sealFailed) {
                return;
            }
        }
        dispatchStreamValidateAndCommit();
}

private void dispatchStreamValidateAndCommit() {
        mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
    }
mSession的類型為IPackageInstallerSession,這說明要通過IPackageInstallerSession來進(jìn)行進(jìn)程間的通信,最終會調(diào)用PackageInstallerSession的commit方法。
在這里發(fā)送了一個MSG_STREAM_VALIDATE_AND_COMMIT的信號,并在handler中進(jìn)行處理:
public boolean handleMessage(Message msg) {
        case MSG_STREAM_VALIDATE_AND_COMMIT:
           handleStreamValidateAndCommit();
           break;
            case MSG_INSTALL:
                handleInstall(); //
                break;
        ......
}

    private void handleStreamValidateAndCommit() {
        ......
            if (unrecoverableFailure != null) {
                onSessionVerificationFailure(unrecoverableFailure);
                // fail other child sessions that did not already fail
                for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
                    PackageInstallerSession session = nonFailingSessions.get(i);
                    session.onSessionVerificationFailure(unrecoverableFailure);
                }
            }
        }

        if (!allSessionsReady) {
            return;
        }

        mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
    }
在handleStreamValidateAndCommit又發(fā)送了消息MSG_INSTALL,實際上真正在執(zhí)行的是在handleInstall中:
private void handleInstall() {
        ......

        // 對于 multiPackage 會話,請在鎖之外讀取子會話,因為在持有鎖的情況下讀取子會話可能會導(dǎo)致死鎖 (b123391593)。
        List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();

        try {
            synchronized (mLock) {
                installNonStagedLocked(childSessions);
            }
        } catch (PackageManagerException e) {
            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
            Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
            destroyInternal();
            dispatchSessionFinished(e.error, completeMsg, null);
        }
    }

private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
            throws PackageManagerException {
        ......
            if (!success) {
                sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
                        isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
                        failure.error, failure.getLocalizedMessage(), null);
                return;
            }
            mPm.installStage(installingChildSessions);
        } else {
            mPm.installStage(installingSession);
        }
    }

????????最后執(zhí)行到了PMS的installStage方法。在上述的過程中,通過PackageInstaller維持了Session,把安裝包寫入到Session,真正的安裝過程就要來看PMS了。

2.3 PMS執(zhí)行安裝

//PackageManagerService.java
void installStage(List<ActiveInstallSession> children)
            throws PackageManagerException {
  //創(chuàng)建了類型未INIT_COPY的消息
        final Message msg = mHandler.obtainMessage(INIT_COPY);
  //創(chuàng)建InstallParams,它對應(yīng)于包的安裝數(shù)據(jù)
        final MultiPackageInstallParams params =
                new MultiPackageInstallParams(UserHandle.ALL, children);
        params.setTraceMethod("installStageMultiPackage")
                .setTraceCookie(System.identityHashCode(params));
        msg.obj = params;

        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
                System.identityHashCode(msg.obj));
        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                System.identityHashCode(msg.obj));
  //將InstallParams通過消息發(fā)送出去
        mHandler.sendMessage(msg);
    }

handler對INIT_COPY的消息進(jìn)行處理:

//PackageManagerService.java
void doHandleMessage(Message msg) {
            switch (msg.what) {
                case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    if (params != null) {
                        if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                System.identityHashCode(params));
                        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                      //執(zhí)行APK拷貝動作
                        params.startCopy();
                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                    }
                    break;
                }
                ......
            }
  
  final void startCopy() {
            if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
            handleStartCopy();
            handleReturnCode();
        }

????????在這里調(diào)用了兩個方法handleStartCopy和handleReturnCode,其實現(xiàn)是在InstallParams 中。
在handleStartCopy,做了以下操作:

  • 檢查空間大小,如果空間不夠則釋放無用空間
  • 覆蓋原有安裝位置的文件,并根據(jù)返回結(jié)果來確定函數(shù)的返回值,并設(shè)置installFlags
  • 確定是否有任何已安裝的包驗證器,如有,則延遲檢測。主要分三步:首先新建一個驗證Intent,然后設(shè)置相關(guān)的信息,之后獲取驗證器列表,最后向每個驗證器發(fā)送驗證Intent
public void handleStartCopy() {
  ......
    //解析包 返回最小的細(xì)節(jié):pkgName、versionCode、安裝所需空間大小、獲取安裝位置等
    pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                    origin.resolvedPath, installFlags, packageAbiOverride);
  ......
    //覆蓋原有安裝位置的文件,并根據(jù)返回結(jié)果來確定函數(shù)的返回值,并設(shè)置installFlags。
    if (ret == PackageManager.INSTALL_SUCCEEDED) {
                int loc = pkgLite.recommendedInstallLocation;
                if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
                    ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                    ret = PackageManager.INSTALL_FAILED_INVALID_URI;
                } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
                    ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
                } else {
                     .......
                }
            }
  
  //安裝參數(shù)
  final InstallArgs args = createInstallArgs(this);
            mVerificationCompleted = true;
            mIntegrityVerificationCompleted = true;
            mEnableRollbackCompleted = true;
            mArgs = args;

            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                final int verificationId = mPendingVerificationToken++;

                // apk完整性校驗
                if (!origin.existing) {
                    PackageVerificationState verificationState =
                            new PackageVerificationState(this);
                    mPendingVerification.append(verificationId, verificationState);

                    sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
                    ret = sendPackageVerificationRequest(
                            verificationId, pkgLite, verificationState);

                    ......
                }

}

然后來看下handleReturnCode方法:

@Override
        void handleReturnCode() {
            ......
                if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                  //執(zhí)行APKcopy拷貝
                    mRet = mArgs.copyApk();
                }
          //執(zhí)行安裝
                processPendingInstall(mArgs, mRet);
            }
        }

APK的copy過程是如何拷貝的:

//packageManagerService.java
int copyApk() {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
            try {
                return doCopyApk();
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

private int doCopyApk() {
            ......

            int ret = PackageManagerServiceUtils.copyPackage(
                    origin.file.getAbsolutePath(), codeFile);
            ......
            return ret;
        }
//繼續(xù)追蹤下去,他會到PackagemanagerSeriveUtils的copyFile方法

//PackagemanagerSeriveUtils
private static void copyFile(String sourcePath, File targetDir, String targetName)
            throws ErrnoException, IOException {
        if (!FileUtils.isValidExtFilename(targetName)) {
            throw new IllegalArgumentException("Invalid filename: " + targetName);
        }
        Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);

        final File targetFile = new File(targetDir, targetName);
        final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
                O_RDWR | O_CREAT, 0644);
        Os.chmod(targetFile.getAbsolutePath(), 0644);
        FileInputStream source = null;
        try {
            source = new FileInputStream(sourcePath);
            FileUtils.copy(source.getFD(), targetFd);
        } finally {
            IoUtils.closeQuietly(source);
        }
    }

????????在這里就通過文件流的操作,把Apk拷貝到/data/app的目錄下了。結(jié)束完拷貝之后,就要進(jìn)入真正的安裝了,流程如下:

/PackageManagerService.java
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        if (args.mMultiPackageInstallParams != null) {
            args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
        } else {
          //安裝結(jié)果
            PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
          //創(chuàng)建一個新線程來處理安轉(zhuǎn)參數(shù)來進(jìn)行安裝
            processInstallRequestsAsync(
                    res.returnCode == PackageManager.INSTALL_SUCCEEDED,
                    Collections.singletonList(new InstallRequest(args, res)));
        }
    }

//排隊執(zhí)行異步操作
private void processInstallRequestsAsync(boolean success,
            List<InstallRequest> installRequests) {
        mHandler.post(() -> {
            if (success) {
                for (InstallRequest request : installRequests) {
                  //進(jìn)行檢驗,如果之前安裝失敗,則清除無用信息
                    request.args.doPreInstall(request.installResult.returnCode);
                }
                synchronized (mInstallLock) {
                  //安裝的核心方法,進(jìn)行解析apk安裝
                    installPackagesTracedLI(installRequests);
                }
                for (InstallRequest request : installRequests) {
                  //再次檢驗清除無用信息
                  
                    request.args.doPostInstall(
                            request.installResult.returnCode, request.installResult.uid);
                }
            }
            for (InstallRequest request : installRequests) {
              //備份、可能的回滾、發(fā)送安裝完成先關(guān)廣播
                restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                        new PostInstallData(request.args, request.installResult, null));
            }
        });
    }

看到了核心方法installPackagesTracedLI,接著內(nèi)部執(zhí)行到了installPackagesLI方法:

//PackageMmanagerSerice.java 
private void installPackagesLI(List<InstallRequest> requests) {
   .......
     //分析當(dāng)前任何狀態(tài),分析包并對其進(jìn)行初始化驗證
     prepareResult =
          preparePackageLI(request.args, request.installResult);
      
  ......
    //根據(jù)準(zhǔn)備階段解析包的信息上下文,進(jìn)一步解析
      final ScanResult result = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user, request.args.abiOverride);     
    .......
      //驗證掃描后包的信息好狀態(tài),確保安裝成功
      reconciledPackages = reconcilePackagesLocked(
                            reconcileRequest, mSettings.mKeySetManagerService);
          
        //提交所有的包并更新系統(tǒng)狀態(tài)。這是安裝流中唯一可以修改系統(tǒng)狀態(tài)的地方,必須在此階段之前確定所有可預(yù)測的錯誤
        commitRequest = new CommitRequest(reconciledPackages,
                            mUserManager.getUserIds());
                    commitPackagesLocked(commitRequest);
  .......
    //完成APK安裝
  executePostCommitSteps(commitRequest);
 }

由上面代碼可知,installPackagesLI主要做了以下事情:

  • 分析當(dāng)前任何狀態(tài),分析包并對其進(jìn)行初始化驗證
  • 根據(jù)準(zhǔn)備階段解析包的信息上下文,進(jìn)一步解析
  • 驗證掃描后包的信息好狀態(tài),確保安裝成功
  • 提交所有騷哦歐廟的包并更新系統(tǒng)狀態(tài)
  • 完成APK安裝

在 preparePackageLI() 內(nèi)使用 PackageParser2.parsePackage() 解析AndroidManifest.xml,獲取四大組件等信息;使用ParsingPackageUtils.getSigningDetails() 解析簽名信息;重命名包最終路徑 等。

完成了解析和校驗準(zhǔn)備工作后,最后一步就是對apk的安裝了。這里調(diào)用了executePostCommitSteps準(zhǔn)備app數(shù)據(jù),并執(zhí)行dex優(yōu)化。

//PackageManagerService.java
private void executePostCommitSteps(CommitRequest commitRequest) {
  //進(jìn)行安裝
  prepareAppDataAfterInstallLIF(pkg);
   .......
   final boolean performDexopt =
                    (!instantApp || Global.getInt(mContext.getContentResolver(),
                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                    && !pkg.isDebuggable()
                    && (!onIncremental);
  
  //為新的代碼路徑準(zhǔn)備應(yīng)用程序配置文件
  mArtManagerService.prepareAppProfiles(
                    pkg,
                    resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
  
  if (performDexopt) {

             ......
               //其中分配了 dexopt 所需的庫文件
               PackageSetting realPkgSetting = result.existingSettingCopied
                        ? result.request.pkgSetting : result.pkgSetting;
                if (realPkgSetting == null) {
                    realPkgSetting = reconciledPkg.pkgSetting;
                }
                
                            //執(zhí)行dex優(yōu)化
                mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
                        null /* instructionSets */,
                        getOrCreateCompilerPackageStats(pkg),
                        mDexManager.getPackageUseInfoOrDefault(packageName),
                        dexoptOptions);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
}

在prepareAppDataAfterInstallLIF方法中,經(jīng)過一系列的調(diào)用,最中會調(diào)用到 mInstaller.createAppData,這里也是調(diào)用Installd守護(hù)進(jìn)程的入口:

public class Installer extends SystemService {
    
   @Override
    public void onStart() {
        if (mIsolated) {
            mInstalld = null;
        } else {
          //通過Binder調(diào)用到進(jìn)程installd
            connect();
        }
    }

    private void connect() {
        IBinder binder = ServiceManager.getService("installd");
        ......

        if (binder != null) {
            mInstalld = IInstalld.Stub.asInterface(binder);
            try {
                invalidateMounts();
            } catch (InstallerException ignored) {
            }
        } else {
            Slog.w(TAG, "installd not found; trying again");
            BackgroundThread.getHandler().postDelayed(() -> {
                connect();
            }, DateUtils.SECOND_IN_MILLIS);
        }
    }
  
     public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo, int targetSdkVersion) throws InstallerException {
        if (!checkBeforeRemote()) return -1;
        try {
          //進(jìn)行安裝操作
            return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                    targetSdkVersion);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }
    }

可以看到最終調(diào)用了Installd的createAppData方法進(jìn)行安裝。Installer是Java層提供的Java API接口,Installd 則是在init進(jìn)程啟動的具有root權(quán)限的Daemon進(jìn)程。

在processInstallRequestsAsync最后一步時調(diào)用了restoreAndPostInstall,在安裝完成時會發(fā)送POST_INSTALL消息:

//PackageManagerService.java
private void restoreAndPostInstall(
            int userId, PackageInstalledInfo res, @Nullable PostInstallData data) {
  
  .......
    if (!doRestore) {
            
            if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);

            Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
            mHandler.sendMessage(msg);
        }
}

void doHandleMessage(Message msg) {
  .......
  case POST_INSTALL: {
    .......
      //處理安裝結(jié)果
    handlePackagePostInstall(parentRes, grantPermissions,
                                killApp, virtualPreload, grantedPermissions,
                                whitelistedRestrictedPermissions, autoRevokePermissionsMode,
                                didRestore, args.installSource.installerPackageName, args.observer,
                                args.mDataLoaderType);
  }
}

private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
            boolean killApp, boolean virtualPreload,
            String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
            int autoRevokePermissionsMode,
            boolean launchedForRestore, String installerPackage,
            IPackageInstallObserver2 installObserver, int dataLoaderType) {
  
  ......
    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                        extras, 0 /*flags*/,
                        null /*targetPackage*/, null /*finishedReceiver*/,
                        updateUserIds, instantUserIds, newBroadcastWhitelist);
}

最后發(fā)送了ACTION_PACKAGE_ADDED廣播,launcher接收到這個廣播之后就會在桌面上添加應(yīng)用圖標(biāo)了。文章來源地址http://www.zghlxwxcb.cn/news/detail-564227.html

到了這里,關(guān)于android應(yīng)用市場點擊下載APK安裝詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Android Studio 無法安裝apk到小米手機(jī)問題解決

    以前開發(fā)都是用自己的samsung手機(jī),打開開發(fā)者選項和usb調(diào)試,直接可以連上Android Studio,進(jìn)行調(diào)試,后來我的samsung退伍了,換上了Apple,就無法使用了,用公司的小米手機(jī)打開開發(fā)者選項和usb調(diào)試,然后進(jìn)行調(diào)試,將apk安裝小米手機(jī)安裝應(yīng)用報錯(Failed to establish session?Erro

    2024年02月15日
    瀏覽(36)
  • Android下載apk并安裝apk(用于軟件版本升級用途)

    Android下載apk并安裝apk(用于軟件版本升級用途)

    軟件版本更新是每個應(yīng)用必不可少的功能,基本實現(xiàn)方案是請求服務(wù)器最新的版本號與本地的版本號對比,有新版本則下載apk并執(zhí)行安裝。請求服務(wù)器版本號與本地對比很容易,本文就不過多講解,主要講解下載apk到安裝apk的內(nèi)容。 (1)讀寫外部存儲的權(quán)限需要動態(tài)申請,

    2024年02月01日
    瀏覽(32)
  • flutter開發(fā)實戰(zhàn)-應(yīng)用更新apk下載、安裝apk、啟動應(yīng)用實現(xiàn)

    flutter開發(fā)實戰(zhàn)-應(yīng)用更新apk下載、安裝apk、啟動應(yīng)用實現(xiàn)

    flutter開發(fā)實戰(zhàn)-應(yīng)用更新apk下載、安裝apk、啟動應(yīng)用實現(xiàn) 在開發(fā)過程中,經(jīng)常遇到需要更新下載新版本的apk文件,之后進(jìn)行應(yīng)用更新apk下載、安裝apk、啟動應(yīng)用。我們在flutter工程中實現(xiàn)下載apk,判斷當(dāng)前版本與需要更新安裝的版本進(jìn)行比對判斷,通過判斷VersionCode來確定下載

    2024年02月02日
    瀏覽(60)
  • iOS和Android手機(jī)瀏覽器鏈接打開app store或應(yīng)用市場下載軟件

    1.Android主流手機(jī)跳轉(zhuǎn)鏈接 2.判斷手機(jī)類型 3.iOS跳轉(zhuǎn)app store

    2024年02月11日
    瀏覽(45)
  • 在Android Studio通過adb命令強(qiáng)制安裝debug版本apk到手機(jī),且允許version code降級

    在Android Studio通過adb命令強(qiáng)制安裝debug版本apk到手機(jī),且允許version code降級 切換到Terminal: .appbuildintermediatesapkdebug是android studio的apk編譯生成路徑。 參數(shù): -t? ?允許安裝測試包 -d? ?運行version code 降級 -r? ?取代現(xiàn)有application -g? 授予所有權(quán)限 ? ? ? adb命令導(dǎo)出手機(jī)已安

    2024年02月14日
    瀏覽(30)
  • iOS和Android手機(jī)瀏覽器鏈接打開app store或應(yīng)用市場下載軟件講解

    當(dāng)開發(fā)一個app出來后,通過分享引流用戶去打開/下載該app軟件,不同手機(jī)下載的地方不一樣,比如:ios需要到蘋果商店去下載,Android手機(jī)需要到各個不同的應(yīng)用商店去下載(華為手機(jī)需要到華為應(yīng)用商店下載,vivo手機(jī)需要到vivo手機(jī)的應(yīng)用商店下載,oppo需到oppo的應(yīng)用商店去下

    2024年02月13日
    瀏覽(58)
  • adb命令導(dǎo)出手機(jī)已安裝的android應(yīng)用apk文件

    adb命令導(dǎo)出手機(jī)已安裝的android應(yīng)用apk文件

    前提條件是手機(jī)已經(jīng)和PC電腦可以通過adb建立連接。 (1)通過adb shell命令獲取當(dāng)前手機(jī)所有已經(jīng)安裝的應(yīng)用包名: ? (2)根據(jù)上面打印出來的包名,找到想要導(dǎo)出apk文件的應(yīng)用包名,這個包名可以通過多種方式找到,也可以用一些工具找,假設(shè)已經(jīng)知道某個應(yīng)用的包名后,

    2024年02月16日
    瀏覽(37)
  • Android Studio下載與安裝

    Android Studio下載與安裝

    注意:下載Android Studio之前,電腦要配置JDK環(huán)境變量 注意:該版本為 2021.2.1.16 Android官網(wǎng):https://developer.android.google.cn/

    2024年02月11日
    瀏覽(16)
  • 下載安裝Android Studio教程

    下載安裝Android Studio教程

    步驟1:下載Android Studio 訪問Android Studio官方網(wǎng)站(https://developer.android.com/studio),點擊“下載Android Studio”按鈕。選擇適用于您操作系統(tǒng)的版本,然后下載安裝程序。 ? 步驟2:往下滑,打勾,點擊綠色按鈕下載 ? 步驟3:下載好之后會在本地有一個exe安裝程序,雙擊安裝 ? 步驟

    2024年02月12日
    瀏覽(24)
  • Android studio的下載安裝教程

    Android studio的下載安裝教程

    1. 打開瀏覽器,搜索android studio,點擊官網(wǎng)鏈接。(或點擊Android studio) 2.點擊Download options ? ?3.進(jìn)行Android studio版本的選擇(根據(jù)電腦的版本選取對應(yīng)的安裝包,我的電腦是Windows 64 bit,因此選擇Windows)。 ?4.勾選同意協(xié)議,點擊下載 ?5.找到下載的安裝程序,雙擊打開 6. 點

    2024年02月05日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包