欢迎光临散文网 会员登陆 & 注册

AOSP Intent.getExtras的一个坑

2022-02-18 21:41 作者:OMGCA  | 我要投稿


注:非AOSP原生代码已做脱敏处理


工作中做了一个需求,其中一部分是想把系统进程里读到的一些数据,在应用进程启动Activity的时候去读取。

大致流程是通过自定义接口读到数据后传入ActivityOptions,然后通过ActivityOptions在ActivityThread里传给ActivityRecord里的Intent。通过AOSP的Intent.putExtras()放数据,应用进程启动时通过Intent.getExtras()读取。具体实现如下:

  1.  ActivityStarter

    AOSP代码地址:https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/wm/ActivityStarter.java

    Activity启动时通过execute()函数走到executeRequest()函数,入参Request类可以获得Activity启动的一些信息request.activityOptions。

options变量初始化

Activity的启动通过startActivityUnchecked,其中第一个参数r为ActivityRecord对象

startActivityUnchecked的调用

r初始化过程中将checkedOptions作为入参设置为ActivityOptions

于是在初始化之前通过我的自定义接口返回带有我自己数据的ActivityOptions

在https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/wm/ActivityStarter.java中加入接口调用

在启动Activity的时候,核心代码是ActivityThread中的performLaunchActivity()方法

performLaunchActivity将ActivityStarter中的ActivityRecord作为入参,中间转换成了ActivityClientRecord

在大致3230行处,我试图通过之前的ActivityOptions读到数据

但是运行App时获得报错,报错栈如下:

在intent.getExtras()报了ClassNotFoundException,猜测原因是App将自定义类的数据也放入了intent的mExtra中,但默认ClassLoader不知道这个类,在intent.getExtras()时的反序列化报错。但是这说不通,因为App本身是一定会知道自定义类的定义的,但在这里却不知道了。后来继续看performLaunchActivity的实现发现:

performLaunchActivity本身会去加载App的ClassLoader

performLaunchActivity会获得App的ClassLoader并设置为mExtra的ClassLoader

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/Intent.java

所以精简过程为:intent.getExtras()返回的mExtras是一个Bundle类,Bundle类的初始化需要对里面的所有数据反序列化。App塞入了一个自定义的类在intent的mExtras里,但我们在获取mExtras的时候时机过早,Bundle还在使用系统默认的ClassLoader而获取不到相关自定义类的信息,导致ClassNotFoundException。而performLaunchActivity中会给mExtras做加载App的ClassLoader的操作。所以将代码后移即可解决问题。这个想法也通过issuetracker得到了证实:

https://issuetracker.google.com/issues/37053389

代码后移


AOSP Intent.getExtras的一个坑的评论 (共 条)

分享到微博请遵守国家法律