APK安装流程详解(一)
一.基础知识
1.1 AndroidManifest理解
我们大家都知道AndroidManifest是清单文件,列举了APK的核心信息,包括权限、元数据、四大组件、启动模式等信息。但他只是一个xml文件,在安装时会起什么作用呢?为了便于理解,我们看下图:
下面我们依据上图把涉及到的类分析一下:
1.1.1 PackageInfo
该类实现了Parceable接口,可以在进程间传递。
重要成员变量简介:
- public String packageName: 包名
- public String versionName:版本名
- public String versionCode:版本号
- public String sharedUserId:共享用户ID,签名相同的情况下程序之间数据共享
- public long firstInstallTime:第一次安装时间,忽略之前安装后卸载的情况单位ms
- public long lastUpdateTime:最后更新时间,相同版本号的APK覆盖安装,该值也会发生变化,单位ms
- public String[] requestedPermissions:请求的权限
- public ApplicationInfo applicationInfo:Applicationinfo对象,下面会讲解
- public ActivityInfo[] activities:注册的Activity
- public ActivityInfo[] receivers:注册的Receiver,PS:注意这里是ActivityInfo[]
- public ServiceInfo[] services:注册的服务
- public ProviderInfo[] providers:注册的Providers
我们看可以看出,该类包含了从AndroidManifest.xml中收集的所有信息。
1.1.2 PackageItemInfo
它是AndroidManifest.xml文件中所有节点的基类,提供最基本的属性集合,如:label、icon、meta等。
1.1.3 ApplicationInfo
该类继承自PackageItemInfo并实现了Parcelable接口,对应Manifest.xml中的
1.1.4 ActivityInfo、ServiceInfo、Provider
ActivityInfo继承自ComponentInfo并实现了Parcelable接口,对应AndroidManifest.xml里面的
ServiceInfo继承自ComponentInfo并实现了Parcelable接口,它对应manifest里面
ProviderInfo类继承自ComponentInfo并实现了Parcelable接口,对应manifest里面的
1.1.5 ResolveInfo
ResolveInfo就是解件intent过程返回的信息,对应位于AndroidManifest.xml的
重要成员变量简介:
- public ActivityInfo activityInfo:和Intent相匹配的ActivityInfo(可能是Activity或者Receiver)
- public ServiceInfo serviceInfo:和Intent相匹配的serviceInfo
- public ProviderInfo providerInfo:和Intent相匹配的providerInfo
- public IntentFilter filter:匹配的IntentFilter
1.1.6PermissionInfo
顾名思义,这个类代表应用的权限描述信息,既是权限信息的记录,也是权限的级别保护,在Android系统中,做任何操作都要申请权限。使用PermissionInfo指定一个权限的基本信息时,需要指定protectedLevel和所属的group信息。
重要的成员变量:
- public int protectionLevel:保护权限的级别,可以是如下级别
public static final int PROTECTION_NORMAL:表示只要是申请了就可以使用的级别。
public static final int PROTECTION_DANGEROUS:表示在安装时需要用户确认才可以使用
public static final int PROTECTION_SIGNATURE:表示使用者的APP和系统使用同一个证书,即系统权限级别- public String group:权限组
1.1.7类结构
上述类的类结构如下图所示:
二.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是管理应用程序安装、卸载和升级的API。当我们安装APK文件时,PackageManager会解析APK包文件和显示确认信息。当我们点击OK按钮后,PackageManager会调用InstallPackage方法,PackageManager会启动一个Service服务PackageManagerService(下文简称PMS),所有相关的操作都在这个service中发生。APK安装流程如下图:
2.2.2 PackageManager的作用是什么
- 安装、卸载应用
- 查询permission信息(application、activity、receiver、service、provider及相应属性等)
- 查询Application相关信息
- 查询已安装应用
- 增加、删除permission
- 清除用户数据、缓存、代码等
2.3PackageManager的具体实现类
我们知道PackageManager是一个抽象类,现在我们来看一下它的具体实现类。2.1小节中我们看PackageManager的注释中,官方推荐通过Context的实现类ContextImpl#getPackageManager方法来获取,查看Android源码,发现返回的是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中关于PackageManager的具体实现,其实是调用IPackageManager来实现的。
2.3.2 IPackageManager
IPackageManager的获取是在Context的getPackageManager方法中,调用ActivityThread#getPackageManager方法,关于ActivityThread会在后续Android系统启动流程中详细讲解。
/**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;
}
这个方法内部流程大体上分三步:
- 判断sPackageManager是否为空,如果为空说明是第一次调用,走第二步,如果不为空,直接返回sPackageManager
- 走到第二步,说明是第一次调用。调用ServiceManager#getService方法获取一个IBinder对象
- 通过调用IPackageManager.Stub.asInterface方法获取一个sPackageManager对象
上面的代码看着是不是有点熟悉?是不是让你写到了AIDL?这里涉及到了Binder知识,会在另外一个系列文章中讲述。
所以我们得知在ApplicationPackageManager里面的mPM其实就是IPackageManager.Stub内部类的Proxy对象。对应的IPackageManager.Stub就是PackageManagerService.java,因为:
public class PackageManagerService extends IPackageManager.Stub {
...
}
- PackageManager负责通信。
IPackageManager中定义了很多业务方法,但是出于安全等方面的考虑,Android SDK对外提供的是它的一个子集,该子集被封装在抽象类PackageManager中。客户端一般通过Context#getPackageManager方法获取PackageManager,实际返回的是ApplicationPackageManager,ApplicationPackageManager并没有直接参与Binder通信,而是其中一个mPM成员指向了一个IPackageManager.stub.Proxy对象
AIDL中的Binder服务端是PackageManagerService。PMS作为服务端参与Binder通信。
AIDL中的Binder客户端是ApplicationPackageManager中成员变量mPM,mPM指向的是IPackageManager.stub.Proxy
整体Binder流程如下:
2.4形象理解
假设你在和客房商谈事务,要给老板打电话请示。这里,你就是应用进程里的ApplicationPackageManager,IpackageMaanger就是你们的通信工具-电话,你的老板就是SystemServer进程里面的PackageManagerService,你的电话是IPackageManager.Stub.Proxy,老板的电话是IPackageManager.Stub。IpackageManager其实就是一个具体业务场景下的数据交换的工具而已。
三.总结
本文主要讲了PackageManager和PackageManagerService的关系,PackageManagerService事实上是一个binder(继承自IpackageManager.Stub,而Stub继承自Binder),Client端通过获取获取PMS的服务代理对象IpackageManager.Stub.Proxy,通过Binder调用服务端Binder中的方法,即Stub中的接口实现。如下图:
参考文章:http://www.jianshu.com/p/a301291ca845