Physical Address:
ChongQing,China.
WebSite:

反编译安卓应用以实现文案语言转换的工程实践。

在近期某个项目中,接收到一个比较奇葩的需求,需要在不修改源码的情况下替换所有的文案为俄文。
接到该需求时,第一反应便是需要修改资源包,通常而言每个应用的所有文本内容都会放到res目录下对应的资源文件夹内,如下所示:
values-zh-rCN //中国大陆地区
values-zh-rHK //中国香港地区
values-zh-rTW //中国台湾地区
正向思维来看,我们需要新增对应地区的语言资源文件夹,将相应的文案进行对应翻译,放入该文件夹,之后重新进行编译打包,再进行签名,后续进行安装就能看到效果了。
以上建立在我们拥有源码工程及对应的签名文件的情况下,如果没有源码去实现这个需求,就只能通过反编译的手段来实现了。
此时我们需要借助apktool这个工具,apktool 是一个非常常用的Android 逆向工程工具,主要用于反编译 APK(Android 应用安装包),以便查看、修改、重新打包和调试应用资源及 Smali 代码。它常被用于分析 APK 的结构、修改界面文字、多语言适配、甚至研究某些应用的实现逻辑。
总的来说,要实现这个目的需要经历如下步骤:
1.首先确定需要进行文案替换的应用具体是哪一个,此时我们可以先打开该应用,使其位于前台,再通过如下命令确认位于前台的应用所对应的包名:
adb shell dumpsys activity activities | grep mResumedActivity
//获取当前出于Resume状态的应用
pissarropro:/ $ dumpsys activity activities | grep mResumedActivity
mResumedActivity: ActivityRecord{dc6c83a u0 com.android.chrome/com.google.android.apps.chrome.Main t8188}
pissarropro:/ $
2.根据前述步骤拿到的包名,找到系统内对应的APK路径,通过ADB工具拉取该APK
//找到APK对应的路径
pissarropro:/ $ pm list packages -f | grep "com.android.chrome"
package:/data/app/~~rf1cFFBb7xWuaYGMDZ2S_w==/com.android.chrome-CarZF9ibWgDes2CEjGjyXA==/base.apk=com.android.chrome
pissarropro:/ $
//拉取该APK
adb pull /data/app/~~rf1cFFBb7xWuaYGMDZ2S_w==/com.android.chrome-CarZF9ibWgDes2CEjGjyXA==/base.apk
3.通过apk tool对拉取出来的APK进行反编译:
apktool d CarControl.apk -o OUTPUT
如果在执行上述命令的过程中出现如下错误:
Can't find framework resources for package of id: 2. You must install proper framework files
出现该错误的原因是因为APK本身依赖了一些系统资源,APKTool在解析这些资源时,找不到对应的framework资源文件,此时我们就需要从系统中找到这些资源文件并进行安装,以便APKTool进行解析。
通常而言,framework的资源文件位于framework-res.apk内,我们可以通过如下命令进行拉取:
adb pull /system/framework/framework-res.apk
对于不同的厂商而言,每个厂商还有自己定制的framework资源文件,这些资源文件也需要拉取:
//华为
adb pull /system/framework/hwext-res.apk
//小米
adb pull /system/framework/miui-framework-res.apk
拿到上述资源后,我们再进行安装:
apktool if framework-res.apk
apktool if framework-res-ext.apk
安装完成之后我们再进行反编译,得到如下内容:
AndroidManifest.xml
apktool.yml
assets/
original/
res/
unknown/
之后我们找到res/values-zh-rCN/strings.xml文件,将该文件内的中文内容进行翻译修改,直接将其修改为对应的语言文本即可。
修改完成之后,我们需要使用apktool重新进行打包,使用如下命令进行打包:
Apktool b OUTPUT -o CarControl_New.apk
这样我们就得到了新的APK,接下来我们需要注意,如果直接重新安装应用,大概率是会安装失败的,因为我们并没有原始的签名,所以这里只能是将新生成的APK进行推入。之后我们重新启动应用,就可以看到效果了。
更进一步,我们来了解一下apktool的具体工作原理,apktool其实是一个工具的组合,可以对APK进行解包与打包操作。在解包操作中,apktool会进行如下步骤:
在经过上述步骤后,我们可以拿到AndroidManifest.xml,修改权限申请、入口Activity等内容;同时也拿到了res资源文件,我们可以修改对应的资源文件,实现不同的文案显示、颜色样式等;更进一步我们可以直接修改smali文件,实现逻辑修改、去广告等操作。
后记
在解决该问题的过程中,除了apktool,我们还可以用APKEditor。相对于apktool,APKEditor更适合这种简单的文案修改工作,使用起来也会更得心应手。
除了使用这种反编译的方式修改APK资源,我们还可以用Overlay的方法实现该需求,这种方式更为合理,对系统的侵入修改会更小。对于Overlay的具体原理可以参考我的另一篇文章,此处不做过多赘述,这里只列举一下大概的流程:
1.新建APK,无需Activity、Service等内容,只需将values-zh-rCN/strings.xml内容放置于res目录
2.配置AndroidManifest.xml,内容可参考如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.seres.settings.overlay">
<overlay
android:targetPackage="com.android.settings"
android:priority="999"
android:isStatic="true" />
</manifest>
3.打包APK,无Root情况下需要同样的系统签名;Root情况下可以手动推入系统
4.使用adb shell cmd overlay list查看是否生效:
franzkafka@franzkafka:~$ adb shell cmd overlay list
com.android.uwb.resources
[x] com.android.uwb.resources.cuttlefish.overlay
com.android.connectivity.resources
[x] com.android.connectivity.resources.cuttlefish.overlay
android
[x] android.cuttlefish.overlay
[x] android.cuttlefish.phone.overlay
[ ] com.android.internal.display.cutout.emulation.corner
[ ] com.android.internal.display.cutout.emulation.double
[ ] com.android.internal.systemui.navbar.gestural_wide_back
[ ] com.android.internal.display.cutout.emulation.hole
[ ] com.android.internal.display.cutout.emulation.tall
[ ] com.android.internal.systemui.navbar.threebutton
[ ] com.android.internal.systemui.navbar.gestural_extra_wide_back
[ ] com.android.theme.font.notoserifsource
[ ] com.android.internal.display.cutout.emulation.waterfall
[ ] com.android.internal.systemui.navbar.transparent
[ ] com.android.role.notes.enabled
[ ] com.android.internal.systemui.navbar.gestural
[ ] com.android.internal.systemui.navbar.gestural_narrow_back
[x] com.android.systemui:neutral
[x] com.android.systemui:accent
[x] com.android.systemui:dynamic
com.android.nfc
[x] com.android.nfc.cuttlefish.overlay
com.android.providers.settings
[x] com.android.providers.settings.cuttlefish.overlay
com.android.wifi.resources
[x] com.android.wifi.resources.cf
com.android.networkstack.tethering
[x] com.android.networkstack.tethering.cuttlefishoverlay
com.android.systemui
[x] com.android.systemui.auto_generated_rro_vendor__