【Android 插件化】Hook 插件化框架 ( hook 插件化原理 | 插件包管理 )
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 插件化原理
- 二、插件化依賴庫創建
- 三、插件包管理
- 四、插件包管理完整代碼示例
- 五、博客資源
前言
前 222 篇博客 【Android 插件化】Hook 插件化框架 ( 從 Hook 應用角度分析 Activity 啟動流程 一 | Activity 進程相關源碼 ) , 【Android 插件化】Hook 插件化框架 ( 從 Hook 應用角度分析 Activity 啟動流程 二 | AMS 進程相關源碼 | 主進程相關源碼 ) 中 , 分析了從 Activity 調用 startActivity 啟動另一個 Activity 的底層源碼流程 , 涉及到了 222 個進程 , 一個是本應用的主線程所在的進程 , 一個是 ActivityManagerService 進程 ;
本博客中開始對 Activity 啟動過程進行 Hook 操作 , 基于 Android 999 , API 282828 版本 , 這里要注意 , 不同的 API 版本底層源碼邏輯不同 , Hook 點以及 Hook 方式也不同 ;
目前的主流插件化框架都已經兼容到了 Android 101010 版本 ;
一、hook 插件化原理
使用 Hook 實現的插件化原理如下 : 通過以下 333 個步驟實現插件化 ;
1. 加載插件包中的字節碼
2. hook 技術 : 直接通過 hook 技術, 鉤住系統的 Activity 啟動流程實現
① Activity 對象創建之前 , 要做很多初始化操作 , 先在 ActivityRecord 中加載 Activity 信息 , 如果修改了該信息 , 將要跳轉的 Activity 信息修改為插件包中的 Activity , 原來的 Activity 只用于占位 , 用于欺騙 Android 系統 ;
② 使用 hook 技術 , 加載插件包 apk 中的 Activity
③ 實現跳轉的 Activity ( 插件包中的 )
3. 資源加載 : 主要是解決 Resources 資源沖突問題 ;
( 使用上述 hook 插件化 , 可以不用考慮 Activity 的生命周期問題 )
占位 Activity : 插件包中的 Activity 是通過正規流程 , 由 AMS 進行創建并加載的 , 但是 該 Activity 并沒有在 AndroidManifest.xml 清單文件中注冊 , 這里需要一個已經在清單文件注冊的 Activity 欺騙系統 ;
插裝式插件化 : 是通過代理 Activity , 將 插件包加載的 字節碼 Class 類 中 對應的 Activity 類作為一個普通的 Java 類 , 該普通的 Java 類有所有的 Activity 的業務邏輯 , 該 Activity 的生命周期 , 由代理 Activity 執行相關的生命周期方法
hook 插件化 : hook 插件化直接鉤住系統中 Activity 啟動流程的某個點
二、插件化依賴庫創建
hook 插件化依賴庫是 Android 依賴庫 ( Android Library Module ) ;
創建插件化的核心依賴庫 :
通過該 lib_plugin_core 依賴庫 , 實現插件化相關功能 ;
在其中創建插件化的核心管理類 PluginManager , 用于管理插件相關內容 ;
三、插件包管理
插件包目錄 : 將插件包放在 /data/data/< package name >/files/ 目錄中 ;
// 插件包的絕對路徑 , /data/data/< package name >/files/ String apkPath = mBase.getFilesDir().getAbsolutePath() + "plugin.apk";插件包緩存目錄 : 同時設置 , 加載插件包中產生的緩存文件路徑是 /data/data/< package name >/app_plugin_cache/ 目錄 ;
// 加載插件包后產生的緩存文件路徑 // /data/data/< package name >/app_plugin_cache/ String cachePath =mBase.getDir("plugin_cache", Context.MODE_PRIVATE).getAbsolutePath();創建插件包的類加載器 :
// 創建類加載器 DexClassLoader plugin_dexClassLoader =new DexClassLoader(apkPath, // 插件包路徑cachePath, // 插件包加載時產生的緩存路徑null, // 庫的搜索路徑, 可以設置為空mBase.getClassLoader() // 父加載器, PathClassLoader);四、插件包管理完整代碼示例
package kim.hsl.plugin;import android.content.Context;import java.lang.reflect.Field;import dalvik.system.DexClassLoader;/*** 使用 Hook 實現的插件使用入口* 1. 加載插件包中的字節碼* 2. 直接通過 hook 技術, 鉤住系統的 Activity 啟動流程實現* ① Activity 對象創建之前 , 要做很多初始化操作 , 先在 ActivityRecord 中加載 Activity 信息* 如果修改了該信息 , 將要跳轉的 Activity 信息修改為插件包中的 Activity* 原來的 Activity 只用于占位 , 用于欺騙 Android 系統* ② 使用 hook 技術 , 加載插件包 apk 中的 Activity* ③ 實現跳轉的 Activity ( 插件包中的 )* 3. 解決 Resources 資源沖突問題* ( 使用上述 hook 插件化 , 可以不用考慮 Activity 的聲明周期問題 )** 插件包中的 Activity 是通過正規流程 , 由 AMS 進行創建并加載的* 但是該 Activity 并沒有在 AndroidManifest.xml 清單文件中注冊* 這里需要一個已經在清單文件注冊的 Activity 欺騙系統** 插裝式插件化 是通過代理 Activity , 將插件包加載的字節碼 Class 作為一個普通的 Java 類* 該普通的 Java 類有所有的 Activity 的業務邏輯* 該 Activity 的聲明周期 , 由代理 Activity 執行相關的生命周期方法* hook 插件化 : hook 插件化直接鉤住系統中 Activity 啟動流程的某個點* 使用插件包中的 Activity 替換占位的 Activity*/ public class PluginManager {/*** 上下文*/private Context mBase;/*** 單例*/private static PluginManager instance;public static PluginManager getInstance(Context context) {if (instance == null) {instance = new PluginManager(context);}return instance;}private PluginManager(Context context) {this.mBase = context;}/*** Application 啟動后 , 調用該方法初始化插件化環境* 加載插件包中的字節碼*/private void init() {// 加載 apk 文件loadApk();}private void loadApk() {// 插件包的絕對路徑 , /data/data/< package name >/files/String apkPath = mBase.getFilesDir().getAbsolutePath() + "plugin.apk";// 加載插件包后產生的緩存文件路徑// /data/data/< package name >/app_plugin_cache/String cachePath =mBase.getDir("plugin_cache", Context.MODE_PRIVATE).getAbsolutePath();// 創建類加載器DexClassLoader plugin_dexClassLoader =new DexClassLoader(apkPath, // 插件包路徑cachePath, // 插件包加載時產生的緩存路徑null, // 庫的搜索路徑, 可以設置為空mBase.getClassLoader() // 父加載器, PathClassLoader);}}
五、博客資源
博客資源 :
- GitHub : https://github.com/han1202012/Plugin_Hook
總結
以上是生活随笔為你收集整理的【Android 插件化】Hook 插件化框架 ( hook 插件化原理 | 插件包管理 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【错误记录】Android Studio
- 下一篇: 【Android 插件化】Hook 插件