本篇文章讲解如果真正修改手机硬件参数。
app 会通过判断当前手机的imei、mac、imsi等参数来判断此手机多次注册过app。一般情况下的权重是 imei > imsi > mac > android_id 。
Android 获取 imei 等信息的源码主要在TelephonyManager.java中,app 能获取这些参数只有这一种途径,通过adb 和shell是获取不到。所以比较简单。
获取imei

telephonyManager.getImei(){ //获取默认卡的imei ,就是当前正在联网的if(true){    从sd卡或者数据库读取动态imei[size=3]}[/size] return getImei(getSlotIndex());}[/size]public String getImei(int slotIndex) { //如果是多卡,就获取指定的imei。不知道模拟器或者双开注意要支持        ITelephony telephony = getITelephony();         if (telephony == null) return null;        try {            return telephony.getImeiForSlot(slotIndex, getOpPackageName());[/size]        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }

剩下 手机号 、 simnum 、iccid 的大概都是此方法,我已经通过下面代码验证,修改的参数完全起作用

private void imei() {        try {            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {                return;            }            String ANDROID_ID = Settings.System.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);            Log.e(TAG,"def ANDROID_ID ->" + ANDROID_ID);           String imei0 = telephonyManager.getDeviceId();            Log.e(TAG,"def myimei ->" + imei0);            String imei1 = telephonyManager.getDeviceId(1);            Log.e(TAG,"myimei1 ->" + imei1);            if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){            String imei2 = telephonyManager.getImei(0);            Log.e(TAG,"26+ imei0 ->" + imei2);}            String imsi = telephonyManager.getSubscriberId();            Log.e(TAG, "imsi ->" + imsi);            String phoneNumber = telephonyManager.getLine1Number();            Log.e(TAG, "SIM卡中存储本机号码 phoneNumber ->" + phoneNumber);            String voiceMail = telephonyManager.getVoiceMailNumber();            Log.e(TAG, "语音邮件号码 voiceMail ->" + voiceMail);            String simSerial = telephonyManager.getSimSerialNumber();            Log.e(TAG, "SIM卡序列号 simSerial ->" + simSerial);            String countryIso = telephonyManager.getNetworkCountryIso();            Log.e(TAG, "SIM卡提供商的国家代码 countryIso ->" + countryIso);            String carrier = telephonyManager.getNetworkOperatorName();            Log.e(TAG, "当前移动网络运营商 mynetname ->" + carrier);            String netid = telephonyManager.getNetworkOperator();            Log.e(TAG, "当前移动网络运营商 netid ->" + netid);            int count = telephonyManager.getPhoneCount();            Log.e(TAG, "移动卡数量 count ->" + count);            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {                String Meid = telephonyManager.getMeid();                Log.e(TAG, "移动卡数量 Meid ->" + Meid);            }            if (Build.VERSION.SDK_INT > 28) {                String nai = telephonyManager.getNai();                Log.e(TAG, "移动卡数量 Nai ->" + nai);            }            String simOperator = telephonyManager.getSimOperator();            Log.e(TAG, "SIM的移动运营商的名称 mysmo ->" + simOperator);            int phoneType = telephonyManager.getPhoneType();            Log.e(TAG, "移动终端的类型 phoneType ->" + phoneType);            int radioType = telephonyManager.getNetworkType();            Log.e(TAG, "当前使用的网络制式 radioType ->" + radioType);            String softVersion = telephonyManager.getDeviceSoftwareVersion();            Log.e(TAG, "软件版本 softVersion ->" + softVersion);            boolean Roam = telephonyManager.isNetworkRoaming();            Log.e(TAG, "漫游 Roam ->" + Roam);        } catch (Exception e) {            e.printStackTrace();        }    }

Android 修改Android_id的方法:
Android 获取的方法是
String ANDROID_ID = Settings.System.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
此参数read-only。如果使用 Settings.System.putString(this.getContentResolver(),“自定义id”);
会报错误,只需要把

