Android 插件化系列文章目录
【Android 插件化】插件化简介 ( 组件化与插件化 )
【Android 插件化】插件化原理 ( JVM 内存数据 | 类加载流程 )
【Android 插件化】插件化原理 ( 类加载器 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 获取插件入口 Activity 组件 | 加载插件 Resources 资源 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 运行应用 | 代码整理 )
【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )
【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动过程 | 静态代理 )
【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )
【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )
【Android 插件化】Hook 插件化框架 ( hook 插件化原理 | 插件包管理 )
【Android 插件化】Hook 插件化框架 ( 通过反射获取 “插件包“ 中的 Element[] dexElements )
【Android 插件化】Hook 插件化框架 ( 通过反射获取 “宿主“ 应用中的 Element[] dexElements )
【Android 插件化】Hook 插件化框架 ( 合并 “插件包“ 与 “宿主“ 中的 Element[] dexElements | 设置合并后的 Element[] 数组 )
【Android 插件化】Hook 插件化框架 ( 创建插件应用 | 拷贝插件 APK | 初始化插件包 | 测试插件 DEX 字节码 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 反射获取 IActivityManager 对象 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | AMS 启动前使用动态代理替换掉插件 Activity 类 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )
文章目录
- Android 插件化系列文章目录
- 一、插件包 Activity 启动原理
- 二、分析主线程中创建 Activity 实例源码
-
- 1、LaunchActivityItem
- 2、ActivityThread
- 三、使用 Hook 技术在主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件
-
- 1、反射获取 ActivityThread 类
- 2、反射获取 ActivityThread 单例对象
- 3、反射获取 mH 字段
- 4、反射获取 mH 对象
- 5、反射获取 Handler 中的 mCallback 字段
- 6、通过反射替换 Handler 中的 mCallback 成员
- 7、完整代码示例
- 四、用于替换 ActivityThread 中 mH 中的 mCallback 静态代理类
-
- 1、获取 ClientTransaction 类
- 2、验证 msg.obj 类型是否合法
- 3、反射获取 mActivityCallbacks 字段
- 4、反射获取 mActivityCallbacks 成员对象
- 5、使用插件 Activity 对应的 Intent 替换 LaunchActivityItem 类中的 mIntent 字段
- 6、完整代码示例
- 五、Hook Activity 启动流程涉及的完整代码
- 六、博客资源
一、插件包 Activity 启动原理
使用动态代理 , 替换 android.app.ActivityManager 中的 private static final Singleton IActivityManagerSingleton 成员的 mInstance 成员 ;
注意 : 该操作一定要在 AMS 启动之前将原来的 Intent 替换掉 , 使用占坑的 Activity 替换插件包中的 Activity , 之后 AMS 执行完毕 , 执行到主线程 实例化 Activity 对象之前 , 还要替换回去 ;
插件包组件启动方式 : 使用 Intent 启动插件包时 , 一般都使用隐式启动 ; 调用 Intent 的 setComponent , 通过包名和类名创建 Component , 这样操作 , 即使没有获得 Activity 引用 , 也不会报错
该插件包中的 Activity 没有在 “宿主” 应用中注册 , 因此启动报错 ;
AMS 会干掉没有注册过的 Activity , 这里先 在启动 AMS 之前 , 设置一个已经 注册过的 占坑 Activity ( StubActivity ) 执行启动流程 , 在主线程生成 Activity 实例对象时 , 还需要恢复插件包中的 Activity
二、分析主线程中创建 Activity 实例源码
1、LaunchActivityItem
ActivityManagerService 执行 Activity 启动 , 执行了一系列的操作后 , 需要在主线程中进行实例化 , 这些操作暂时不管 , 与 Hook 无关 , 直接开始分析 主线程中的 Activity 实例化操作 ;
Activity 实例化的起点 , 从 LaunchActivityItem 源码开始分析 ;
LaunchActivityItem 类 , 继承了 ClientTransactionItem 类 ;
该类中重写了 execute 方法 , 其中调用了 client.handleLaunchActivity 方法 , 就是调用的 ActivityThread 的 handleLaunchActivity 方法 ;
代码语言:javascript复制public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
源码路径 : /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
2、ActivityThread
ActivityThread 中的 handleLaunchActivity 方法中调用了 performLaunchActivity ,
在 performLaunchActivity 方法中 , 进行了 Activity 的实例化操作 ;
代码语言:javascript复制 activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
在 class H extends Handler 类中 , 处理 EXECUTE_TRANSACTION 信号时 , 启动了 LaunchActivityItem 的 execute 方法 , 进而调用 ActivityThread 中的 handleLaunchActivity 方法 , 创建 Activity 实例对象 ;
这里劫持该 Handler , 将插件包 Activity 替换到原来的 Activity 中 ;
ActivityThread 的相关源码 :
代码语言:javascript复制public final class ActivityThread extends ClientTransactionHandler {
final H mH = new H();
/** Reference to singleton {@link ActivityThread} */
private static volatile ActivityThread sCurrentActivityThread;
class H extends Handler {
public static final int EXECUTE_TRANSACTION = 159;
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " codeToString(msg.what));
switch (msg.what) {
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
}
}
}
/**
* Extended implementation of activity launch. Used when server requests a launch or relaunch.
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " r);
// Initialize before creating the activity
if (!ThreadedRenderer.sRendererDisabled) {
GraphicsEnvironment.earlyInitEGL();
}
WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " component
": " e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " r);
if (localLOGV) Slog.v(
TAG, r ": app=" app
", appName=" app.getPackageName()
", pkg=" r.packageInfo.getPackageName()
", comp=" r.intent.getComponent().toShortString()
", dir=" r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
r.activityInfo.name " with config " config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " r.intent.getComponent().toShortString()
" did not call through to super.onCreate()");
}
r.activity = activity;
}
r.setState(ON_CREATE);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " component
": " e.toString(), e);
}
}
return activity;
}
}
源码路径 : /frameworks/base/core/java/android/app/ActivityThread.java
三、使用 Hook 技术在主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件
1、反射获取 ActivityThread 类
代码语言:javascript复制 // 反射获取 ActivityThread 类
Class<?> activityThreadClass = null;
try {
activityThreadClass = Class.forName("android.app.ActivityThread");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2、反射获取 ActivityThread 单例对象
代码语言:javascript复制 // Activity Thread 是一个单例 , 内部的单例成员是
// private static volatile ActivityThread sCurrentActivityThread;
// 可以直接通过 ActivityThread 类 , 获取该单例对象
// 这也是 Hook 点优先找静态变量的原因 , 静态变量对象容易拿到 , 通过反射即可获取 , 不涉及系统源码相关操作
Field sCurrentActivityThreadField = null;
try {
sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
// 反射获取的字段一般都要设置可见性
sCurrentActivityThreadField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 获取类的静态变量 , 使用 字段.get(null) 即可
Object activityThreadObject = null;
try {
activityThreadObject = sCurrentActivityThreadField.get(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
3、反射获取 mH 字段
代码语言:javascript复制 // 获取 Activity Thread 中的 final H mH = new H() 成员字段 ;
Field mHField = null;
try {
mHField = activityThreadClass.getDeclaredField("mH");
// 设置该字段的可见性
mHField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
4、反射获取 mH 对象
代码语言:javascript复制 // 通过反射获取 Activity Thread 中的 final H mH = new H() 成员实例对象
Handler mHObject = null;
try {
mHObject = (Handler) mHField.get(activityThreadObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
5、反射获取 Handler 中的 mCallback 字段
代码语言:javascript复制 Class<?> handlerClass = null;
try {
handlerClass = Class.forName("android.os.Handler");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 通过反射获取 final H mH = new H() 成员的 mCallback 成员字段
// Handler 中有成员变量 final Callback mCallback;
Field mCallbackField = null;
try {
//mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField = mHObject.getClass().getDeclaredField("mCallback");
// 设置字段的可见性
mCallbackField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
6、通过反射替换 Handler 中的 mCallback 成员
代码语言:javascript复制 // 使用静态代理类 HandlerProxy , 替换 final H mH = new H() 成员实例对象中的 mCallback 成员
HandlerProxy proxy = new HandlerProxy();
try {
Log.i(TAG, "mCallbackField : " mCallbackField " , mHObject : " mHObject " , proxy : " proxy);
mCallbackField.set(mHObject, proxy);
} catch (Exception e) {
e.printStackTrace();
}
7、完整代码示例
代码语言:javascript复制 /**
* 劫持 Activity Thread 的 final H mH = new H(); 成员
* 该成员类型是 class H extends Handler ;
* @param context
*/
public static void hookActivityThread(Context context) {
// 反射获取 ActivityThread 类
Class<?> activityThreadClass = null;
try {
activityThreadClass = Class.forName("android.app.ActivityThread");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// Activity Thread 是一个单例 , 内部的单例成员是
// private static volatile ActivityThread sCurrentActivityThread;
// 可以直接通过 ActivityThread 类 , 获取该单例对象
// 这也是 Hook 点优先找静态变量的原因 , 静态变量对象容易拿到 , 通过反射即可获取 , 不涉及系统源码相关操作
Field sCurrentActivityThreadField = null;
try {
sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
// 反射获取的字段一般都要设置可见性
sCurrentActivityThreadField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 获取类的静态变量 , 使用 字段.get(null) 即可
Object activityThreadObject = null;
try {
activityThreadObject = sCurrentActivityThreadField.get(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 获取 Activity Thread 中的 final H mH = new H() 成员字段 ;
Field mHField = null;
try {
mHField = activityThreadClass.getDeclaredField("mH");
// 设置该字段的可见性
mHField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 通过反射获取 Activity Thread 中的 final H mH = new H() 成员实例对象
Handler mHObject = null;
try {
mHObject = (Handler) mHField.get(activityThreadObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class<?> handlerClass = null;
try {
handlerClass = Class.forName("android.os.Handler");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 通过反射获取 final H mH = new H() 成员的 mCallback 成员字段
// Handler 中有成员变量 final Callback mCallback;
Field mCallbackField = null;
try {
//mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField = mHObject.getClass().getDeclaredField("mCallback");
// 设置字段的可见性
mCallbackField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 使用静态代理类 HandlerProxy , 替换 final H mH = new H() 成员实例对象中的 mCallback 成员
HandlerProxy proxy = new HandlerProxy();
try {
Log.i(TAG, "mCallbackField : " mCallbackField " , mHObject : " mHObject " , proxy : " proxy);
mCallbackField.set(mHObject, proxy);
} catch (Exception e) {
e.printStackTrace();
}
}
四、用于替换 ActivityThread 中 mH 中的 mCallback 静态代理类
静态代理 ActivityThread 中的 final H mH = new H() 成员中的 mCallback 成员 ;
该静态代理类的主要作用是 , 在创建的 Activity 示例类之前 , 使用插件包中的 Activity 组件替换之前在 AMS 调用之前使用的 占坑用的 Activity , 就是要创建 插件包 中的 Activity 类的实例对象 ;
1、获取 ClientTransaction 类
代码语言:javascript复制 // 反射 android.app.servertransaction.ClientTransaction 类
// 该类中有如下成员变量
// private List<ClientTransactionItem> mActivityCallbacks;
// 这个集合中存放的就是 android.app.servertransaction.LaunchActivityItem 类实例
// 不能直接获取 LaunchActivityItem 实例 , 否则会出错
Class<?> clientTransactionClass = null;
try {
clientTransactionClass =
Class.forName("android.app.servertransaction.ClientTransaction");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2、验证 msg.obj 类型是否合法
验证处理的信号 , 是否是对应 LaunchActivityItem , 如果不是 , 直接退出 ;
代码语言:javascript复制 // 验证当前的 msg.obj 是否是 ClientTransaction 类型 , 如果不是则不进行 Intent 替换
// 通过阅读源码可知 , 在 ActivityThread 的 mH 中, 处理 EXECUTE_TRANSACTION 信号时
// 有 final ClientTransaction transaction = (ClientTransaction) msg.obj;
if (!clientTransactionClass.isInstance(msg.obj)) {
return true;
}
3、反射获取 mActivityCallbacks 字段
代码语言:javascript复制 // 反射获取
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段
Field mActivityCallbacksField = null;
try {
mActivityCallbacksField =
clientTransactionClass.getDeclaredField("mActivityCallbacks");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 设置成员字段可见性
mActivityCallbacksField.setAccessible(true);
4、反射获取 mActivityCallbacks 成员对象
代码语言:javascript复制 // 反射获取
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
Object mActivityCallbacksObject = null;
try {
mActivityCallbacksObject = mActivityCallbacksField.get(msg.obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
5、使用插件 Activity 对应的 Intent 替换 LaunchActivityItem 类中的 mIntent 字段
遍历 ClientTransaction 中 private List mActivityCallbacks 成员对象 , 只针对 LaunchActivityItem 类型的元素进行后续处理 ;
获取 LaunchActivityItem 类中的 mIntent 成员变量 , 然后从其中获取 获取 启动 插件包 组件的 Intent , 使用该 Intent 替换之前的 mIntent 成员 ;
代码语言:javascript复制 // 将
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
// 强转为 List 类型 , 以用于遍历
List mActivityCallbacksObjectList = (List) mActivityCallbacksObject;
for (Object item : mActivityCallbacksObjectList) {
Class<?> clazz = item.getClass();
// 只处理 LaunchActivityItem 的情况
if (clazz.getName().equals("android.app.servertransaction.LaunchActivityItem")) {
// 获取 LaunchActivityItem 的 private Intent mIntent; 字段
// 该 Intent 中的 Activity 目前是占坑 Activity 即 StubActivity
// 需要在实例化之前 , 替换成插件包中的 Activity
Field mIntentField = null;
try {
mIntentField = clazz.getDeclaredField("mIntent");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
mIntentField.setAccessible(true);
// 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 Intent
Intent intent = null;
try {
intent = (Intent) mIntentField.get(item);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 获取 启动 插件包 组件的 Intent
Intent pluginIntent = intent.getParcelableExtra("pluginIntent");
if (pluginIntent != null) {
// 使用 包含插件包组件信息的 Intent ,
// 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intent
try {
mIntentField.set(item, pluginIntent);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
6、完整代码示例
代码语言:javascript复制package kim.hsl.plugin;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.List;
/**
* 静态代理 ActivityThread 中的 final H mH = new H() 成员
*/
public class HandlerProxy implements Handler.Callback {
public static final int EXECUTE_TRANSACTION = 159;
@Override
public boolean handleMessage(Message msg) {
if (msg.what == EXECUTE_TRANSACTION) {
// 反射 android.app.servertransaction.ClientTransaction 类
// 该类中有如下成员变量
// private List<ClientTransactionItem> mActivityCallbacks;
// 这个集合中存放的就是 android.app.servertransaction.LaunchActivityItem 类实例
// 不能直接获取 LaunchActivityItem 实例 , 否则会出错
Class<?> clientTransactionClass = null;
try {
clientTransactionClass =
Class.forName("android.app.servertransaction.ClientTransaction");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 验证当前的 msg.obj 是否是 ClientTransaction 类型 , 如果不是则不进行 Intent 替换
// 通过阅读源码可知 , 在 ActivityThread 的 mH 中, 处理 EXECUTE_TRANSACTION 信号时
// 有 final ClientTransaction transaction = (ClientTransaction) msg.obj;
if (!clientTransactionClass.isInstance(msg.obj)) {
return true;
}
// 反射获取
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段
Field mActivityCallbacksField = null;
try {
mActivityCallbacksField =
clientTransactionClass.getDeclaredField("mActivityCallbacks");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 设置成员字段可见性
mActivityCallbacksField.setAccessible(true);
// 反射获取
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
Object mActivityCallbacksObject = null;
try {
mActivityCallbacksObject = mActivityCallbacksField.get(msg.obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 将
// private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
// 强转为 List 类型 , 以用于遍历
List mActivityCallbacksObjectList = (List) mActivityCallbacksObject;
for (Object item : mActivityCallbacksObjectList) {
Class<?> clazz = item.getClass();
// 只处理 LaunchActivityItem 的情况
if (clazz.getName().equals("android.app.servertransaction.LaunchActivityItem")) {
// 获取 LaunchActivityItem 的 private Intent mIntent; 字段
// 该 Intent 中的 Activity 目前是占坑 Activity 即 StubActivity
// 需要在实例化之前 , 替换成插件包中的 Activity
Field mIntentField = null;
try {
mIntentField = clazz.getDeclaredField("mIntent");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
mIntentField.setAccessible(true);
// 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 Intent
Intent intent = null;
try {
intent = (Intent) mIntentField.get(item);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 获取 启动 插件包 组件的 Intent
Intent pluginIntent = intent.getParcelableExtra("pluginIntent");
if (pluginIntent != null) {
// 使用 包含插件包组件信息的 Intent ,
// 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intent
try {
mIntentField.set(item, pluginIntent);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
return false;
}
}
五、Hook Activity 启动流程涉及的完整代码
代码语言:javascript复制package kim.hsl.plugin;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
/**
* 主要职责 : Hook Activity 的启动过程
* 本工具类只针对 API Level 28 实现 , 如果是完整插件化框架 , 需要实现所有版本的 Hook 过程
* 不同的版本 , Activity 的启动过程是不同的 , 需要逐个根据 Activity 启动源码进行 Hook 适配
*/
public class HookUtils {
private static final String TAG = "HookUtils";
/**
* 最终目的是劫持 ActivityManagerService 的 startActivity 方法 ,
* 修改 Intent 中药启动的 Activity 类
*/
public static void hookAms(Context context){
// 获取 android.app.ActivityManager 类
Class<?> activityManagerClass = null;
try {
activityManagerClass = Class.forName("android.app.ActivityManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取 android.app.ActivityManager 类 中的 IActivityManagerSingleton 属性
// private static final Singleton<IActivityManager> IActivityManagerSingleton 成员变量
Field iActivityManagerSingletonField = null;
try {
iActivityManagerSingletonField =
activityManagerClass.getDeclaredField("IActivityManagerSingleton");
// 设置成员字段的可访问性
iActivityManagerSingletonField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 获取 android.app.ActivityManager 类的静态成员变量
// private static final Singleton<IActivityManager> IActivityManagerSingleton
// 直接调用 Field 字段 iActivityManagerSingletonField 的 get 方法 , 传入 null 即可获取
Object iActivityManagerSingletonObject = null;
try {
iActivityManagerSingletonObject = iActivityManagerSingletonField.get(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 获取 Singleton 类
// ActivityManager 中的 IActivityManagerSingleton 成员是 Singleton<IActivityManager> 类型的
Class<?> singletonClass = null;
try {
singletonClass = Class.forName("android.util.Singleton");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 反射获取 Singleton 类中的 mInstance 字段
Field mInstanceField = null;
try {
mInstanceField = singletonClass.getDeclaredField("mInstance");
// 设置字段的可访问性
mInstanceField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 反射获取 Singleton 类中的 mInstance 成员对象
// 该 mInstanceObject 成员对象就是 IActivityManager
// private static final Singleton<IActivityManager> IActivityManagerSingleton
Object mInstanceObject = null;
try {
mInstanceObject = mInstanceField.get(iActivityManagerSingletonObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 使用动态代理 , 替换 android.app.ActivityManager 中的
// private static final Singleton<IActivityManager> IActivityManagerSingleton 成员的
// mInstance 成员
// 注意 : 该操作一定要在 AMS 启动之前将原来的 Intent 替换掉
// 之后还要替换回去
// 使用 Intent 启动插件包时 , 一般都使用隐式启动
// 调用 Intent 的 setComponent , 通过包名和类名创建 Component ,
// 这样操作 , 即使没有获得 Activity 引用 , 也不会报错
// 该插件包中的 Activity 没有在 "宿主" 应用中注册 , 因此启动报错
// AMS 会干掉没有注册过的 Activity
// 这里先在启动 AMS 之前 , 设置一个已经 注册过的 占坑 Activity ( StubActivity ) 执行启动流程
// 在主线程生成 Activity 实例对象时 , 还需要恢复插件包中的 Activity
// IActivityManager 是接口
// 这是一个 AIDL 文件生成的 , 由 IActivityManager.aidl 生成
Class<?> IActivityManagerInterface = null;
try {
IActivityManagerInterface = Class.forName("android.app.IActivityManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 动态代理的实际代理类
AmsInvocationHandler amsInvocationHandler =
new AmsInvocationHandler(context, mInstanceObject);
// 动态代理过程
Object proxy = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(), // 类加载器
new Class[]{IActivityManagerInterface}, // 接口
amsInvocationHandler); // 代理的对象
// 使用动态代理类 , 替换原来的 ActivityManager 中的 IActivityManagerSingleton 成员
// 的 Singleton 类中的 mInstance 成员
try {
mInstanceField.set(iActivityManagerSingletonObject, proxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 劫持 Activity Thread 的 final H mH = new H(); 成员
* 该成员类型是 class H extends Handler ;
* @param context
*/
public static void hookActivityThread(Context context) {
// 反射获取 ActivityThread 类
Class<?> activityThreadClass = null;
try {
activityThreadClass = Class.forName("android.app.ActivityThread");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// Activity Thread 是一个单例 , 内部的单例成员是
// private static volatile ActivityThread sCurrentActivityThread;
// 可以直接通过 ActivityThread 类 , 获取该单例对象
// 这也是 Hook 点优先找静态变量的原因 , 静态变量对象容易拿到 , 通过反射即可获取 , 不涉及系统源码相关操作
Field sCurrentActivityThreadField = null;
try {
sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
// 反射获取的字段一般都要设置可见性
sCurrentActivityThreadField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 获取类的静态变量 , 使用 字段.get(null) 即可
Object activityThreadObject = null;
try {
activityThreadObject = sCurrentActivityThreadField.get(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 获取 Activity Thread 中的 final H mH = new H() 成员字段 ;
Field mHField = null;
try {
mHField = activityThreadClass.getDeclaredField("mH");
// 设置该字段的可见性
mHField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 通过反射获取 Activity Thread 中的 final H mH = new H() 成员实例对象
Handler mHObject = null;
try {
mHObject = (Handler) mHField.get(activityThreadObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class<?> handlerClass = null;
try {
handlerClass = Class.forName("android.os.Handler");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 通过反射获取 final H mH = new H() 成员的 mCallback 成员字段
// Handler 中有成员变量 final Callback mCallback;
Field mCallbackField = null;
try {
//mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField = mHObject.getClass().getDeclaredField("mCallback");
// 设置字段的可见性
mCallbackField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 使用静态代理类 HandlerProxy , 替换 final H mH = new H() 成员实例对象中的 mCallback 成员
HandlerProxy proxy = new HandlerProxy();
try {
Log.i(TAG, "mCallbackField : " mCallbackField " , mHObject : " mHObject " , proxy : " proxy);
mCallbackField.set(mHObject, proxy);
} catch (Exception e) {
e.printStackTrace();
}
}
}
六、博客资源
博客资源 :
- GitHub : https://github.com/han1202012/Plugin_Hook