注,这篇文章是于 2023 年 6 月 15 日从最早期的 WordPress 博客迁移来的,主要是记录(证明)一下小时候折腾的各种事情吧((逃
这个app的核心在于如何通过Xposed向电源菜单的列表添加项目。
我查看了GravityBox的源代码(Github),其中修改电源菜单的类是 ModPowerMenu.java,整个重力工具箱的Xposed入口类是GravityBox.java,它初始化了所有调整类,包括 ModPowerMenu.java。
找到handleLoadPackage函数,系统每加载一个包都会调用这个函数。
里面有许多if,找到其中初始化ModPowerMenu的语句:
if (lpparam.packageName.equals(“android”) {
ModPowerMenu.init(prefs, lpparam.classLoader);
}
lpparam.packageName.equals(ModPowerMenu.PACKAGE_NAME)判断包名是个好习惯,因为系统每加载一个包都会调用这个函数,所以加载比如说微信的时候也会被调用,但我们的hook目标是android包,所以如果没有判断,程序会试图去修改别的app,导致找不到类(或函数)的异常。
当确定是android包的时候,启动调整。我们再找到ModPowerMenu.java的init函数:
首先,找到两个类:
final Class<?> globalActionsClass = XposedHelpers.findClass(CLASS_GLOBAL_ACTIONS, classLoader);
final Class<?> actionClass = XposedHelpers.findClass(CLASS_ACTION, classLoader);
这个CLASS_GLOBAL_ACTIONS是com.android.internal.policy.impl.GlobalActions类,它负责创建电源选项对话框。
CLASS_ACTION是com.android.internal.policy.impl.GlobalActions.Action,也就是上边CLASS_GLOBAL_ACTIONS的内部接口,它声明了电源菜单列表项的操作。包含以下函数:
- create 初始化列表项视图是调用,返回View
- onPress 当列表项被点击是调用
- onLongPress 当列表项长按是调用
- showDuringKeyguard 我也不知道~~
- showBeforeProvisioning 不造
- isEnabled不造
随后,使用Xposed提供的XposedBridge.hookAllConstructors方法,hook globalactionclass的构造器,逮住context等必要参数:
XposedBridge.hookAllConstructors(globalActionsClass, new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
mContext = (Context) param.args[0]; //获取构造参数0,是context
下面的不写了,挑主要的说:
Context gbContext = mContext.createPackageContext(
GravityBox.PACKAGE_NAME, Context.CONTEXT_IGNORE_SECURITY);// 这是重力工具箱自己的context
Resources res = mContext.getResources(); // 这是系统的资源
Resources gbRes = gbContext.getResources(); // 这是重力工具箱的资源
然后找到context以及资源后,找到drawable以及string,用于修改,比如说重启资源:
mRebootIcon = gbRes.getDrawable(R.drawable.ic_lock_reboot);// 从重力工具箱资源中找到重启图标
mRebootSoftStr = gbRes.getString(rebootSoftStrId);// 找到软重启文字
到此为止,初始化部分完成了。