public static boolean putStringForUser(@NonNull ContentResolver resolver,                @NonNull String name, [url=home.php?mod=space&uid=1043391]@nullable[/url] String value, @Nullable String tag,                boolean makeDefault, @UserIdInt int userHandle) {            if (LOCAL_LOGV) {                Log.v(TAG, "Global.putString(name=" + name + ", value=" + value                        + " for " + userHandle);            }            // Global and Secure have the same access policy so we can forward writes            if (MOVED_TO_SECURE.contains(name)) {                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global"                        + " to android.provider.Settings.Secure, value is unchanged.");                return Secure.putStringForUser(resolver, name, value, tag,                        makeDefault, userHandle);            }            return sNameValueCache.putStringForUser(resolver, name, value, tag,                    makeDefault, userHandle);        }

只需要 if (MOVED_TO_SECURE.contains(name)) {}内容注释掉即可。
Android 动态修改mac 比较麻烦
Android 获取 mac 方式有以下几种
第一种执行 shell 命令:ifconfig
第二种是

private static String getMacFromHardware() {    try {        List all = Collections.list(NetworkInterface.getNetworkInterfaces());        Log.d("Utils", "all:" + all.size());        for (NetworkInterface nif : all) {            if (!nif.getName().equalsIgnoreCase("wlan0")) {                continue;            }            byte[] macBytes = nif.getHardwareAddress();            if (macBytes == null) {                return null;            }            Log.d("Utils", "macBytes:" + macBytes.length + "," + nif.getName());            StringBuilder res1 = new StringBuilder();            for (byte b : macBytes) {                res1.append(String.format("%02X:", b));            }            if (res1.length() > 0) {                res1.deleteCharAt(res1.length() - 1);            }            return res1.toString();        }    } catch (Exception e) {        e.printStackTrace();    }    return null;}

第三种 cat /sys/class/net/wlan0/address
对于第一种 和第三种比较麻烦。如果通过修改getInetAddresses 返回动态的的 mac,无法绕过ifconfig 和 cat /sys/class/net/wlan0/address 所有我这边是直接修改mac地址,通过执行命名 ifconfig wlan0 hw ether $Mac ,修改后三种方法都起作用,不知道可有第四种通过反射的方式获取mac。但是此方法必须由root权限才行。如果手机userdebug 或者eng 就可以随便修改。如果想在代码中就可以动态修改,需要修改开机脚本。具体细节不列出了。修改 SN

public static String getSerial() {            boolean flag =SystemProperties.getBoolean("persist.sys.keep.mprop",false);                if(flag){                返回我的sn             }                }else{                IDeviceIdentifiersPolicyService service = IDeviceIdentifiersPolicyService.Stub                        .asInterface(ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE));                try {                    return service.getSerial();                } catch (RemoteException e) {                    e.rethrowFromSystemServer();                }                }        return UNKNOWN;    }

以上修改都通过我测试app 验证过。完全可以支持动态修改, 对于动态修改屏幕分辨率和密度 、sensor类型及名字 和 apk 列表都已经完成。只是个人感觉没啥作用我的这些 很方便的移植到Lineage OS 上,可以支持多款手机
。 有兴趣的可以联系我一起研究,如果还有其他修改可以留言

更多相关文章

  1. Android多进程app中Application回调onCreate()方法被执行多次分
  2. Android下使用dlopen函数动态调用.so链接库
  3. 【转】Ubuntu下Adb调试Android找不到设备的解决方法
  4. [读书笔记]布局的屏幕适配常用方法
  5. 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬
  6. Android Tv 背景动态改变,带过渡效果
  7. Android so 文件进阶 从dlsym()源码看android 动态链接过程
  8. Android使用JNI生成.so文件并调用(使用传统生成.h的方法)

随机推荐

  1. Android使用百度地图SDK
  2. Android(安卓)- 如何判断当前线程是否是
  3. Android消息传递机制浅析
  4. android AsyncTask相关的一些面试题目
  5. android studio - swiperefreshlayout注
  6. Android(安卓)error: "/usr/bin/ld: cann
  7. Android(安卓)串口通讯集成
  8. ColorFilter初探一
  9. android studio删除module
  10. 3.腾讯微博Android客户端开发——算法、