返回列表 发新帖
楼主: henkeai - 

【Xposed实战】Hook Activity:动态修改TextView与ImageView

  [复制链接]

0

主题

4421

回帖

7718

积分

硕士生

Rank: 6Rank: 6

金币
304
好评
0
信誉
100
发表于 2025-11-11 12:50:59 来自手机  | 显示全部楼层  来自 江苏
看看隐藏
回复

使用道具 举报

1

主题

227

回帖

1206

积分

高中生

Rank: 4

金币
764
好评
0
信誉
98
发表于 2025-11-11 14:15:10 来自手机  | 显示全部楼层  来自 甘肃
[赞
回复

使用道具 举报

0

主题

1513

回帖

4632

积分

大学生

Rank: 5Rank: 5

金币
4524
好评
0
信誉
95
发表于 2025-11-11 17:46:56 来自手机  | 显示全部楼层  来自 北京
看看隐藏
回复

使用道具 举报

0

主题

1235

回帖

2218

积分

大学生

Rank: 5Rank: 5

金币
24
好评
0
信誉
101
发表于 2025-11-11 17:47:24 | 显示全部楼层  来自 安徽
看看隐藏
回复

使用道具 举报

0

主题

27

回帖

126

积分

小学生

Rank: 2

金币
60
好评
0
信誉
100
发表于 2025-11-12 01:15:20 来自手机  | 显示全部楼层  来自 广西
看看隐藏内容
回复

使用道具 举报

0

主题

1165

回帖

3408

积分

大学生

Rank: 5Rank: 5

金币
3674
好评
0
信誉
100
QQ
发表于 2025-11-12 07:10:34 来自手机  | 显示全部楼层  来自 广东
感谢分享,回复学习隐藏内容
回复

使用道具 举报

0

主题

247

回帖

688

积分

初中生

Rank: 3Rank: 3

金币
439
好评
0
信誉
100
发表于 2025-11-12 07:38:01 来自手机  | 显示全部楼层  来自 广东
很是不错哦,感谢分享
回复

使用道具 举报

1

主题

519

回帖

1711

积分

高中生

Rank: 4

金币
1509
好评
0
信誉
100
发表于 2025-11-12 07:52:51 来自手机  | 显示全部楼层  来自 河南
看看隐藏
回复

使用道具 举报

6

主题

1428

回帖

3925

积分

大学生

Rank: 5Rank: 5

金币
6457
好评
0
信誉
100
发表于 2025-11-12 10:03:11 来自手机  | 显示全部楼层  来自 广东
蟹蟹大佬的教程分享
回复

使用道具 举报

2

主题

835

回帖

2326

积分

大学生

Rank: 5Rank: 5

金币
688
好评
0
信誉
98

MT论坛新人MT论坛帅哥考神

发表于 2025-11-12 11:49:21 来自手机  | 显示全部楼层  来自 山东
感谢分享
回复

使用道具 举报

6

主题

794

回帖

4026

积分

大学生

Rank: 5Rank: 5

金币
3847
好评
14
信誉
120

考神MT论坛新人MT论坛帅哥MT论坛活跃会员

发表于 2025-11-12 18:59:31 来自手机  | 显示全部楼层  来自 山东
本帖最后由 henkeai 于 2025-11-12 19:03 编辑
  1. import android.os.Bundle;
  2. import android.view.View;
  3. import android.view.ViewGroup;
  4. import android.widget.*;
  5. import android.text.SpannableString;
  6. import android.text.Spanned;
  7. import de.robv.android.xposed.IXposedHookLoadPackage;
  8. import de.robv.android.xposed.XC_MethodHook;
  9. import de.robv.android.xposed.XposedHelpers;
  10. import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
  11. import java.lang.reflect.Method;
  12. import java.util.ArrayList;
  13. import java.util.List;

  14. public class HookInit implements IXposedHookLoadPackage {

  15.     @Override
  16.     public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
  17.         if (!lpparam.packageName.equals("com.fuli")) return;

  18.         XposedHelpers.findAndHookMethod(
  19.             "com.fuli.MainActivity",
  20.             lpparam.classLoader,
  21.             "onCreate",
  22.             Bundle.class,
  23.             new XC_MethodHook() {
  24.                 @Override
  25.                 protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  26.                     // 修改
  27.                     
  28.                     Henkeai.henkeai(param.thisObject, "复利计算器", "1");
  29.                     Henkeai.henkeai(param.thisObject, "初始资金(元)", "2");
  30.                     Henkeai.henkeai(param.thisObject, "请输入初始资金", "3");
  31.                     Henkeai.henkeai(param.thisObject, "每日涨幅(%)", "4");
  32.                     Henkeai.henkeai(param.thisObject, "请输入每日涨幅百分比", "5");
  33.                     Henkeai.henkeai(param.thisObject, "目标资金(元)", "6");
  34.                     Henkeai.henkeai(param.thisObject, "请输入目标资金", "7");
  35.                     Henkeai.henkeai(param.thisObject, "计算天数", "8");
  36.                     Henkeai.henkeai(param.thisObject, "功能跳转", "9");
  37.                     Henkeai.henkeai(param.thisObject, "计算结果", "10");
  38.                     Henkeai.henkeai(param.thisObject, "计算结果", "11");
  39.                     Henkeai.henkeai(param.thisObject, "等待计算...", "12");
  40.                     

  41.                     // 批量修改
  42.                    // Henkeai.modifyMultipleText(param.thisObject,
  43.                     //                                         new String[]{"a", "b", "c"},
  44.                     //                                         new String[]{"a1", "b2", "c3"}
  45.                      //                                        );
  46.                 }
  47.             }
  48.         );
  49.     }

  50.    
  51.      // 修改Android控件
  52.      
  53.     public static class Henkeai {

  54.         
  55.          // 修改所有类型的文本
  56.          
  57.         public static void henkeai(Object activity, String findText, String newText) {
  58.             try {
  59.                 View rootView = getRootView(activity);
  60.                 if (rootView instanceof ViewGroup) {
  61.                     traverseAndModifyAllText((ViewGroup) rootView, findText, newText);
  62.                 }
  63.             } catch (Exception e) {
  64.                 e.printStackTrace();
  65.             }
  66.         }

  67.         
  68.          // 批量修改文本
  69.          
  70.         public static void modifyMultipleText(Object activity, String[] findTexts, String[] newTexts) {
  71.             if (findTexts.length != newTexts.length) return;

  72.             try {
  73.                 View rootView = getRootView(activity);
  74.                 if (rootView instanceof ViewGroup) {
  75.                     for (int i = 0; i < findTexts.length; i++) {
  76.                         traverseAndModifyAllText((ViewGroup) rootView, findTexts[i], newTexts[i]);
  77.                     }
  78.                 }
  79.             } catch (Exception e) {
  80.                 e.printStackTrace();
  81.             }
  82.         }

  83.         
  84.          // 递归遍历并修改所有文本
  85.          
  86.         private static boolean traverseAndModifyAllText(ViewGroup parent, String findText, String newText) {
  87.             // 遍历父容器的所有直接子View
  88.             for (int i = 0; i < parent.getChildCount(); i++) {
  89.                 View child = parent.getChildAt(i);

  90.                 // 处理所有可能的文本控件
  91.                 if (tryModifyViewText(child, findText, newText)) {
  92.                     return true;
  93.                 }

  94.                 // 如果这个子View本身也是容器,递归遍历它的子View,递归处理子View
  95.                 if (child instanceof ViewGroup) {
  96.                     boolean found = traverseAndModifyAllText((ViewGroup) child, findText, newText);
  97.                     if (found) return true;
  98.                 }
  99.             }
  100.             return false;
  101.         }

  102.         
  103.          // 修改View的文本
  104.          
  105.         private static boolean tryModifyViewText(View view, String findText, String newText) {
  106.             try {
  107.                 // TextView及其子类 Button、EditText、CheckBox等
  108.                 if (view instanceof TextView) {
  109.                     TextView textView = (TextView) view;

  110.                     // 检查显示文本
  111.                     CharSequence text = textView.getText();
  112.                     if (text != null && findText.equals(text.toString())) {
  113.                         textView.setText(newText);
  114.                         return true;
  115.                     }

  116.                     // 检查提示文本EditText等
  117.                     CharSequence hint = textView.getHint();
  118.                     if (hint != null && findText.equals(hint.toString())) {
  119.                         textView.setHint(newText);
  120.                         return true;
  121.                     }
  122.                 }

  123.                 // Toolbar ActionBar
  124.                 if (view instanceof android.widget.Toolbar) {
  125.                     android.widget.Toolbar toolbar = (android.widget.Toolbar) view;
  126.                     CharSequence title = toolbar.getTitle();
  127.                     if (title != null && findText.equals(title.toString())) {
  128.                         toolbar.setTitle(newText);
  129.                         return true;
  130.                     }

  131.                     CharSequence subtitle = toolbar.getSubtitle();
  132.                     if (subtitle != null && findText.equals(subtitle.toString())) {
  133.                         toolbar.setSubtitle(newText);
  134.                         return true;
  135.                     }
  136.                 }

  137.                 // SearchView
  138.                 if (view instanceof SearchView) {
  139.                     SearchView searchView = (SearchView) view;

  140.                     // 通过反射获取查询提示
  141.                     try {
  142.                         Method getQueryHintMethod = SearchView.class.getMethod("getQueryHint");
  143.                         CharSequence queryHint = (CharSequence) getQueryHintMethod.invoke(searchView);
  144.                         if (queryHint != null && findText.equals(queryHint.toString())) {
  145.                             searchView.setQueryHint(newText);
  146.                             return true;
  147.                         }
  148.                     } catch (Exception e) {
  149.                         // 忽略反射错误
  150.                     }
  151.                 }

  152.                 // ProgressBar
  153.                 if (view instanceof ProgressBar) {
  154.                     CharSequence contentDesc = view.getContentDescription();
  155.                     if (contentDesc != null && findText.equals(contentDesc.toString())) {
  156.                         view.setContentDescription(newText);
  157.                         return true;
  158.                     }
  159.                 }

  160.                 // ImageView
  161.                 if (view instanceof ImageView) {
  162.                     CharSequence contentDesc = view.getContentDescription();
  163.                     if (contentDesc != null && findText.equals(contentDesc.toString())) {
  164.                         view.setContentDescription(newText);
  165.                         return true;
  166.                     }
  167.                 }

  168.                 // 任何View的内容描述
  169.                 CharSequence contentDesc = view.getContentDescription();
  170.                 if (contentDesc != null && findText.equals(contentDesc.toString())) {
  171.                     view.setContentDescription(newText);
  172.                     return true;
  173.                 }

  174.                 // 通过反射尝试获取其他文本属性
  175.                 if (tryModifyByReflection(view, findText, newText)) {
  176.                     return true;
  177.                 }

  178.             } catch (Exception e) {
  179.                 // 忽略单个View的修改错误,继续处理其他View
  180.             }
  181.             return false;
  182.         }

  183.         
  184.          // 通过反射修改其他可能的文本属性
  185.          
  186.         private static boolean tryModifyByReflection(View view, String findText, String newText) {
  187.             try {
  188.                 // 获取View的所有方法
  189.                 Method[] methods = view.getClass().getMethods();

  190.                 for (Method method : methods) {
  191.                     // 查找可能的文本获取方法
  192.                     if (method.getName().startsWith("get") &&
  193.                         method.getParameterTypes().length == 0 &&
  194.                         CharSequence.class.isAssignableFrom(method.getReturnType())) {

  195.                         try {
  196.                             CharSequence text = (CharSequence) method.invoke(view);
  197.                             if (text != null && findText.equals(text.toString())) {
  198.                                 // 查找对应的setter方法
  199.                                 String setterName = "set" + method.getName().substring(3);
  200.                                 try {
  201.                                     Method setter = view.getClass().getMethod(setterName, CharSequence.class);
  202.                                     setter.invoke(view, newText);
  203.                                     return true;
  204.                                 } catch (Exception e) {
  205.                                     // 尝试其他类型的setter
  206.                                     try {
  207.                                         Method setter = view.getClass().getMethod(setterName, String.class);
  208.                                         setter.invoke(view, newText);
  209.                                         return true;
  210.                                     } catch (Exception e2) {
  211.                                         // 继续尝试其他方法
  212.                                     }
  213.                                 }
  214.                             }
  215.                         } catch (Exception e) {
  216.                             // 继续尝试其他方法
  217.                         }
  218.                     }
  219.                 }
  220.             } catch (Exception e) {
  221.                 // 忽略反射错误
  222.             }
  223.             return false;
  224.         }

  225.         
  226.          // 获取所有包含指定文本的View
  227.          
  228.         public static List<View> findAllViewsWithText(Object activity, String findText) {
  229.             List<View> result = new ArrayList<>();
  230.             try {
  231.                 View rootView = getRootView(activity);
  232.                 if (rootView instanceof ViewGroup) {
  233.                     findAllViewsWithText((ViewGroup) rootView, findText, result);
  234.                 }
  235.             } catch (Exception e) {
  236.                 e.printStackTrace();
  237.             }
  238.             return result;
  239.         }
  240.         
  241.         //递归查找包含指定文本的View
  242.         private static void findAllViewsWithText(ViewGroup parent, String findText, List<View> result) {
  243.             for (int i = 0; i < parent.getChildCount(); i++) {
  244.                 View child = parent.getChildAt(i);

  245.                 if (containsText(child, findText)) {
  246.                     result.add(child);
  247.                 }

  248.                 if (child instanceof ViewGroup) {
  249.                     findAllViewsWithText((ViewGroup) child, findText, result);
  250.                 }
  251.             }
  252.         }

  253.         
  254.          // 检查View是否包含指定文本
  255.          
  256.         private static boolean containsText(View view, String findText) {
  257.             try {
  258.                 // TextView及其子类
  259.                 if (view instanceof TextView) {
  260.                     TextView textView = (TextView) view;
  261.                     if (findText.equals(textView.getText().toString()) ||
  262.                         findText.equals(textView.getHint().toString())) {
  263.                         return true;
  264.                     }
  265.                 }

  266.                 // Toolbar
  267.                 if (view instanceof android.widget.Toolbar) {
  268.                     android.widget.Toolbar toolbar = (android.widget.Toolbar) view;
  269.                     if (findText.equals(toolbar.getTitle().toString()) ||
  270.                         findText.equals(toolbar.getSubtitle().toString())) {
  271.                         return true;
  272.                     }
  273.                 }

  274.                 // 内容描述
  275.                 CharSequence contentDesc = view.getContentDescription();
  276.                 if (contentDesc != null && findText.equals(contentDesc.toString())) {
  277.                     return true;
  278.                 }

  279.             } catch (Exception e) {
  280.                 // 忽略错误
  281.             }
  282.             return false;
  283.         }

  284.         // 获取Activity的根视图
  285.         private static View getRootView(Object activity) throws Exception {
  286.             Object window = XposedHelpers.callMethod(activity, "getWindow");
  287.             return (View) XposedHelpers.callMethod(window, "getDecorView");
  288.         }
  289.     }
  290. }
复制代码
回复

使用道具 举报

0

主题

87

回帖

306

积分

初中生

Rank: 3Rank: 3

金币
194
好评
0
信誉
100
发表于 2025-11-12 23:56:22 来自手机  | 显示全部楼层  来自 重庆
看看隐藏
回复

使用道具 举报

23

主题

1154

回帖

4463

积分

大学生

Rank: 5Rank: 5

金币
2346
好评
4
信誉
101

考神

发表于 2025-11-13 08:57:06 来自手机  | 显示全部楼层  来自 湖北
先收藏一波,感谢分享
回复

使用道具 举报

0

主题

2969

回帖

6906

积分

硕士生

Rank: 6Rank: 6

金币
3327
好评
0
信誉
100

MT论坛新人考神MT论坛帅哥

发表于 2025-11-14 00:06:38 来自手机  | 显示全部楼层  来自 浙江
感谢分享
回复

使用道具 举报

0

主题

58

回帖

218

积分

小学生

Rank: 2

金币
185
好评
0
信誉
100
QQ
发表于 2025-11-14 00:35:58 来自手机  | 显示全部楼层  来自 广东
6666666
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表