[黑历史] GREENIFYSHUTCUT开发经历小记(1)

· 99 words · 1 minute read

注,这篇文章是于 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的内部接口,它声明了电源菜单列表项的操作。包含以下函数:

  1. create 初始化列表项视图是调用,返回View
  2. onPress 当列表项被点击是调用
  3. onLongPress 当列表项长按是调用
  4. showDuringKeyguard 我也不知道~~
  5. showBeforeProvisioning 不造
  6. 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);// 找到软重启文字

到此为止,初始化部分完成了。