APK安装流程详解(一)

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里面的或者节点里的信息,可以用来设置我们的任何属性,包括theme、launchMode等。

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

你可能感兴趣的