Android PackageManagerService和ClassLoader

PackageManagerService(PMS)是用来获取apk包信息的,AMS总是会使用PMS加载包信息,将其封装在LoadedApk类对象中,然后就可以从中取出AndroidManifest声明的四大组件信息了,在下载并安装App的过程中,会把apk存放在data/app目录下。

App安装流程

Android系统使用PMS解析这个apk中的AndroidManifest文件,包括:

分配用户ID和用户组id,用户id是唯一的,因为android是一个Liunx系统,用户组id指的是各种权限,每个权限都在一个分组中,比如读写sd卡或网络访问权限,分配哪些用户组id,就拥有哪些权限。

在Launcher生成一个icon,icon中保存着默认启动的Activity信息,

在App安装过程的最后,把保默认的Activity信息记录在xml文件中,以备下次安装时再次使用,android系统每次重启的时候都会把apk重新安装一遍,一共分为4个步骤

①因为结束安装的时候,都会把信息保存在xml中,所以android系统再次启动的时,会重新安装所有的apk,就可以直接读取之前保存的xml文件了

②从data/private受DRM保护的app、data/app用户安装的app、system/framework资源型app,用于打包、system/app系统自带app、vender/app设备厂商提供的app

③④和单独安装一个app是一致的

Android系统重启后,会重新安装所有的app,这是由PMS完成的,App首次安装到手机上,也是由PMS完成的,PMS是系统进程,是我们不能hook的。

PMS中有个类对我们App开发来说很重要,那就是PackageParser,它是专门用来解析AndriodManifest文件的,以获得四大组件的信息以及用户权限。

PackageParser类中,有一个parsePackage方法,接受一个apkFile的参数,既可以是当前apk文件,也可以是外部apk文件,我们可以使用这个类,来读取插件apk的AndroidManifest文件中的信息,但是PackageParser是隐藏的不对app开发人员开放,我们只能通过反射hook此类。

parsePackage方法返回的是Package类型的实体对象,里面存储着四大组件的信息,但Package类我获取不到,取而代之的是PackageParser类的generatePackageInfo方法,把Package类型转化为PackageInfo类型,在插件化编程中,我们反射PackageParser,一般是用来获取插件AndroidManifest中的四大组件信息。

ClassLoader

Android插件化能从外部下载一个apk插件,就在于classLaoder,classLoader是一个家族,ClassLader是老祖先,它有很多子孙,看下图

其中最重要的是PathClassLoader和DexClassLoader,以及父类BaseDexClassLoader.

这两个类的构造参数optimizedDirectory的值不一样,PathClassLoader把这个参数设置为null,DexClassLoader把这个参数设置为非空,optimizedDirectory是用来缓存我们需要加载的dex文件的,并创建一个DexFile对象,如果它为null,那么直接使用dex文件原有的路径来创建DexFile对象。

DexClassLoader可以指定自己的optimizedDirectory,所以它可以加载外部dex,因为这个dex会被复制到内部路径的optimizedDirectory,而PathClassLoader没有optimizedDirectory,所以只能加载内部dex,这些大都是存在于系统中已经安装过的apk里面的。

对于App而言,Apk文件有一个classes.dex文件,那么这个dex文件就是apk的主dex,是通过PathClassLoader加载的

在App的Activity中,通过getClassLoader获取到的事PathClassLoader,它的父类是BootClassLoader,对于插件化而言,有一种方案是将App的ClassLoader替换为自定义的ClassLoader,这样就要求自定义ClassLoader模拟双亲委托机制。

MultiDex

MultiDex是谷歌退出的,为了解决65536的问题的,原理就是把原来一个Dex文件拆分为多个dex文件,每个dex文件的方法不超过65536

classes.dex称为主dex,由app使用PathClassLoader进行加载,而classes2.dex和classes3.dex,这些子dex,会在app启动后使用DexClassLoader进行加载。

 

发布了15 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qinggancha/article/details/103540089