Android使用TelephonyManager获取设备信息触发SecurityException问题求助
问题:Android获取MEID/IMEI时触发SecurityException,UID无访问权限
错误信息
E/SecurityException Error(29502): Security Exception: IMEI access not permitted E/SecurityException Error(29502): java.lang.SecurityException: getMeidForSlot: The uid 11222 does not meet the requirements to access device identifiers. E/SecurityException Error(29502): at android.os.Parcel.createExceptionOrNull(Parcel.java:3023) E/SecurityException Error(29502): at android.os.Parcel.createException(Parcel.java:3007) E/SecurityException Error(29502): at android.os.Parcel.readException(Parcel.java:2990) E/SecurityException Error(29502): at android.os.Parcel.readException(Parcel.java:2932) E/SecurityException Error(29502): at com.android.internal.telephony.ITelephony$Stub$Proxy.getMeidForSlot(ITelephony.java:10794) E/SecurityException Error(29502): at android.telephony.TelephonyManager.getMeid(TelephonyManager.java:2898) E/SecurityException Error(29502): at android.telephony.TelephonyManager.getMeid(TelephonyManager.java:2855) E/SecurityException Error(29502): at com.example.sim_iccid_demo.MainActivity.getIccidList(MainActivity.kt:50) E/SecurityException Error(29502): at com.example.sim_iccid_demo.MainActivity.configureFlutterEngine$lambda-0(MainActivity.kt:24) E/SecurityException Error(29502): at com.example.sim_iccid_demo.MainActivity.$r8$lambda$8Tzl3un6utopCfe_BwLm26cMOFo(Unknown Source:0) E/SecurityException Error(29502): at com.example.sim_iccid_demo.MainActivity$$ExternalSyntheticLambda0.onMethodCall(Unknown Source:2) E/SecurityException Error(29502): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258) E/SecurityException Error(29502): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295) E/SecurityException Error(29502): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322) E/SecurityException Error(29502): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12) E/SecurityException Error(29502): at android.os.Handler.handleCallback(Handler.java:942) E/SecurityException Error(29502): at android.os.Handler.dispatchMessage(Handler.java:99) E/SecurityException Error(29502): at android.os.Looper.loopOnce(Looper.java:226) E/SecurityException Error(29502): at android.os.Looper.loop(Looper.java:313) E/SecurityException Error(29502): at android.app.ActivityThread.main(ActivityThread.java:8757) E/SecurityException Error(29502): at java.lang.reflect.Method.invoke(Native Method) E/SecurityException Error(29502): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) E/SecurityException Error(29502): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
问题背景
开发SIM卡及设备信息相关功能时触发上述错误,该功能在Android 10及以下版本正常运行,但需要适配全版本获取设备信息及ICCID,已按官方要求配置权限。
已配置的权限(AndroidManifest.xml)
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" /> <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
实现代码
private Map<String, String> getSimInfo() { Map<String, String> simInfo = new HashMap<>(); try { SubscriptionManager subsManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); List<SubscriptionInfo> subsList = subsManager.getActiveSubscriptionInfoList(); if (subsList != null) { for (SubscriptionInfo subsInfo : subsList) { String iccid = subsInfo.getIccId(); if (iccid != null) { simInfo.put("ICCID" + subsInfo.getSimSlotIndex(), iccid); } } } String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); simInfo.put("AndroidID", androidId != null ? androidId : "N/A"); simInfo.put("MEID","N/A"); simInfo.put("IMEI","N/A"); TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String meid = telephonyManager.getSimSerialNumber(); simInfo.put("MEID", meid != null ? meid : "N/A"); if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM)) { try { String imei = telephonyManager.getImei(); Log.d("IMEI DATA", imei); simInfo.put("IMEI", imei != null ? imei : "N/A"); } catch (SecurityException e) { handleException("IMEI access not permitted", e); } } } catch (SecurityException e) { handleException("IMEI access not permitted", e); } catch (Exception e) { handleException("An error occurred", e); } return simInfo; }
解决方案
核心原因
Android 10(API 29)及以上版本对设备标识符(IMEI/MEID等)做了强制限制:
- 普通第三方应用无法通过
READ_PHONE_STATE获取IMEI/MEID READ_PRIVILEGED_PHONE_STATE仅系统应用或签名级权限应用可使用,普通应用无法获取
针对性修复方案
1. 分版本处理设备标识符获取
Android 10+放弃直接获取IMEI/MEID,改用AndroidID作为替代;仅在Android 9及以下版本尝试获取:
// 修改getSimInfo方法中的设备标识逻辑 TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // Android 9及以下版本尝试获取MEID/IMEI try { String meid = telephonyManager.getMeid(); simInfo.put("MEID", meid != null ? meid : "N/A"); if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM)) { String imei = telephonyManager.getImei(); simInfo.put("IMEI", imei != null ? imei : "N/A"); } } catch (SecurityException e) { handleException("设备标识访问被拒绝", e); } } else { // Android 10+仅保留AndroidID simInfo.put("MEID", "N/A"); simInfo.put("IMEI", "N/A"); }
2. 清理无效权限
移除普通应用无法使用的权限,避免冗余:
<!-- 移除以下权限 --> <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" />
3. 确保ICCID权限正常
你的ICCID获取逻辑是正确的,Android 10+仍可通过SubscriptionManager获取,但需确保已动态申请READ_PHONE_STATE权限:
// 动态申请权限示例 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1001); }
关键注意事项
- Android 10+普通应用无法获取IMEI/MEID,这是系统强制限制,无绕过方法
- 若业务需唯一设备标识,优先使用
AndroidID或第三方标识方案(如Firebase Instance ID) - ICCID获取不受Android 10+严格限制,只要正确申请
READ_PHONE_STATE即可正常获取
内容的提问来源于stack exchange,提问作者user21218693
相关产品推荐
相关产品推荐

