0%

Android-Activity启动过程

代理方式

1.代理方式插件化实现

未安装的 APK文件是可以通过 DexClassLoader 来加载、运行的

1
2
3
4
private DexClassLoader createDexClassloader(String apkPath) {
File file = mContext.getDir("dex",Context.MODE_PRIVATE);
return new DexClassLoader(apkPath,file.getAbsolutePath(),null,mContext.getClassLoader());
}

其中 :
1、mContext 是一个 Context类型的对象。
2、apkPath 就是 apk 在手机中的绝对路径(示例中是从 assets 中复制到手机中的)。 3、file.getAbsolutePath() 就是 APK 解压出的 dex 的存放目录。

这里返回的 loader 就是一个可以加载 APK 的 ClassLoader。然后通过 ClassLoader 加载这个 APK 的默认启动的 Activity,并且通过反射调用这个插件 Activity 的 onCreate,onStart,onResume 函数就可以加载这个应用。

资源加载

资源的加载需要 Resouces ,而创建 Resouces 需要 AssetManager,因此,先创建 AssetManager,再创建 Resouces.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private AssetManager createAssetManager(String apkPath) {
AssetManager am = null;
try {
//反射构造 AssetManager
am = AssetManager.class.newInstance();
Method method = AssetManager.class.getDeclaredMethod("addAssetPath",String.class);
//通过反射 将 apk 的目录添加到 AssetManager 的资源路径下
method.invoke(am,apkPath);
return am;

} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return am;

}

2.Hook方式实现

Hook目的是替换掉系统默认逻辑

Activity 启动过程

插件化支持首先要解决的一点就是插件里的 Activity 并未在宿主程序的 AndroidMainfest.xml 注册。常规方法肯定无法直接启动插件的 Activity,这个时候就需要去了解 Activity 的启动流程。

流程

Activity 调用 startActivity,实际会调用 Instrumentation 类的 execStartActivity 方法,
Instrumentation 是系统用来监控 Activity 运行的一个类,

1.Activity 调用 startActivity,实际会调用 Instrumentation 类的 execStartActivity 方法,Instrumentation 是系统用来监控 Activity 运行的一个类,Activity 的整个生命周期都有它的影子。
2.通过跨进程的 Binder 调用,进入到 ActivityManagerService 中,其内部会处理 Activity 栈。之后又通过跨进程调用进入到需要调用的 Activity 所在的进程中。
3.ApplicationThread 是一个 Binder 对象,其运行在 Binder 线程池中,内部包含一个 H 类,该类继承于类 Handler。ApplicationThread 将启动需要调用的 Activity 的信息通过 H 对象发送给主线程。
4.主线程拿到需要调用的 Activity 的信息后,调用 Instrumentation 类的 newActivity 方法,其内通过 ClassLoader 创建 Activity 实例。