准备工作:
电脑上安装好JDK、下载smali和baksmali、下载apktools、要修改的ROM、adb工具(可选)
注:由于本教程面向的对象为有一定ROM修改基础的兄弟,所以对于如何使用电脑,如何使用CMD以及上述工具的具体用法等等都不在本贴的讨论范围内,本文将仅讲述如何添加高级重启菜单
1、从要修改的ROM中提取出以下文件
/system/framework/framework-res.apk
/system/framework/android.policy.jar
2、反编译修改framework-res.apk,加入需要的图片以及字符串等资源。
2.1、反编译framework-res.apk
CMD中执行命令
> java -jar apktool.jar d -s framework-res.apk framework-res
2.2、加入字符资源
英文部分(如需要则添加):使用文本编辑器打开framework-res\res\values\strings.xml,在最后添加所要用的字符串
....
<string name="reboot_recovery">Recovery</string>
</resources>
简体中文部分:使用文本编辑器打开framework-res\res\values-zh-rCN\strings.xml,在最后添加所要用的字符串
....
<string name="reboot_recovery">恢复模式</string>
</resources>
2.3、加入所需的图片
本方法将用到一张图片,显示在所加入的菜单上。
因为i88的分辨率为800×480,所以我将两张图片放入framework-res_apk\res\drawable-hdpi之中
图片的名字为(可自定义,注意上下一致即可)
ic_power_recovery.png(此处用到的图片分辨率为:48×48)
2.4、为所加入的字符及图片指定资源ID(提供两种方式,任选一种即可。个人推荐第一种)
自动指定方式:完成上述的修改后,CMD执行命令
>java -jar apktool.jar b framework-res framework-res_mod.apk
>java -jar apktool.jar d -s framework-res_mod.apk framework-res_mod
复制framework-res_mod\res\values\public.xml,用其来替换framework-res\res\values\public.xml
对应记下ID1、ID2、
<public type="string" name="reboot_recovery" id="ID1" />
<public type="drawable" name="ic_power_recovery" id="ID2" />
手动指定方式:
使用文本编辑器打开D:\PowerMenu\framework-res\res\values\public.xml
搜索<public type="string",找到string段对应的最后一个id号(请确定是最后一个),此处记为String_ID
搜索<public type="drawable",找到drawable段对应的最后一个id号(请确定是最后一个),此处记为Drawable_ID
在文件后添加两行
<public type="string" name="reboot_recovery" id="String_ID+1" />
<public type="drawable" name="ic_power_bootloader" id="Drawable_ID+1" />
根据第一种方法,在这里我获得的对应ID如下
<public type="string" name="reboot_recovery" id="0x010806b6" />
<public type="drawable" name="ic_power_recovery" id="0x010404f8" />
2.5、打包并完成对framework-res.apk的修改
CMD下执行命令
> java -jar apktool.jar b framework-res framework-res_done.apk
使用winra或7z等压缩工具,从得到的framework-res_done.apk文件中提取出resources.arsc
将resources.arsc替换framework-res.apk中的同名文件,并将ic_power_recovery.png添加到framework-res.apk中的对应位置
res\drawable-hdpi\ic_power_recovery.png
至此,对framework-res.apk的修改就完成了。保存好修改完毕的framework-res.apk。
代码修改部分
用WinRAR或者7z之类的压缩工具打开android.policy.jar,从中把classes.dex提取出来。
然后在CMD下执行命令:
> java -jar baksmali.jar classes.dex -o android.policy_dex
打开android.policy_dex\com\android\internal\policy\impl\文件夹,找到GlobalActions$打头的几个文件,记住最后一个的编号。
比如我这里看到的以GlobalActions$打头的文件的最后一个是GlobalActions$9.smali。
因为之后我们会创建一个文件,以GlobalActions$开头。
按本例的情况,会是GlobalActions$10.smali(重启进入recovery的代码)
使用文本编辑器打开android.policy_dex\com\android\internal\policy\impl\GlobalActions.smali
搜索:.method private createDialog()。这个函数是用来创建电源菜单的,既然我们是要添加菜单项,那么自然是要对这个函数进行修改。
不保证其他ROM也是一样的,这个大家在了解添加方法后,自己观察下就可以判断的,我找到的是:
.method private createDialog()Landroid/app/AlertDialog;
我发现4.0的下面的代码根本没办法直接看出哪 个是关机的代码,哪 个是重启的代码,不过我们可以用逆向追踪的方法。从创建电源菜单的代码中一定可以找到一些资源ID,复制这个ID到framework-res\res\values-zh-rCN\public.xml中搜索,很快就可以看到这个ID是做什么的(如 0x10404f2这个是定义的重启字符串,搜索前先要在前面加个0,就是0x010404f2,public.xml中的ID前面的0在这里被省略了)。这里基本就可以确定GlobalActions$3这个就是调用的重启方法了。
本例中的情况见下:
iget-object v0, p0, Lcom/android/internal/policy/impl/GlobalActions;->mItems: Ljava/util/ArrayList;
new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$2;
const v2, 0x1080030
const v3, 0x104013c
invoke-direct {v1, p0, v2, v3}, Lcom/android/internal/policy/impl/GlobalActions$2;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
.line 234
#以上为关机代码
iget-object v0, p0, Lcom/android/internal/policy/impl/GlobalActions;->mItems: Ljava/util/ArrayList;
new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$3;
const v2, 0x10802f0
const v3, 0x10404f2
invoke-direct {v1, p0, v2, v3}, Lcom/android/internal/policy/impl/GlobalActions$3;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
.line 252
#此为重启代码
不管是正常重启,还是重启到recovery,均是进行重启,只是重启时的参数不一样,重启到Recovery代码就可以参考正常重启部分的了。
new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$3;(注意这个,这个是正常重启用到的执行代码)
我们把重启的代码复制一份插入到上面重启代码的下面,也就是 .line 252这行的下面,GlobalActions$3.smali重命名为GlobalActions$10.smal。
插入的代码如下:
iget-object v0, p0, Lcom/android/internal/policy/impl/GlobalActions;->mItems: Ljava/util/ArrayList;
new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$10;
const v2, 0x10806b6
const v3, 0x10404f8
invoke-direct {v1, p0, v2, v3}, Lcom/android/internal/policy/impl/GlobalActions$10;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
对文件GlobalActions.smali的修改到这里就结束了
复制一份android.policy_dex\com\android\internal\policy\impl\GlobalActions$3.smali,重命名为GlobalActions$10.smali
打开GlobalActions$10.smali进行修改
全部GlobalActions$3都修改为GlobalActions$10.smali
const-string v1, "null"修改为const-string v1, "recovery"
因为我的只有两个参数,如果你的有三个参数还要修改一下,红色标记部分为修改部份,可以直接删除不要这个参数,保留的话要先在strings.xml中定义。
Lcom/android/internal/policy/impl/GlobalActions$SinglePressAction;-><init>(II)V II表示两个参数
.parameter "x0"
.parameter "x1"
.parameter "x2"(比正常重启项少一个参数,该参数是每项下方的那个提示文字,这个我的没有)
invoke-direct {p0, p2, p3, p4},
修改好保存退出,添加重启到recovery的执行代码文件就完成了。
保存上面所做的修改,开始进行打包
CMD下执行命令:
> java -jar smali.jar android.policy_dex -o classes.dex
然后WinRAR或者7z之类的压缩工具打开android.policy.jar,使用修改得到classes.dex替换原文件。
OK,到这里,对android.policy.jar的修改也完成了。
最后把修改好的两个文件替换到手机看看效果吧,怎么换我就不说了