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)。如下圖:
