【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(一)

简介: Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(一)

文章目录

Android 插件化系列文章目录

前言

一、从源码角度分析加载资源流程

1、ActivityThread 入口

2、LaunchActivityItem

3、ActivityThread.performLaunchActivity

4、ContextImpl

二、Hook 点选择

三、资源冲突解决方案

四、博客资源

前言

在之前的博客 【Android 插件化】Hook 插件化框架 ( 插件包资源加载 ) 中 , 实现了从插件包中获取资源 ;


但是这种方法对代码的侵入性较大 , 使用这种方式开发 , 插件应用 和 宿主应用 , 都需要对 Resources 进行特别处理 , 如重写 Activity 和 Application 的 public Resources getResources() 方法 ;


最好是使用 Hook 方式加载资源文件 , 实现插件包代码 0 侵入 , 开发插件应用 与 开发普通应用 , 基本一致 ;






一、从源码角度分析加载资源流程


在插件包中的 Activity , 如果加载 R.layout.activity_main , 拿到的是 “宿主” 应用中的资源 , 无法拿到插件包中的资源 ;



1、ActivityThread 入口


在 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 ) 博客中 , 分析了 Activity 在主线程启动前的一些操作 ;



在 ActivityThread 中的 mH 处理 EXECUTE_TRANSACTION 信号时 , 其中 ClientTransaction 中有 LaunchActivityItem ;


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;
            }
        }
  }
}


源码路径 : /frameworks/base/core/java/android/app/ActivityThread.java



2、LaunchActivityItem


LaunchActivityItem 中的 execute 方法中的 ClientTransactionHandler client 参数 就是 ActivityThread ;


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



3、ActivityThread.performLaunchActivity


在 LaunchActivityItem 的 execute 方法中 , 调用 client.handleLaunchActivity 方法就是执行的 ActivityThread 的 handleLaunchActivity 方法 ;


在 ActivityThread 中的 handleLaunchActivity 方法中 , 调用了 performLaunchActivity 方法 ;


在 ActivityThread 中的 performLaunchActivity 方法中 , 调用


ContextImpl appContext = createBaseContextForActivity(r);


方法 , 创建了 ContextImpl 对象 ;


public final class ActivityThread extends ClientTransactionHandler {
    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
        final int displayId;
        try {
            displayId = ActivityManager.getService().getActivityDisplayId(r.token);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
        // For debugging purposes, if the activity's package name contains the value of
        // the "debug.use-second-display" system property as a substring, then show
        // its content on a secondary display if there is one.
        String pkgName = SystemProperties.get("debug.second-display.pkg");
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int id : dm.getDisplayIds()) {
                if (id != Display.DEFAULT_DISPLAY) {
                    Display display =
                            dm.getCompatibleDisplay(id, appContext.getResources());
                    appContext = (ContextImpl) appContext.createDisplayContext(display);
                    break;
                }
            }
        }
        return appContext;
    }
}


源码路径 : /frameworks/base/core/java/android/app/ActivityThread.java



目录
相关文章
|
18天前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
26天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
51 15
Android 系统缓存扫描与清理方法分析
|
29天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
74 6
|
28天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
30天前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
26 3
|
1月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
24 2
|
30天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
18 0
|
1月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
Java Android开发 容器