转载请注明出处:http://blog.youkuaiyun.com/ximsfei/article/details/50886134
github地址:https://github.com/ximsfei/DynamicDeploymentApk
在上一篇文章:Android动态部署:Google原生Split APK浅析中,简单描述了Google实现SplitApk的机制。
接下来我们就开始一步步的实践,自己手动实现非安装apk的动态加载。
首先来了解一下APK解析安装的源码:
我们可以通过adb命令来安装apk到Android手机中:
1. adb push xxx /data/app
此处/data/app第三方应用的安装目录,还可以为/system/app:系统应用,/vendor/app:方案商应用等。
2. adb install xxx
3. adb shell pm install yyy
其中adb push命令需要重启手机才能安装成功,xxx为宿主电脑中的apk路径,yyy则为Android手机中的路径
使用adb push 安装apk
源码解析:通过adb push命令将APK放到/data/app目录,手机重启后,会在PackageManagerService的构造方法中解析该apk,至于PackageManagerService这个类的构造方法何时调用,大家可以看看Android framework的启动源码,这里只需要知道,在Android启动后,SystemServer类中会调用PackageManagerService中的main方法。
SystemServer.java
private void startBootstrapServices() {
...
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...
}
PackageManagerService.java
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
调用ServiceManager的addService方法可能会引起PERMISSION DENIED问题:浅谈android add_service PERMISSION DENIED问题
下图为手机启动后PackageManagerService app解析的时序图,其中红色标注的为我们在研究过程需要关注的点:
- PackageParser.java中的new AssetManager & new Resources
我们可以根据APK的绝对路径,及Host APK的Resources初始化一个插件APK的Resources对象
AssetManager assets = AssetManager.class.newInstance();
Reflect.create().setClass(AssetManager.class)
.setMethod("addAssetPath", String