欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > Android >内容正文

Android

【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

发布时间:2025/6/17 Android 42 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 ) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

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 方法 ;

public class LaunchActivityItem extends ClientTransactionItem {@Overridepublic 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 的实例化操作 ;

activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);

在 class H extends Handler 类中 , 处理 EXECUTE_TRANSACTION 信号时 , 启动了 LaunchActivityItem 的 execute 方法 , 进而调用 ActivityThread 中的 handleLaunchActivity 方法 , 创建 Activity 实例对象 ;

这里劫持该 Handler , 将插件包 Activity 替换到原来的 Activity 中 ;


ActivityThread 的相关源码 :

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.*/@Overridepublic 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 activityif (!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 类


// 反射获取 ActivityThread 类Class<?> activityThreadClass = null;try {activityThreadClass = Class.forName("android.app.ActivityThread");} catch (ClassNotFoundException e) {e.printStackTrace();}

2、反射获取 ActivityThread 单例对象


// 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 字段


// 获取 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 对象


// 通过反射获取 Activity Thread 中的 final H mH = new H() 成员实例对象Handler mHObject = null;try {mHObject = (Handler) mHField.get(activityThreadObject);} catch (IllegalAccessException e) {e.printStackTrace();}

5、反射获取 Handler 中的 mCallback 字段


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 成员


// 使用静态代理类 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、完整代码示例


/*** 劫持 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 类


// 反射 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 , 如果不是 , 直接退出 ;

// 验证当前的 msg.obj 是否是 ClientTransaction 类型 , 如果不是则不进行 Intent 替换// 通过阅读源码可知 , 在 ActivityThread 的 mH 中, 处理 EXECUTE_TRANSACTION 信号时// 有 final ClientTransaction transaction = (ClientTransaction) msg.obj;if (!clientTransactionClass.isInstance(msg.obj)) {return true;}

3、反射获取 mActivityCallbacks 字段


// 反射获取// private List<ClientTransactionItem> mActivityCallbacks; 成员字段Field mActivityCallbacksField = null;try {mActivityCallbacksField =clientTransactionClass.getDeclaredField("mActivityCallbacks");} catch (NoSuchFieldException e) {e.printStackTrace();}// 设置成员字段可见性mActivityCallbacksField.setAccessible(true);

4、反射获取 mActivityCallbacks 成员对象


// 反射获取// 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 成员 ;

// 将// 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// 需要在实例化之前 , 替换成插件包中的 ActivityField mIntentField = null;try {mIntentField = clazz.getDeclaredField("mIntent");} catch (NoSuchFieldException e) {e.printStackTrace();}mIntentField.setAccessible(true);// 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 IntentIntent intent = null;try {intent = (Intent) mIntentField.get(item);} catch (IllegalAccessException e) {e.printStackTrace();}// 获取 启动 插件包 组件的 IntentIntent pluginIntent = intent.getParcelableExtra("pluginIntent");if (pluginIntent != null) {// 使用 包含插件包组件信息的 Intent ,// 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intenttry {mIntentField.set(item, pluginIntent);} catch (IllegalAccessException e) {e.printStackTrace();}}}}}

6、完整代码示例


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;@Overridepublic 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// 需要在实例化之前 , 替换成插件包中的 ActivityField mIntentField = null;try {mIntentField = clazz.getDeclaredField("mIntent");} catch (NoSuchFieldException e) {e.printStackTrace();}mIntentField.setAccessible(true);// 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 IntentIntent intent = null;try {intent = (Intent) mIntentField.get(item);} catch (IllegalAccessException e) {e.printStackTrace();}// 获取 启动 插件包 组件的 IntentIntent pluginIntent = intent.getParcelableExtra("pluginIntent");if (pluginIntent != null) {// 使用 包含插件包组件信息的 Intent ,// 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intenttry {mIntentField.set(item, pluginIntent);} catch (IllegalAccessException e) {e.printStackTrace();}}}}}return false;} }



五、Hook Activity 启动流程涉及的完整代码



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> IActivityManagerSingletonObject 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

总结

以上是生活随笔为你收集整理的【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。