解决Xposed框架拦截修改Build.MODEL手机型号失败问题

在使用Xposed框架拦截修改Build系列的静态值一直很顺利,一直到拦截修改MODEL手机机型这个静态变量的sh时候出现问题,博主发现,通过正常的途径以及采用映射都无法修改点手机机型,遂一直努力查找技术文档攻克,终于功夫不负有心人,解决了该问题。闲话少说,上代码。

博主具体参考一款插件“应用变量”来做讲解,具体的项目地址参考应用变量

package com.sollyu.android.appenv.helper;

import android.os.Build;
import android.support.annotation.RequiresApi;

import java.util.HashMap;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

/**
 * 作者: Sollyu
 * 时间: 16/10/20
 * 联系: [email protected]
 * 说明:
 */
public class XposedHookHelper {

    private static final String TAG = "AppEnv";

    public BuildImpl     Build     = null;
    public TelephonyImpl Telephony = null;
    public WifiImpl      Wifi      = null;
    public SettingsImpl  Settings  = null;

    private XC_LoadPackage.LoadPackageParam loadPackageParam = null;

    private static XposedHookHelper instances = null;

    @RequiresApi(api = android.os.Build.VERSION_CODES.CUPCAKE)
    private XposedHookHelper(XC_LoadPackage.LoadPackageParam loadPackageParam) {
        this.loadPackageParam = loadPackageParam;

        Build     = new BuildImpl();
        Telephony = new TelephonyImpl();
        Wifi      = new WifiImpl();
        Settings  = new SettingsImpl();
    }

    @RequiresApi(api = android.os.Build.VERSION_CODES.CUPCAKE)
    public static XposedHookHelper getInstances(XC_LoadPackage.LoadPackageParam loadPackageParam) {
        if (instances == null){
            instances = new XposedHookHelper(loadPackageParam);
        }
        return instances;
    }

    public XC_LoadPackage.LoadPackageParam getLoadPackageParam() {
        return loadPackageParam;
    }


    /**
     * android.os.Build 拦截
     */
    @SuppressWarnings("WeakerAccess")
    public class BuildImpl {
        public VersionImpl Version = new VersionImpl();

        public HashMap hashMap = new HashMap<>();

