在宿主调用 startActivity(pluginActivity)的时候,通过Hook 告诉AMS 启动的是 SubActivity,因为 AMS 认识这个SubActivity,然后在AMS 通知启动 放入SubActivity 中保存起来 ,那么再 AMS 通知启动 SubActivity回来的时候,我们再从SubActivity取出真正要开启realActivity。 在宿主中的androidmainfest添加一个傀儡SubActivity<activity android:name="com.example.myapplication.<em>SubActivity</em>"/> 的时候,换成启动 SubActivity内中的readActivity当AMS 告诉应用进程启动SubActivity的时候会经过应用进程的ActivityThread 里面的Handle 类H ,这个 最开始我们hook 欺骗AMS,启动subactivity ,那么 AMS的 mActivitys,它的其中一个 token key 对应的是 subactivity 。
名字为“shy.luo.task.subactivity”的Actvity实现在src/shy/luo/task/SubActivity.java文件中: package shy.luo.task; : 现在,我们如何来确认SubActivity是不是在新的任务中启动并且位于这个新任务的堆栈底部呢? 和MainActivity都是运行在TaskRecord#3中,并且SubActivity在MainActivity的上面。 要在新的任务中启动,但是别急,还要看看其它条件是否满足,如果条件都满足,才可以在新的任务中启动这个SubActivity。 在这个例子中,就是要在属性值affinity等于”shy.luo.task”的任务中看看是否存在SubActivity类型的实例,如果有,就把它上面的Activity都结束掉。
Example: MainActivity, SubActivity, Person MainActivity package com.learn; import android.app.Activity Parcelable Log.d(TAG, "mPerson=" + mPerson); Intent intent = new Intent(this, SubActivity.class bundle); startActivity(intent); Log.d(TAG, "startActivity"); } } } SubActivity import android.os.Parcelable; import android.util.Log; import android.widget.TextView; public class SubActivity 487): writeToParcel(Parcel dest, int flags) D/Parcelable( 487): startActivity D/Parcelable( 487): SubActivity
在AndroidManifest.xml中注册SubActivity,如下所示。 AndroidManifest.xml <?xml version="1.0" encoding="utf-8"? 2.2 使用占坑Activity通过AMS验证 为了防止报错,需要将启动的TargetActivity替换为SubActivity,用SubActivity来通过AMS的验证。 ,同时Log中打印了"hook成功",说明我们已经成功用SubActivity通过了AMS的校验。 前面的例子我们用SubActivity替换了TargetActivity通过了AMS的校验,这样AMS只知道SubActivity的存在,那么AMS是如何能控制TargetActivity生命周期的回调的 首先我们自定义一个Instrumentation,在execStartActivity方法中将启动的TargetActivity替换为SubActivity,如下所示。
::class.java)) } } } SubActivity中创建子组件,并注入 class SubActivity : AppCompatActivity() { singleton hashcode: ${singleton.hashCode()}") Log.i("aruba_log", "SubActivity subObject1 hashcode : ${subObject1.hashCode()}") Log.i("aruba_log", "SubActivity subObject2 hashcode: ${subObject2 singleton hashcode: 127836367 2021-12-04/com.aruba.daggerapplication I/aruba_log: SubActivity subObject1 hashcode: 44284508 2021-12-04/com.aruba.daggerapplication I/aruba_log: SubActivity subObject2 hashcode
下面的代码显示了如何启动一个子Activity: private static final int SHOW_SUBACTIVITY = 1; Intent intent = new Intent(this , MyOtherActivity.class); startActivityForResult(intent, SHOW_SUBACTIVITY); 和正常的Activity一样,子Activity可以隐式或显式启动 下面的框架代码使用一个隐式的Intent来启动一个新的子Activity来挑选一个联系人: private static final int PICK_CONTACT_SUBACTIVITY = 2; ); Intent intent = new Intent(Intent.ACTION_PICK, uri); startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY
下面的框架代码使用一个隐式的Intent来启动一个新的子Activity来挑选一个联系人: private static final int PICK_CONTACT_SUBACTIVITY = 2; ); Intent intent = new Intent(Intent.ACTION_PICK, uri); startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY
LAUNCH_ACTIVITY) { Object r = msg.obj; try { //得到消息中的Intent(启动SubActivity Intent target = intent.getParcelableExtra(HookHelper.TARGET_INTENT); //将启动SubActivity execStartActivity方法来激活Activity的生命周期,所以可以通过替换Instrumentation来完成,然后在Instrumentation的execStartActivity方法中用占坑SubActivity
: const/16 v0, 0xa :try_start_0 # try 块开始 invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity :try_end_0} :catch_0 :goto_0 invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity;->callAnotherMethod : const/16 v0, 0xa :try_start_0 # try 块开始 invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity ; const/16 v0, 0xa :try_start_0 # try 块开始 invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity catchall_0 const/4 v0, 0x0 # 复制一份到外面 :goto_0 invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity
} } } 不过还有一个问题,主项目启动插件Activity的时候,我们可以替换Activity,但是如果在插件Activity(比如MainActivity)启动另一个Activity(SubActivity
这会使启动SubActivity的时间至少延长了142ms。而这个Handler是App自己的Handler。
这会使启动SubActivity的时间至少延长了142ms。而这个Handler是App自己的Handler。
return true; } //点击”安装“,跳转 InstallInstalling - 开始安装 private void startInstall() { // Start subactivity
startInstall()方法解析 代码在PackageInstallerActivity.java 683行 private void startInstall() { // Start subactivity