日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )

發布時間:2025/6/17 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android 插件化系列文章目錄

【Android 插件化】插件化簡介 ( 組件化與插件化 )
【Android 插件化】插件化原理 ( JVM 內存數據 | 類加載流程 )
【Android 插件化】插件化原理 ( 類加載器 )

【Android 插件化】“ 插樁式 “ 插件化框架 ( 原理與實現思路 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 類加載器創建 | 資源加載 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 獲取插件入口 Activity 組件 | 加載插件 Resources 資源 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 運行應用 | 代碼整理 )

【Android 插件化】Hook 插件化框架 ( Hook 技術 | 代理模式 | 靜態代理 | 動態代理 )
【Android 插件化】Hook 插件化框架 ( Hook 實現思路 | Hook 按鈕點擊事件 )


文章目錄

  • Android 插件化系列文章目錄
  • 前言
  • 一、Hook 實現思路
  • 二、Hook 按鈕點擊事件
    • 1、按鈕點擊事件
    • 2、熟悉底層源碼
    • 3、獲取 View 的 ListenerInfo mListenerInfo 成員
    • 4、分析 Hook 點
    • 5、反射 ListenerInfo 并設置新的 OnClickListener 監聽器
  • 三、完整代碼示例
  • 四、博客資源


前言

在上一篇博客 【Android 插件化】Hook 插件化框架 ( Hook 技術 | 代理模式 | 靜態代理 | 動態代理 ) 中 , 對 Hook 技術進行了簡要介紹 , Android 中的 Hook 技術主要是通過

反射
代理模式 ( 動態代理 / 靜態代理 )

實現的 ;


之所以使用 Hook 技術 , 是因為反射系統的源碼時 , 會出現問題 , Google 官方對 Android 的反射進行了限制 ;

反射出現問題時 , 必須找到一個可以反射的反射點掛鉤子 , 如在 A 位置無法進行反射 , 就在 B 位置掛 Hook 鉤子 ;


最終要實現的是使用 Hook , 影響 Activity 的啟動流程 , 在啟動流程中注入我們想要的業務邏輯 , 干涉啟動流程 , 以達到能啟動插件包 APK 中的 Activity 的目的 ;






一、Hook 實現思路



Hook 點選擇規則 : Hook 技術的關鍵是找好 Hook 點 , 將鉤子掛在哪 , 勾住哪個方法 , 需要遵循一定的規則 :

靜態變量 / 單例 : 優先選擇 靜態變量 , 單例對象 , 這些對象一旦創建 , 基本不會改變 , 容易定位 ;


Hook 點實現思路 :

① 查找 Hook 點 : 用于下鉤子 ;

② 選擇代理模式 : 靜態代理 / 動態代理 ;

③ 代理替換 : 通過反射 , 將鉤子替換成開發者自定義的代理 , 一般是在原有調用的基礎上 , 不影響原來功能的前提下 , 注入新的邏輯 ;





二、Hook 按鈕點擊事件




1、按鈕點擊事件


獲取布局文件的按鈕 , 并為其設置點擊事件 , 該點擊事件 public void onClick(View v) 就是需要 Hook 的方法 , 我們使用 Hook 技術 , 使用動態代理 , 替換掉該 onClick 方法 , 注入額外的業務邏輯 ;

// 獲取按鈕 , 并未按鈕組件設置點擊事件 Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.i(TAG, "Button OnClickListener onClick");} });

2、熟悉底層源碼


使用 Hook 的前提是 , 必須熟悉要 Hook 功能的底層源碼 , 如 : Hook 按鈕點擊事件 , 必須熟悉 View 組件的 OnClickListener 相關源碼 ;

先分析 View 的 setOnClickListener 方法的源碼 , 傳入 OnClickListener l 監聽器 , 將該監聽器賦值給 getListenerInfo().mOnClickListener 值 ;

public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {@UnsupportedAppUsageListenerInfo mListenerInfo;/*** Register a callback to be invoked when this view is clicked. If this view is not* clickable, it becomes clickable.** @param l The callback that will run** @see #setClickable(boolean)*/public void setOnClickListener(@Nullable OnClickListener l) {if (!isClickable()) {setClickable(true);}getListenerInfo().mOnClickListener = l;}@UnsupportedAppUsageListenerInfo getListenerInfo() {if (mListenerInfo != null) {return mListenerInfo;}mListenerInfo = new ListenerInfo();return mListenerInfo;} }

如果要替換 按鈕點擊事件 , 可以反射 View 的 getListenerInfo() 方法 , 直接設置一個新的 點擊監聽器 ;

getListenerInfo().mOnClickListener = l;

位置作為鉤子的 Hook 點 , 勾住該方法 ;


3、獲取 View 的 ListenerInfo mListenerInfo 成員


先使用反射獲取 View 組件的 getListenerInfo 方法 ;

// 獲取 View 的 getListenerInfo 方法 Method getListenerInfo = null; try {getListenerInfo = View.class.getDeclaredMethod("getListenerInfo"); } catch (NoSuchMethodException e) {e.printStackTrace(); }

設置 getListenerInfo 方法的可見性 , 之后要調用該方法 , 否則會報錯 ;

// 執行所有的反射方法 , 設置成員變量 之前 , 都要設置可見性 getListenerInfo.setAccessible(true);

執行 反射獲取的 getListenerInfo 方法 , 并獲取 ListenerInfo mListenerInfo 成員 ;

// 執行 View view 對象的 getListenerInfo 方法 Object object = null; try {object = getListenerInfo.invoke(view); } catch (IllegalAccessException e) {e.printStackTrace(); } catch (InvocationTargetException e) {e.printStackTrace(); }

4、分析 Hook 點