        private BuildImpl() {
            XposedBridge.hookAllMethods(XposedHelpers.findClass("android.os.SystemProperties", getLoadPackageParam().classLoader), "get", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    if (hashMap.containsKey(param.args[0].toString())) {
                        param.setResult(hashMap.get(param.args[0].toString()));
                    }
                }
            });
        }

        public void MANUFACTURER(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "MANUFACTURER", value);
            hashMap.put("ro.product.manufacturer", value);
        }

        public void BRAND(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "BRAND", value);
            hashMap.put("ro.product.brand", value);
        }

        public void BOOTLOADER(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "BOOTLOADER", value);
            hashMap.put("ro.bootloader", value);
        }

        public void MODEL(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "MODEL", value);
            hashMap.put("ro.product.model", value);
        }

        public void DEVICE(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "DEVICE", value);
            hashMap.put("ro.product.device", value);
        }

        public void DISPLAY(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "DISPLAY", value);
            hashMap.put("ro.build.display.id", value);
        }

        public void PRODUCT(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "PRODUCT", value);
            hashMap.put("ro.product.name", value);
        }

        public void BOARD(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "BOARD", value);
            hashMap.put("ro.product.board", value);
        }

        public void HARDWARE(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "HARDWARE", value);
            hashMap.put("ro.hardware", value);
        }

        public void SERIAL(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "SERIAL", value);
            hashMap.put("ro.serialno", value);
        }

        public void TYPE(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "TYPE", value);
            hashMap.put("ro.build.type", value);
        }

        public void TAGS(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "TAGS", value);
            hashMap.put("ro.build.tags", value);
        }

        public void FINGERPRINT(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "FINGERPRINT", value);
            hashMap.put("ro.build.fingerprint", value);
        }

        public void USER(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "USER", value);
            hashMap.put("ro.build.user", value);
        }

        public void HOST(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "HOST", value);
            hashMap.put("ro.build.host", value);
        }

        public class VersionImpl {
            private VersionImpl() {
            }

            public void INCREMENTAL(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "INCREMENTAL", value);
                hashMap.put("ro.build.version.incremental", value);
            }

            public void RELEASE(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "RELEASE", value);
                hashMap.put("ro.build.version.release", value);
            }

            public void BASE_OS(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "BASE_OS", value);
                hashMap.put("ro.build.version.base_os", value);
            }

            public void SECURITY_PATCH(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "SECURITY_PATCH", value);
                hashMap.put("ro.build.version.security_patch", value);
            }

            public void SDK(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "SDK", value);
                hashMap.put("ro.build.version.sdk", value);
            }

            public void CODENAME(String value) {
                XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "CODENAME", value);
                hashMap.put("ro.build.version.all_codenames", value);
            }

            public void SDK_INT(int value) {
                XposedHelpers.setStaticIntField(android.os.Build.VERSION.class, "SDK_INT", value);
            }
        }
    }

    @SuppressWarnings("WeakerAccess")
    public static class TelephonyImpl {
        private TelephonyImpl() {
        }

        public void getDeviceId(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getDeviceId", new XC_ResultHook(value));
        }

        public void getDeviceSoftwareVersion(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getDeviceSoftwareVersion", new XC_ResultHook(value));
        }

        public void getLine1Number(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getLine1Number", new XC_ResultHook(value));
        }

        public void getMmsUAProfUrl(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getMmsUAProfUrl", new XC_ResultHook(value));
        }

        public void getMmsUserAgent(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getMmsUserAgent", new XC_ResultHook(value));
        }

        public void getNetworkCountryIso(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getNetworkCountryIso", new XC_ResultHook(value));
        }

        public void getNetworkOperator(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getNetworkOperator", new XC_ResultHook(value));
        }

        public void getNetworkOperatorName(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getNetworkOperatorName", new XC_ResultHook(value));
        }

        public void getSimCountryIso(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSimCountryIso", new XC_ResultHook(value));
        }

        public void getSimOperator(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSimOperator", new XC_ResultHook(value));
        }

        public void getSimOperatorName(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSimOperatorName", new XC_ResultHook(value));
        }

        public void getSimSerialNumber(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSimSerialNumber", new XC_ResultHook(value));
        }

        public void getSubscriberId(String value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSubscriberId", new XC_ResultHook(value));
        }

        public void getCallState(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getCallState", new XC_ResultHook(value));
        }

        public void getDataNetworkType(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getDataNetworkType", new XC_ResultHook(value));
        }

        public void getDataState(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getDataState", new XC_ResultHook(value));
        }

        public void getNetworkType(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getNetworkType", new XC_ResultHook(value));
        }

        public void getPhoneCount(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getPhoneCount", new XC_ResultHook(value));
        }

        public void getPhoneType(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getPhoneType", new XC_ResultHook(value));
        }

        public void getSimState(int value) {
            XposedBridge.hookAllMethods(android.telephony.TelephonyManager.class, "getSimState", new XC_ResultHook(value));
        }
    }

    @SuppressWarnings("WeakerAccess")
    public static class WifiImpl {
        public InfoImpl Info = new InfoImpl();

        private WifiImpl() {
        }

        public void enableNetwork(boolean returnStatus) {
            XposedBridge.hookAllMethods(android.net.wifi.WifiManager.class, "enableNetwork", new XC_ResultHook(returnStatus));
        }

        public void disableNetwork(boolean returnStatus) {
            XposedBridge.hookAllMethods(android.net.wifi.WifiManager.class, "disableNetwork", new XC_ResultHook(returnStatus));
        }

        public void getWifiState(int returnStatus) {
            XposedBridge.hookAllMethods(android.net.wifi.WifiManager.class, "getWifiState", new XC_ResultHook(returnStatus));
        }

        public static class InfoImpl {
            private InfoImpl() {
            }

            public void getSSID(String value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getSSID", new XC_ResultHook(value));
            }

            public void getBSSID(String value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getBSSID", new XC_ResultHook(value));
            }

            public void getMacAddress(String value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getMacAddress", new XC_ResultHook(value));
            }

            public void getIpAddress(int value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getIpAddress", new XC_ResultHook(value));
            }

            public void getFrequency(int value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getFrequency", new XC_ResultHook(value));
            }

            public void getLinkSpeed(int value) {
                XposedBridge.hookAllMethods(android.net.wifi.WifiInfo.class, "getLinkSpeed", new XC_ResultHook(value));
            }
        }
    }

    @RequiresApi(api = android.os.Build.VERSION_CODES.CUPCAKE)
    @SuppressWarnings("WeakerAccess")
    public static class SettingsImpl {
        public SystemImpl System = new SystemImpl();

        private SettingsImpl() {
        }

        @SuppressWarnings("WeakerAccess")
        public static class SystemImpl {
            private HashMap hashMap = new HashMap<>();

            @RequiresApi(api = android.os.Build.VERSION_CODES.CUPCAKE)
            private SystemImpl() {
                XposedBridge.hookAllMethods(android.provider.Settings.System.class, "getString", new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        if (param.args.length > 1 && param.args[1] != null && hashMap.containsKey(param.args[1].toString())) {
                            param.setResult(hashMap.get(param.args[1].toString()));
                        }
                    }
                });

                XposedBridge.hookAllMethods(android.provider.Settings.Secure.class, "getString", new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        if (param.args.length > 1 && param.args[1] != null && hashMap.containsKey(param.args[1].toString())) {
                            param.setResult(hashMap.get(param.args[1].toString()));
                        }
                    }
                });
            }

            public void getString(String keyName, String value) {
                hashMap.put(keyName, value);
            }
        }
    }

    private static class XC_ResultHook extends XC_MethodHook {
        private Object resultObject = null;

        XC_ResultHook(Object resultObject) {
            this.resultObject = resultObject;
        }

        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            if (resultObject != null)
                param.setResult(resultObject);
        }
    }
}

 以上代码是项目“应用变量”的XposedHookHelper.java文件

其中关键代码为:

使用了HashMap存放Build中的静态变量,然后通过判断HashMap中的键值是否存在,存在则去修改返回结果

XposedBridge.hookAllMethods(XposedHelpers.findClass("android.os.SystemProperties", getLoadPackageParam().classLoader), "get", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    if (hashMap.containsKey(param.args[0].toString())) {
                        param.setResult(hashMap.get(param.args[0].toString()));
                    }
                }
            });

把MODEL值存放进HashMap

 public void MODEL(String value) {
            XposedHelpers.setStaticObjectField(android.os.Build.class, "MODEL", value);
            hashMap.put("ro.product.model", value);
        }

解析上面两句代码,我们可以得出:

”应用变量“首先通过setStaticObjectField()方法设置了自定义值,然后又通过setResult()方法修改了get方法的返回值,以此达到了修改Build.MODEL的目的。

看到这里是不是恍然大悟了呢?所以赶快去试试吧。

最后非常感谢项目”应用变量“的作者kingsollyu,如果使用该文章请标明出处!

你可能感兴趣的:(解决Xposed框架拦截修改Build.MODEL手机型号失败问题)