android一键改机之真改机build.prop
本篇文章讲解如果真正修改手机硬件参数。
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 上,可以支持多款手机
。 有兴趣的可以联系我一起研究,如果还有其他修改可以留言
更多相关文章
- Android多进程app中Application回调onCreate()方法被执行多次分
- Android下使用dlopen函数动态调用.so链接库
- 【转】Ubuntu下Adb调试Android找不到设备的解决方法
- [读书笔记]布局的屏幕适配常用方法
- 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬
- Android Tv 背景动态改变,带过渡效果
- Android so 文件进阶 从dlsym()源码看android 动态链接过程
- Android使用JNI生成.so文件并调用(使用传统生成.h的方法)