Android 5.0 进程A和APK B依赖关系问题的研究

(本文来自于和博客上一个朋友的聊天,但可惜我回复后一直没收到这位朋友的回答。故在此把这个问题和大家介绍下,希望能抛砖引玉)

这位朋友的问题是这样的:

应用程序A运行时跑在进程A中,它可以在运行时通过ClassLoader加载另外一个应用程序B。

当然,应用程序B也是可以运行的,它运行在进程B中。

在Android 5.0以前,进程B和进程A是没有关系。但是5.0以后,如果进程B被stop的话,进程A一样会被干掉。

这就是Android 5.0带来的进程A/B依赖关系。

这个问题有几个关键技术点:

1 进程A如何加载应用程序B。这是通过ClassLoader来完成的,主要代码如下所示

(来自这位朋友的提示:)

 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);
         } ......
}

在load的时候:

1 在Android 5.0以前,进程A和应用程序B的关系:没有显示的关系。就是普通的加载

2 在Android 5.0及以后,进程A和应用程序B的关系:显示的绑定。代码在LoadedApk.java中

-->每一个被加载的Apk都对应一个LoaderApk对象。代码在LoadedApk.java中
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, 
 CompatibilityInfo compatInfo, ClassLoader baseLoader,  
 boolean securityViolation, boolean includeCode, boolean registerPackage) { 
 final int myUid = Process.myUid(); 
 aInfo = adjustNativeLibraryPaths(aInfo); 
......
 mRegisterPackage = registerPackage; // 在这里被“绑定”了
 mDisplayAdjustments.setCompatibilityInfo(compatInfo); 
}

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 进程B(也就是Package B本身运行时所在的进程)被杀时,有依赖关系的进程A也会被干掉。这里有几个注意点:

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名, 签名都一致才可以。

时间: 2024-11-03 21:53:03

Android 5.0 进程A和APK B依赖关系问题的研究的相关文章

android studio2.0 搭建Robotium环境--apk测试没有混淆只有签名

1.配置好android sdk ,java环境 2.重新签名apk文件 在用户目录下,会有一个.android的目录,把re-sign.jar放在该目录下.执行命令 java -jar re-sign.jar 即可 再把apk文件脱到打开的re-sign上.保存重新签名后的文件.     遇到问题:提示sdk\tools\zipalign.exe没有这个文件.解决:拷贝一份到这个目录下 3.将生成的debug文件安装到夜神模拟器中 adb connect 127.0.0.1:62001adb

Android 8.0+ 更新安装apk失败的问题

最近做项目发现Android 8.0+ 更新安装apk时 出现安装失败的情况  总结原因是 缺少安装的权限 Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用.在应用权限设置的"特殊访问权限"中,加入了"安装其他应用"的设置. 简单的方法  可以直接在Manifest.xml中加入下面的权限:(亲测可用) <uses-permissionandroid:name="android.permission.REQU

【译】Android 6.0 Changes (机翻加轻微人工校对)

Android 6.0 Changes In this document Runtime Permissions Doze and App Standby Apache HTTP Client Removal BoringSSL Access to Hardware Identifiers Notifications AudioManager Changes Text Selection Browser Bookmark Changes Android Keystore Changes Wi-F

Android获得全局进程信息以及进程使用的内存情况

Android获得全部进程信息,并获得该进程使用的内存情况. package zhangphil.process; import java.util.List; import android.os.Bundle; import android.os.Debug.MemoryInfo; import android.widget.TextView; import android.app.Activity; import android.app.ActivityManager; import and

【译】Android 7.0 for Developers

译者注: 译者:aroundme 原文地址:https://developer.android.com/about/versions/nougat/android-7.0.html 主要是介绍Android 7.0提供新特性. 翻译的动机主要是为了适配Android 7.0,提前踩点.防止大坑. 就翻译来看,除去一些可有可无的更新之外,关注点主要是集中在四点: * 通知栏一系列更新 * 对于应用后台优化(或者说限制) * WebView持续性更新(混合开发需要注意) * 对于GPU的优化,优化3

Android之——获取进程总数、内存、任务列表

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47263863 如今,基于Android平台的应用越来越多,不乏这样一些应用程序,这些应用可以多手机中的进程,内存和任务列表进行管理.Android系统中没有自带的应用程序对这些数据进行管理.大家不禁会说,Android的应用设置里面有这些功能啊!是的,虽然应用设置里面有,但是我们如果想看一下系统的进程,还要跑到系统设置里面去看吗?这样是不是很麻烦?是不是很挫呢?那获取Androi

Android 5.0 源代码结构

本节书摘来自异步社区<深入理解Android 5 源代码>一书中的第2章,第2.2节分析Android源代码结构,作者 李骏. 网址:https://yq.aliyun.com/articles/93279?spm=5176.100239.blogcont93310.17.gtBsUg 2.2 分析Android源代码结构 获得Android 5.0源代码后,源代码的全部工程分为以下3个部分. Core Project:核心工程部分,这是建立Android系统的基础,被保存在根目录的各个文件夹

Android 7.0行为变化—开发者应该关注的(官网同步翻译)

Android 7.0行为变化-开发者应该关注的(官网同步翻译) 版权声明:转载必须注明本文转自严振杰的博客: http://blog.yanzhenjie.com 如果想了解更多Android7.0的内容,可以顺便再看看Android7.0写给开发者的一封信(官网同步翻译). 如果你的引文够好,推荐你阅读官网文章: Android 7.0 Behavior Changes Android N 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍你应该了解并在开发应用

Android 6.0 动态权限申请注意事项

<span style="font-size:24px;color:#ffff00;background-color: rgb(0, 0, 153);"><strong>Android 6.0 权限区分</strong></span> Android 6.0 为了保护用户隐私,将一些权限的申请放在了应用运行的时候去申请, 比如以往的开发中,开发人员只需要将需要的权限在清单文件中配置即可,安装后用户可以在设置中的应用信息中看到:XX应用以获