分析 View 組件的 setOnClickListener 方法 , 最終將 OnClickListener l 點擊監聽器設置到哪 ?

getListenerInfo() 獲取的是 ListenerInfo 類型的對象 , 其中就封裝了 OnClickListener mOnClickListener 成員 , 點擊監聽器就是設置在這里 ;

知道了定義位置 , 就可以通過反射獲取 mOnClickListener 對應的成員字段 Field ;

public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {static class ListenerInfo {/*** Listener used to dispatch click events.* This field should be made private, so it is hidden from the SDK.* {@hide}*/@UnsupportedAppUsagepublic OnClickListener mOnClickListener;}/*** Interface definition for a callback to be invoked when a view is clicked.*/public interface OnClickListener {/*** Called when a view has been clicked.** @param v The view that was clicked.*/void onClick(View v);} }

5、反射 ListenerInfo 并設置新的 OnClickListener 監聽器


獲取 ListenerInfo 中的 public OnClickListener mOnClickListener 成員 , 并重新設置新的成員 , 注入業務邏輯 ;

① 先根據全類名獲取 android.view.View$ListenerInfo 字節碼對象 ;

// ① 先根據全類名獲取 ListenerInfo 字節碼 Class<?> clazz = null; try {clazz = Class.forName("android.view.View$ListenerInfo"); } catch (ClassNotFoundException e) {e.printStackTrace(); }

② 獲取 android.view.View$ListenerInfo 中的 mOnClickListener 成員

// ② 獲取 android.view.View.ListenerInfo 中的 mOnClickListener 成員 Field field = null; try {field = clazz.getField("mOnClickListener"); } catch (NoSuchFieldException e) {e.printStackTrace(); }

③ 設置該字段訪問性, 執行所有的反射方法 , 設置成員變量 之前 , 都要設置可見性 ;

// ③ 設置該字段訪問性, 執行所有的反射方法 , 設置成員變量 之前 , 都要設置可見性 field.setAccessible(true);

④ 獲取 mOnClickListener 成員變量 ;

// ④ 獲取 mOnClickListener 成員變量 View.OnClickListener mOnClickListener = null; try {mOnClickListener = (View.OnClickListener) field.get(mListenerInfo); } catch (IllegalAccessException e) {e.printStackTrace(); }

⑤ 修改 View 的 ListenerInfo 成員的 mOnClickListener 成員 , 重新設置一個自定義的 View.OnClickListener 監聽器 , 在該監聽器的 onClick 方法中 , 調用之前獲取的 監聽器的 onClick 方法 , 此外還可以在該點擊方法前后注入開發者自定義的業務邏輯 ;

// ⑤ 修改 View 的 ListenerInfo 成員的 mOnClickListener 成員 try {View.OnClickListener finalMOnClickListener = mOnClickListener;field.set(mListenerInfo, new View.OnClickListener(){@Overridepublic void onClick(View v) {Log.i(TAG, "Hook Before");finalMOnClickListener.onClick(view);Log.i(TAG, "Hook After");}}); } catch (IllegalAccessException e) {e.printStackTrace(); }



三、完整代碼示例



完整代碼示例 :

package com.example.plugin_hook;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button;import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 獲取按鈕 , 并未按鈕組件設置點擊事件Button button = findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.i(TAG, "Button OnClickListener onClick");}});hook(button);}/*** hook Button 組件的 getListenerInfo 方法* @param view*/private void hook(View view){// 獲取 View 的 getListenerInfo 方法Method getListenerInfo = null;try {getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");} catch (NoSuchMethodException e) {e.printStackTrace();}// 執行所有的反射方法 , 設置成員變量 之前 , 都要設置可見性getListenerInfo.setAccessible(true);// 執行 View view 對象的 getListenerInfo 方法Object mListenerInfo = null;try {mListenerInfo = getListenerInfo.invoke(view);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}// 反射獲取 OnClickListener 成員// ① 先根據全類名獲取 ListenerInfo 字節碼Class<?> clazz = null;try {clazz = Class.forName("android.view.View$ListenerInfo");} catch (ClassNotFoundException e) {e.printStackTrace();}// ② 獲取 android.view.View.ListenerInfo 中的 mOnClickListener 成員Field field = null;try {field = clazz.getField("mOnClickListener");} catch (NoSuchFieldException e) {e.printStackTrace();}// ③ 設置該字段訪問性, 執行所有的反射方法 , 設置成員變量 之前 , 都要設置可見性field.setAccessible(true);// ④ 獲取 mOnClickListener 成員變量View.OnClickListener mOnClickListener = null;try {mOnClickListener = (View.OnClickListener) field.get(mListenerInfo);} catch (IllegalAccessException e) {e.printStackTrace();}// ⑤ 修改 View 的 ListenerInfo 成員的 mOnClickListener 成員// 其中 ListenerInfo 成員 是try {View.OnClickListener finalMOnClickListener = mOnClickListener;field.set(mListenerInfo, new View.OnClickListener(){@Overridepublic void onClick(View v) {Log.i(TAG, "Hook Before");finalMOnClickListener.onClick(view);Log.i(TAG, "Hook After");}});} catch (IllegalAccessException e) {e.printStackTrace();}} }

執行結果 :

2021-06-17 11:19:07.513 12251-12251/com.example.plugin_hook I/MainActivity: Hook Before 2021-06-17 11:19:07.513 12251-12251/com.example.plugin_hook I/MainActivity: Button OnClickListener onClick 2021-06-17 11:19:07.513 12251-12251/com.example.plugin_hook I/MainActivity: Hook After



四、博客資源



博客資源 :

  • GitHub : https://github.com/han1202012/Plugin_Hook

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。