Android 10(Android Q)获取IMSI遇权限异常,求解决方案
Android 10无法获取IMSI的可行替代方案
在Android 10系统中,第三方应用调用TelephonyManager.getSubscriberId()获取IMSI时会抛出如下异常:
java.lang.SecurityException: getSubscriberId: The user 10099 does not meet the requirements to access device identifiers.
这是因为Android 10(API 29)开始强化隐私保护,限制普通第三方应用获取IMSI、IMEI这类敏感设备标识符,仅系统应用、运营商应用或拥有特殊权限的预装应用才能访问。
替代方案汇总
1. 使用广告ID(Advertising ID)
适合用户行为分析、个性化广告等场景,无需特殊权限,用户可在系统设置中重置或关闭该ID。
实现代码:
import com.google.android.gms.ads.identifier.AdvertisingIdClient; import com.google.android.gms.common.GooglePlayServicesNotAvailableException; import com.google.android.gms.common.GooglePlayServicesRepairableException; import java.io.IOException; private String getAdvertisingId() { String adId = null; try { AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(this); adId = adInfo.getId(); // 可检查用户是否开启广告追踪限制 boolean isLimitAdTracking = adInfo.isLimitAdTrackingEnabled(); } catch (GooglePlayServicesNotAvailableException | GooglePlayServicesRepairableException | IOException e) { e.printStackTrace(); } return adId != null ? adId : "unknown"; }
注意:依赖Google Play服务,无Google Play服务的设备无法使用此方案。
2. 生成自定义唯一标识符
适合标识设备用户,首次启动生成UUID并持久化存储,后续复用,除非用户清除应用数据或卸载重装。
实现代码:
import java.util.UUID; import android.content.SharedPreferences; private String getCustomUniqueId() { SharedPreferences prefs = getSharedPreferences("app_core_prefs", MODE_PRIVATE); String uniqueId = prefs.getString("custom_device_id", null); if (uniqueId == null) { uniqueId = UUID.randomUUID().toString(); prefs.edit().putString("custom_device_id", uniqueId).apply(); } return uniqueId; }
3. 使用Android ID(SSAID)
Android ID是系统为每个应用分配的唯一标识符,应用卸载重装或设备重置后会变化,无需特殊权限。
实现代码:
import android.provider.Settings; private String getAndroidId() { return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); }
注意:部分设备可能返回固定默认值(如9774d56d682e549c),需做好兼容判断。
4. 运营商专属应用方案(仅特殊场景)
如果是运营商合作应用,可申请READ_PRIVILEGED_PHONE_STATE权限,但该权限仅对系统签名应用或预装应用开放,普通第三方应用无法获取,不推荐常规场景使用。
适配后的代码示例
将原有获取IMSI的逻辑替换为自定义标识符方案,示例如下:
private void getDeviceIdentifier() { Utility.DEBUG_LOG(TAG, "+ getDeviceIdentifier +"); if (this.deviceIdentifier == null) { Utility.DEBUG_LOG(TAG, "step 1"); try { // 用自定义唯一标识符替代IMSI this.deviceIdentifier = getCustomUniqueId(); Utility.DEBUG_LOG(TAG, "step 3"); if (this.deviceIdentifier == null || this.deviceIdentifier.length() == 0) { Utility.DEBUG_LOG(TAG, "deviceIdentifier:" + this.deviceIdentifier); this.deviceIdentifier = "WiFi"; } } catch (Exception e) { Utility.DEBUG_LOG(TAG, "Exception:" + e.getMessage().toString()); } Utility.DEBUG_LOG(TAG, "Device Identifier:" + this.deviceIdentifier); SharedPref.write("deviceIdentifier", this.deviceIdentifier); Constants.DEVICE_ID = this.deviceIdentifier; } } private String getCustomUniqueId() { SharedPreferences prefs = DashboardContainer.this.getSharedPreferences("app_core_prefs", MODE_PRIVATE); String uniqueId = prefs.getString("custom_device_id", null); if (uniqueId == null) { uniqueId = UUID.randomUUID().toString(); prefs.edit().putString("custom_device_id", uniqueId).apply(); } return uniqueId; }
内容的提问来源于stack exchange,提问作者Ahmad Meghani
相关产品推荐
相关产品推荐

