个人开发的 Xposed 模块中,确实有检查自己模块是否已启用的需求,那么该如何实现呢?
思路分析
最直接思路就是直接去 Xposed Installer 的模块列表里面,自己的模块是否已被勾选。那么, Xposed Installer 有提供相关 api 调用来返回某模块是否被勾选吗?答案是,没有。
那么,能不能 Hook Xposed Installer 的模块列表界面,从而获取是否被勾选呢? 想到这里的时候其实是把此问题复杂化了:只要能 Hook 成功了,就说明自己模块已经启用了,那么何不 Hook 自己的模块应用本身呢? 这样也避免了还需要去逆向 Xposed Installer 的麻烦。
想到这里,其实整个问题都已经迎刃而解了。
编程实现
当前模块相关的工具类 ModuleUtils
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | public class ModuleUtils {
 
 private ModuleUtils() {}
 
 
 
 
 
 private static int getModuleVersion() {
 return -1;
 }
 
 
 
 
 public static boolean isModuleEnabled() {
 return getModuleVersion() > 0;
 }
 }
 
 | 
ModuleUtils.isModuleEnabled() 正常条件下一定是返回 false 的,而我们接下来要做的就是去 Hook  getModuleVersion() 方法,让其在已启用的情况下返回正值,这样就能通过 isModuleEnabled() 判断模块是否已经启用了。
ModuleUtilsHook 用来 Hook ModuleUtils: 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | public class ModuleUtilsHook implements IXposedHookLoadPackage {
 private static final String SMSCODE_PACKAGE = BuildConfig.APPLICATION_ID;
 private static final int MODULE_VERSION = BuildConfig.MODULE_VERSION;
 
 @Override
 public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
 
 if (SMSCODE_PACKAGE.equals(lpparam.packageName)) {
 try {
 XLog.i("Hooking current Xposed module status...");
 hookModuleUtils(lpparam);
 } catch (Throwable e) {
 XLog.e("Failed to hook current Xposed module status.");
 }
 }
 
 }
 
 private void hookModuleUtils(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
 String className = ModuleUtils.class.getName();
 
 XposedHelpers.findAndHookMethod(className, lpparam.classLoader,
 "getModuleVersion",
 XC_MethodReplacement.returnConstant(MODULE_VERSION));
 }
 }
 
 | 
其中上面的 MODULE_VERSION 是在项目 module 的 build.gradle 自定义的:
| 12
 3
 4
 5
 6
 7
 
 | android {
 defaultConfig {
 
 buildConfigField("int", "MODULE_VERSION", "18")
 }
 }
 
 | 
最后,因为 ModuleUtilsHook 在 Hook 过程中用到了反射,所以不应该混淆 ModuleUtils 的 getModuleVersion 方法:
| 12
 3
 
 | -keep class com.github.tianma8023.xposed.smscode.utils.ModuleUtils {int getModuleVersion();
 }
 
 | 
源码请戳 ModuleUtilsHook