0%

Xposed开发之检查模块是否启用

个人开发的 Xposed 模块中,确实有检查自己模块是否已启用的需求,那么该如何实现呢?

思路分析

最直接思路就是直接去 Xposed Installer 的模块列表里面,自己的模块是否已被勾选。那么, Xposed Installer 有提供相关 api 调用来返回某模块是否被勾选吗?答案是,没有。

那么,能不能 Hook Xposed Installer 的模块列表界面,从而获取是否被勾选呢? 想到这里的时候其实是把此问题复杂化了:只要能 Hook 成功了,就说明自己模块已经启用了,那么何不 Hook 自己的模块应用本身呢? 这样也避免了还需要去逆向 Xposed Installer 的麻烦。

想到这里,其实整个问题都已经迎刃而解了。

编程实现

当前模块相关的工具类 ModuleUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class ModuleUtils {

private ModuleUtils() {}

/**
* 返回模块版本
* 注意:该方法被本模块Hook住,返回的值是 BuildConfig.MODULE_VERSION,如果没被Hook则返回-1
*/
private static int getModuleVersion() {
return -1;
}

/**
* 当前模块是否在XposedInstaller中被启用
*/
public static boolean isModuleEnabled() {
return getModuleVersion() > 0;
}
}

ModuleUtils.isModuleEnabled() 正常条件下一定是返回 false 的,而我们接下来要做的就是去 Hook getModuleVersion() 方法,让其在已启用的情况下返回正值,这样就能通过 isModuleEnabled() 判断模块是否已经启用了。

ModuleUtilsHook 用来 Hook ModuleUtils

1
2
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 是在项目 modulebuild.gradle 自定义的:

1
2
3
4
5
6
7
android {
// ...
defaultConfig {
// ...
buildConfigField("int", "MODULE_VERSION", "18")
}
}

最后,因为 ModuleUtilsHook 在 Hook 过程中用到了反射,所以不应该混淆 ModuleUtilsgetModuleVersion 方法:

1
2
3
-keep class com.github.tianma8023.xposed.smscode.utils.ModuleUtils {
int getModuleVersion();
}

源码请戳 ModuleUtilsHook