APK安裝流程詳解(一)

APK安裝流程詳解(一)

一.基礎(chǔ)知識

1.1 AndroidManifest理解

我們大家都知道AndroidManifest是清單文件,列舉了APK的核心信息,包括權(quán)限、元數(shù)據(jù)、四大組件、啟動模式等信息。但他只是一個xml文件,在安裝時會起什么作用呢?為了便于理解,我們看下圖:



下面我們依據(jù)上圖把涉及到的類分析一下:

1.1.1 PackageInfo

該類實現(xiàn)了Parceable接口,可以在進程間傳遞。
重要成員變量簡介:

  • public String packageName: 包名
  • public String versionName:版本名
  • public String versionCode:版本號
  • public String sharedUserId:共享用戶ID,簽名相同的情況下程序之間數(shù)據(jù)共享
  • public long firstInstallTime:第一次安裝時間,忽略之前安裝后卸載的情況單位ms
  • public long lastUpdateTime:最后更新時間,相同版本號的APK覆蓋安裝,該值也會發(fā)生變化,單位ms
  • public String[] requestedPermissions:請求的權(quán)限
  • public ApplicationInfo applicationInfo:Applicationinfo對象,下面會講解
  • public ActivityInfo[] activities:注冊的Activity
  • public ActivityInfo[] receivers:注冊的Receiver,PS:注意這里是ActivityInfo[]
  • public ServiceInfo[] services:注冊的服務(wù)
  • public ProviderInfo[] providers:注冊的Providers

我們看可以看出,該類包含了從AndroidManifest.xml中收集的所有信息。

1.1.2 PackageItemInfo

它是AndroidManifest.xml文件中所有節(jié)點的基類,提供最基本的屬性集合,如:label、icon、meta等。

1.1.3 ApplicationInfo

該類繼承自PackageItemInfo并實現(xiàn)了Parcelable接口,對應(yīng)Manifest.xml中的<application>節(jié)點里的信息

1.1.4 ActivityInfo、ServiceInfo、Provider

ActivityInfo繼承自ComponentInfo并實現(xiàn)了Parcelable接口,對應(yīng)AndroidManifest.xml里面的<activity>或者<receiver>節(jié)點里的信息,可以用來設(shè)置我們的任何屬性,包括theme、launchMode等。

ServiceInfo繼承自ComponentInfo并實現(xiàn)了Parcelable接口,它對應(yīng)manifest里面<service>節(jié)點的信息。

ProviderInfo類繼承自ComponentInfo并實現(xiàn)了Parcelable接口,對應(yīng)manifest里面的<provider>節(jié)點的信息

1.1.5 ResolveInfo

ResolveInfo就是解件intent過程返回的信息,對應(yīng)位于AndroidManifest.xml的<intent>標(biāo)簽收集到的信息。
重要成員變量簡介:

  • public ActivityInfo activityInfo:和Intent相匹配的ActivityInfo(可能是Activity或者Receiver)
  • public ServiceInfo serviceInfo:和Intent相匹配的serviceInfo
  • public ProviderInfo providerInfo:和Intent相匹配的providerInfo
  • public IntentFilter filter:匹配的IntentFilter
1.1.6PermissionInfo

顧名思義,這個類代表應(yīng)用的權(quán)限描述信息,既是權(quán)限信息的記錄,也是權(quán)限的級別保護,在Android系統(tǒng)中,做任何操作都要申請權(quán)限。使用PermissionInfo指定一個權(quán)限的基本信息時,需要指定protectedLevel和所屬的group信息。
重要的成員變量:

  • public int protectionLevel:保護權(quán)限的級別,可以是如下級別
    public static final int PROTECTION_NORMAL:表示只要是申請了就可以使用的級別。
    public static final int PROTECTION_DANGEROUS:表示在安裝時需要用戶確認才可以使用
    public static final int PROTECTION_SIGNATURE:表示使用者的APP和系統(tǒng)使用同一個證書,即系統(tǒng)權(quán)限級別
  • public String group:權(quán)限組
1.1.7類結(jié)構(gòu)

上述類的類結(jié)構(gòu)如下圖所示:


二.PackageManager

2.1PackageManager簡介

我們先來看一下注釋

/**
 * Class for retrieving various kinds of information related to the application
 * packages that are currently installed on the device.
 *
 * You can find this class through {@link Context#getPackageManager}.
 */
public abstract class PackageManager {
   ...
}

由以上可知這是一個抽象類,可以獲取已安裝APK的各種信息,你可以通過Context.getPackageManager方法來獲取這個類。

2.2PackageManager與APK安裝

2.2.1 什么是PackageManager

