Xposed免重启更新模块

匿名 (未验证) 提交于 2019-12-03 00:13:02

    Xposed模块在每次更新后都需要重启才能生效,公司给我的测试机是小米4,非常古董,每次重启都需要花费大量时间.而且手机系统是我刷的一个原生6.0的系统,总有些小bug,有时候需要重启很多次才行,等的我黄花菜都凉了.所以有必要必须把这个搞一搞了.

   简单总结一下原理:安装模块时,Android系统会在data/app/对应包名的目录下保存原始apk,通过读取这个原始的apk,然后new一个PathClassLoader,该PathClassLoader用于加载写有hook逻辑的类,最后通过反射的方式完成hook的具体逻辑.

工具

方法:1.新建一个HookLoader类,具体代码如下:

  1 package com.example.xposedhook;   2    3 import android.app.Application;   4 import android.content.Context;   5 import android.content.pm.ApplicationInfo;   6 import android.content.pm.PackageManager;   7    8 import java.io.File;   9   10 import dalvik.system.PathClassLoader;  11 import de.robv.android.xposed.IXposedHookLoadPackage;  12 import de.robv.android.xposed.IXposedHookZygoteInit;  13 import de.robv.android.xposed.XC_MethodHook;  14 import de.robv.android.xposed.XposedBridge;  15 import de.robv.android.xposed.XposedHelpers;  16 import de.robv.android.xposed.callbacks.XC_LoadPackage;  17   18 /**  19  * @author DX  20  * 这种方案建议只在开发调试的时候使用,因为这将损耗一些性能(需要额外加载apk文件),调试没问题后,直接修改xposed_init文件为正确的类即可  21  * 可以实现免重启,由于存在缓存,需要杀死宿主程序以后才能生效  22  * Created by DX on 2017/10/4.  23  * Modified by chengxuncc on 2019/4/16.  24  */  25   26 public class HookLoader implements IXposedHookLoadPackage, IXposedHookZygoteInit {  27     //按照实际使用情况修改下面几项的值  28     /**  29      * 当前Xposed模块的包名,方便寻找apk文件  30      */  31     private final static String modulePackageName = HookLoader.class.getPackage().getName();  32   33     /**  34      * 实际hook逻辑处理类  35      */  36     private final String handleHookClass = HookLogic.class.getName();  37     /**  38      * 实际hook逻辑处理类的入口方法  39      */  40     private final String handleHookMethod = "handleLoadPackage";  41   42     private final String initMethod = "initZygote";  43   44     private IXposedHookZygoteInit.StartupParam startupparam;  45   46     /**  47      * 重定向handleLoadPackage函数前会执行initZygote  48      *  49      * @param loadPackageParam  50      * @throws Throwable  51      */  52     @Override  53     public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {  54         // 排除系统应用  55         if (loadPackageParam.appInfo == null ||  56                 (loadPackageParam.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) == 1) {  57             return;  58         }  59         //将loadPackageParam的classloader替换为宿主程序Application的classloader,解决宿主程序存在多个.dex文件时,有时候ClassNotFound的问题  60         XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {  61             @Override  62             protected void afterHookedMethod(MethodHookParam param) throws Throwable {  63                 Context context = (Context) param.args[0];  64                 loadPackageParam.classLoader = context.getClassLoader();  65                 Class<?> cls = getApkClass(context, modulePackageName, handleHookClass);  66                 Object instance = cls.newInstance();  67                 try {  68                     cls.getDeclaredMethod(initMethod, startupparam.getClass()).invoke(instance, startupparam);  69                 }catch (NoSuchMethodException e){  70                     // 找不到initZygote方法  71                 }  72                 cls.getDeclaredMethod(handleHookMethod, loadPackageParam.getClass()).invoke(instance, loadPackageParam);  73             }  74         });  75     }  76   77     /**  78      * 实现initZygote,保存启动参数。  79      *  80      * @param startupParam  81      */  82     @Override  83     public void initZygote(IXposedHookZygoteInit.StartupParam startupParam) {  84         this.startupparam = startupParam;  85     }  86   87     private Class<?> getApkClass(Context context, String modulePackageName, String handleHookClass) throws Throwable {  88         File apkFile = findApkFile(context, modulePackageName);  89         if (apkFile == null) {  90             throw new RuntimeException("寻找模块apk失败");  91         }  92         //加载指定的hook逻辑处理类,并调用它的handleHook方法  93         PathClassLoader pathClassLoader = new PathClassLoader(apkFile.getAbsolutePath(), ClassLoader.getSystemClassLoader());  94         Class<?> cls = Class.forName(handleHookClass, true, pathClassLoader);  95         return cls;  96     }  97   98     /**  99      * 根据包名构建目标Context,并调用getPackageCodePath()来定位apk 100      * 101      * @param context           context参数 102      * @param modulePackageName 当前模块包名 103      * @return apk file 104      */ 105     private File findApkFile(Context context, String modulePackageName) { 106         if (context == null) { 107             return null; 108         } 109         try { 110             Context moudleContext = context.createPackageContext(modulePackageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 111             String apkPath = moudleContext.getPackageCodePath(); 112             return new File(apkPath); 113         } catch (PackageManager.NameNotFoundException e) { 114             e.printStackTrace(); 115         } 116         return null; 117     } 118 }

4.大功告成,开始为所欲为.

注意:有的可能会抛出"寻找apk模块失败"的异常,这是因为在findApkFile方法中传入的modulePackageName可能不是当前模块的完整包名,可以手动改成app build.gradle中appcationId的值.如:

  

   原文:https://blog.csdn.net/u011956004/article/details/78612502

   GitHub地址:https://github.com/shuihuadx/XposedHook

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!