标签:
(本文来自于和博客上一个朋友的聊天,但可惜我回复后一直没收到这位朋友的回答。故在此把这个问题和大家介绍下,希望能抛砖引玉)
这位朋友的问题是这样的:
private static Class<?> loadPluginClass(Context launcherContext, String packageName, String className, int type) { try { Context context = launcherContext.createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); final String apkPath = context.getApplicationInfo().sourceDir; PathClassLoader l = new PathClassLoader(apkPath, context.getClassLoader()); return l.loadClass(className); } ...... }
Android 5.0之后为什么会这样呢?进程A和APK B这种依赖关系有什么用呢?
原来,Android 5.0之后:
1 当进程A加载一个package的时候,framework将调用ActivityManagerService的addPackageDependency
这个函数将把进程A和APK B(也就是Package B)绑定到一起去
这个函数在哪里调用的呢?也在LoadedApk.java中:
public ClassLoader getClassLoader() { synchronized (this) { if (mClassLoader != null) { return mClassLoader; } if (mIncludeCode && !mPackageName.equals("android")) { ...... if (mRegisterPackage) { try { ActivityManagerNative.getDefault().addPackageDependency(mPackageName); } catch (RemoteException e) { } }
2.1 如果进程B是自己crash或者被shell kill掉,那么依赖关系不会影响进程A
2.2 如果进程B是被调用killBackgroundProcess或者forceStopPackage的话,由于ActivityManagerService真正调用的是killPackageProcessesLocked
那么依赖关系会导致A被干掉。 从设计角度来看,这本身也是对的,因为APK B运行在自己的进程B,同时也被加载到进程A去运行。
kill package B的时候就应该stop进程B和A。
当然,由于5.0之前google没有考虑这么细,所以没有处理这个问题。
当然,这种依赖关系的引入还有一个原因是Android 5.0在应用程序安装方面的一些新的特性:
1 以前的apk文件 side load到/daa/app等监控目录下不会导致PacakgeManagerService去安装它们。而是需要等到下次重启扫描后,系统才会扫描并安装它们
2 adb install安装的APK,在/data/app目录下会创建一个Package-name(比如com.google.xxx)的文件夹,而apk文件被放到这个package-name目录下,改名叫base.apk
这么搞的目的是因为:Android终于支持一个进程可以加载多个APK了(当然以前也可以,但现在安装的时候,base-apk是主要逻辑,以后升级了,或者添加新的功能,就不需要重新安装新的base,而是安装一个额外的新apk,这个新apk会被加载到base的那个进程里。)这个功能在SDK文档中已经有展示,但是内容不是很详细
总之,base apk和新apk需要package名, 签名都一致才可以。
Android 5.0 进程A和APK B依赖关系问题的研究
标签:
原文地址:http://blog.csdn.net/innost/article/details/43899041