PackageManager是管理應(yīng)用程序安裝、卸載和升級的API。當(dāng)我們安裝APK文件時,PackageManager會解析APK包文件和顯示確認信息。當(dāng)我們點擊OK按鈕后,PackageManager會調(diào)用InstallPackage方法,PackageManager會啟動一個Service服務(wù)PackageManagerService(下文簡稱PMS),所有相關(guān)的操作都在這個service中發(fā)生。APK安裝流程如下圖:

2.2.2 PackageManager的作用是什么
  • 安裝、卸載應(yīng)用
  • 查詢permission信息(application、activity、receiver、service、provider及相應(yīng)屬性等)
  • 查詢Application相關(guān)信息
  • 查詢已安裝應(yīng)用
  • 增加、刪除permission
  • 清除用戶數(shù)據(jù)、緩存、代碼等

2.3PackageManager的具體實現(xiàn)類

我們知道PackageManager是一個抽象類,現(xiàn)在我們來看一下它的具體實現(xiàn)類。2.1小節(jié)中我們看PackageManager的注釋中,官方推薦通過Context的實現(xiàn)類ContextImpl#getPackageManager方法來獲取,查看Android源碼,發(fā)現(xiàn)返回的是ApplicationPackageManager類。

@Override
    public PackageManager getPackageManager() {
        // 第一步
        if (mPackageManager != null) {
            return mPackageManager;
        }
        // 第二步
        IPackageManager pm = ActivityThread.getPackageManager();
         // 第三步
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }
        return null;
    }
2.3.1 ApplicationPackageManager

ApplicationPackageManager中關(guān)于PackageManager的具體實現(xiàn),其實是調(diào)用IPackageManager來實現(xiàn)的。

2.3.2 IPackageManager

IPackageManager的獲取是在Context的getPackageManager方法中,調(diào)用ActivityThread#getPackageManager方法,關(guān)于ActivityThread會在后續(xù)Android系統(tǒng)啟動流程中詳細講解。

/**ActivityThread.java**/
public static IPackageManager getPackageManager() {
         //第一步
        if (sPackageManager != null) {
            return sPackageManager;
        }
        // 第二步
        IBinder b = ServiceManager.getService("package");
        
        // 第三步 
        //返回IpackageManager.Stub.Proxy
        sPackageManager = IPackageManager.Stub.asInterface(b);
       
        return sPackageManager;
    }

這個方法內(nèi)部流程大體上分三步:

  • 判斷sPackageManager是否為空,如果為空說明是第一次調(diào)用,走第二步,如果不為空,直接返回sPackageManager
  • 走到第二步,說明是第一次調(diào)用。調(diào)用ServiceManager#getService方法獲取一個IBinder對象
  • 通過調(diào)用IPackageManager.Stub.asInterface方法獲取一個sPackageManager對象

上面的代碼看著是不是有點熟悉?是不是讓你寫到了AIDL?這里涉及到了Binder知識,會在另外一個系列文章中講述。

所以我們得知在ApplicationPackageManager里面的mPM其實就是IPackageManager.Stub內(nèi)部類的Proxy對象。對應(yīng)的IPackageManager.Stub就是PackageManagerService.java,因為:

public class PackageManagerService extends IPackageManager.Stub {
   ...
}
  • PackageManager負責(zé)通信。

IPackageManager中定義了很多業(yè)務(wù)方法,但是出于安全等方面的考慮,Android SDK對外提供的是它的一個子集,該子集被封裝在抽象類PackageManager中??蛻舳艘话阃ㄟ^Context#getPackageManager方法獲取PackageManager,實際返回的是ApplicationPackageManager,ApplicationPackageManager并沒有直接參與Binder通信,而是其中一個mPM成員指向了一個IPackageManager.stub.Proxy對象

  • AIDL中的Binder服務(wù)端是PackageManagerService。PMS作為服務(wù)端參與Binder通信。

  • AIDL中的Binder客戶端是ApplicationPackageManager中成員變量mPM,mPM指向的是IPackageManager.stub.Proxy

整體Binder流程如下:

2.4形象理解

假設(shè)你在和客房商談事務(wù),要給老板打電話請示。這里,你就是應(yīng)用進程里的ApplicationPackageManager,IpackageMaanger就是你們的通信工具-電話,你的老板就是SystemServer進程里面的PackageManagerService,你的電話是IPackageManager.Stub.Proxy,老板的電話是IPackageManager.Stub。IpackageManager其實就是一個具體業(yè)務(wù)場景下的數(shù)據(jù)交換的工具而已。

三.總結(jié)

本文主要講了PackageManager和PackageManagerService的關(guān)系,PackageManagerService事實上是一個binder(繼承自IpackageManager.Stub,而Stub繼承自Binder),Client端通過獲取獲取PMS的服務(wù)代理對象IpackageManager.Stub.Proxy,通過Binder調(diào)用服務(wù)端Binder中的方法,即Stub中的接口實現(xiàn)。如下圖:


參考文章:http://www.itdecent.cn/p/a301291ca845

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容