smali代码注入解决app界面字体显示不适配大字体设置问题
本帖最后由 tianzry 于 2018-2-24 19:57 编辑我们都知道,安卓手机是可以系统设置显示的字体大小的,用户可以根据自己的使用习惯,选择不同的字体大小,例如MIUI的字体大小里头有“巨无霸”的选项,选择这个之后,软件界面的字体会变得异常大,随之而来的换行问题,行距问题就出来了。
根据我自己的使用、开发安卓软件过程中,发现很多开发者对于“无障碍”这一块的关注不是很多,大部分都不会适配大字体的系统设置情形,这就导致设置了大字体的系统打开相同的软件时候,出现部分字体重叠、显示不全等问题,这个问题很影响用户体验。左边是没有适配大字体的情况,出现字体重叠的情况。
如果开发者一直没有做这方面的是适配,那么我们可以自己动手,改善一下。下面分享一下自己使用的比较简单的方法,内容基于我前几天修改的斐讯路由器控制软件(链接)来说:
1. 对软件进行反编译;
2. 定位字体显示异常的页面,一般来说,在MainActivity中设置一次就可以了。
我们知道,正常开发情况下,要保证软件界面显示不受系统设置的字体影响,可以在onCreate()方法中的setContentView()之前,执行如下的代码:
Resources res = super.getResources();
Configuration config = new Configuration();
config.setToDefaults();
res.updateConfiguration(config, res.getDisplayMetrics());
这样,软件界面的字体就不会随着系统设置的字体大小变化而变化了。
那么,换成smali代码,应该怎么写呢。方法很简单,就是在Android studio里面编写好,然后编译成apk,再进行反编译,即可得到对应的smali代码了。
现在的问题是,如何注入到没有源码的apk中实现修改的效果呢?一般来说可以直接将得到的代码粘贴到对应地方就可以了,但是容易出现问题,就是寄存器的申请问题,因为这几行代码用到几个寄存器;还有一个问题就是代码行的问题,因此,可以采用插入方法(method)的方式来避免这些问题,例如,上面几段代码的smali代码为:
.method public setDefaultView()V
.locals 3
.prologue
invoke-super {p0}, Landroid/support/v7/app/AppCompatActivity;->getResources()Landroid/content/res/Resources;
move-result-object v1
.local v1, "res":Landroid/content/res/Resources;
new-instance v0, Landroid/content/res/Configuration;
invoke-direct {v0}, Landroid/content/res/Configuration;-><init>()V
.local v0, "config":Landroid/content/res/Configuration;
invoke-virtual {v0}, Landroid/content/res/Configuration;->setToDefaults()V
invoke-virtual {v1}, Landroid/content/res/Resources;->getDisplayMetrics()Landroid/util/DisplayMetrics;
move-result-object v2
invoke-virtual {v1, v0, v2}, Landroid/content/res/Resources;->updateConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;)V
return-void
.end method
然后,我们将上面的代码粘贴到MainActivity.smali最后面,注意删除掉 .line xx 的标号。同时,在MainActivity.smali的onCreate方法中插入自定义的方法:
.method protected onCreate(Landroid/os/Bundle;)V
.locals 4
.prologue
.line 107
invoke-super {p0, p1}, Lcom/phicomm/zlapp/base/BaseActivity;->onCreate(Landroid/os/Bundle;)V
invoke-virtual {p0}, Lcom/phicomm/zlapp/activities/MainActivity;->setDefaultView()V
const/4 v3, 0x3
const/4 v2, 0x0
.line 108
const v0, 0x7f04001f
invoke-virtual {p0, v0}, Lcom/phicomm/zlapp/activities/MainActivity;->setContentView(I)V
......
上面的代码“invoke-virtual {p0}, Lcom/phicomm/zlapp/activities/MainActivity;->setDefaultView()V” 就是我们插入的语句。
3. 进行这样的操作之后,重新编译代码,签名,就可以正常安装,观察修改效果了。
最后有一个需要提醒的是,需要明确你修改的app的activity页面继承的是哪个类(Activity、AppCompatActivity、FragmentActivity等),我上面贴的代码就是继承AppCompatActivity的,体现在这一句:invoke-super {p0}, Landroid/support/v7/app/AppCompatActivity;->getResources()Landroid/content/res/Resources;
新手玩smali代码注入,如有说错的,欢迎指出交流。对你有用的记得评一下分哟~
学习了,感谢分享! @冥界3大法王去手机乐园下载斐讯路由器控制软件的4.2.1版本,就是我改的这个版本
学习了,感谢分享! 看了你的分析,让我受益匪浅,感谢你的提供。 谢谢分享!!!
页:
[1]