抱歉,Xposed真的可以为所欲为——2.改为OV机型流畅玩耍高帧率王者农药

6,618 阅读5分钟

一句话概括本文

只需20行代码,利用Xposed Hook掉王者农药王者获取手机系统机型的方法, 改成OV系的系统,以此达到流畅玩耍高帧率的目的。


引言

王者农药的新赛季又到了,本来这篇是昨晚应该撸出来的,后来因为改机型 后玩得太嗨,都没怎么写,惭愧:

其实关于该机型优化已经不是什么新鲜事了,不过前几天在知乎上看到过话题: 如何看待 360 手机为「优化」腾讯游戏体验,在游戏模式中把自己的型号改成了 vivo? 然后呢,你应该会好奇为什么360要这么做,看到答题区的这几个图你应该就懂了:

这个中什么PY交易我不关心,我只知道把系统改成Oppo或者Vivo机型的,就可以 有多核优化和高帧率模式。然后呢,如果你手机Root了的话,直接打开 system/build.prop,修改系统相关的信息,品牌,机型,系统版本等:

然后呢,记得先备份,而且改了的话,有些改完手机是会GG的,比如摄像头 用不了的等,所以并不是最优方案,这个时候idea来了,如果Hook掉王者荣耀 获取手机机型的方法,直接让该方法返回ov系列的机型信息不就可以了? 还记得xposed里有个setResult()设置返回值的方法吧。套路就这样 接下来就是一顿推敲了。


1.胡乱分析

分析下怎么获得设备品牌与版本号的方法,这个谷歌或者百度一搜就有了, 都是通过android.os.Build.xxx获得:

点进去Build类的源码看看:

嗯,都是static修饰的静态成员,最简单的就是直接通过Xposed提供的setStaticObjectField 直接修改成我们想要的值,我们可以把Build里的静态成员都打印出来,看下哪些是需要 我们自行修改的:

输出结果:(依次为魅蓝E2和Oppo R9s)

对比得出需要修改如下字段:

  • MANUFACTURERBRAND ==> OPPO
  • PRODUCTDEVICE ==> R9s
  • MODEL ==> OPPO R9s

如果要修改系统版本号:对应RELEASESDKSDK_INT字段 知道干什么了,接着就可以开始写代码了,代码非常简单:

运行重启一波,打开我们自己的模块,看看打印的Log:

可以,修改成功,打开酷(基)安看看,依次点击我->更多->我的机型,(¯﹃¯)

滑稽,接着打开手机QQ,随便发送一条说说,看下带的后缀是什么机型:


2.打开王者农药验证

接着就到我们的王者荣耀了,把画质调到最高,高帧率模式打开:

先不改机型,用魅蓝色试试

这是真的感人,最高帧50,经常掉到30帧左右,特别打团的时候,最低跌到27帧, 还提示画质降低,我也是服...接着改成Oppo r11 plus试试?

实测,场景不怎么复杂的时候60帧,平时基本处于50帧以上,打团的时候 也稳定在40帧以上,没有出现过画质降低的提示~

So,改改机型就可以爽翻天,里面的PY交易,你我都心知肚明


3.有个问题

一般呢,普通的APP到上面就完了,如果开发者皮一下,不是直接调Build.MODEL 这种获取方法,而是通过反射呢?比如这样的代码:

这个时候拿到的还是原来的机型:

我们的设置就不会生效了,于是乎我们还需要Hook掉这个getString方法

此时拿到的就是修改后的机型了

当然我是不会满足的,在源码里看到:

我对继续点进去,看下**get()**方法

再跟下去:

这里的native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在 当前文件,而是在用其他语言(如C和C++)实现的文件中。如果是改的话需要通过 JNI了,显然我们到了这里就够了,直接hook这个**native_get()**方法,然后返回品牌 或者机型。

再修改下xposed里的代码:

运行重启:

可以很稳,Hook到这里就差不多了,接着加上包名判断,如果打开的 是王者荣耀才去改机型,这里加上酷安的包名,后续真的拿来玩农药 的话再自行去掉吧。

分别打开酷安和设置里的关于手机

OK,没毛病。


4.小结

代码非常简单,20行左右的代码就可以畅玩王者农药了,在此过程中有遇到 两个问题,要说明下:

  • 1.低版本,hook方法不一定生效,所以还是需要静态设置那部分的代码
  • 2.有时重启后代码并没有生效,xposed Installer那里建议关下插件再开,然后再重启

我只是研究技术细节怎么实现的,并不会去完善这个项目,有兴趣的自行扩展, 比如加上应用和机型选择等,在撸这一篇的时候大部分参考的是这个开源项目: github.com/kingsollyu/… 他有个更完善的开源项目(应用变量Xposed插件): github.com/kingsollyu/… 感谢开源作者的开源精神~


附:最终代码(都可以在:github.com/coder-pig/C… 找到):

class XposedInit : IXposedHookLoadPackage {
    @SuppressLint("PrivateApi")
    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
        when(lpparam.packageName) {
            "com.tencent.tmgp.sgame","com.coolapk.market" -> {
                //兼容低版本
                setStaticObjectField(Build::class.java, Constant.MANUFACTURER, "OPPO")
                setStaticObjectField(Build::class.java, Constant.BRAND, "OPPO")
                setStaticObjectField(Build::class.java, Constant.PRODUCT, "R11 Plus")
                setStaticObjectField(Build::class.java, Constant.DEVICE, "R11 Plus")
                setStaticObjectField(Build::class.java, Constant.MODEL, "OPPO R11 Plus")
                //应对反射获取机型的情况
                val c = Class.forName("android.os.SystemProperties")
                val m = c.getDeclaredMethod("native_get", String::class.java, String::class.java)
                m.isAccessible = true
                XposedBridge.hookMethod(m, object : XC_MethodHook() {
                    override fun afterHookedMethod(param: MethodHookParam) {
                        when (param.args[0].toString()) {
                            "ro.product.manufacturer", "ro.product.brand" -> param.result = "OPPO"
                            "ro.product.name", "ro.product.device" -> param.result = "R11 Plus"
                            "ro.product.model" -> param.result = "OPPO R11 Plus"
                        }
                    }
                })
            }
        }
    }
}