You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android API29+真机无法通过Kotlin获取SIM手机号与IMSI求助

Android API 29+ 真机无法获取SIM手机号和IMSI的解决方案

核心原因

Android 10(API29)开始对隐私权限做了严格收紧:

  • 普通第三方应用无法通过READ_PHONE_STATE权限获取手机号(line1Number)和IMSI(subscriberId),这些属于高度敏感的用户隐私信息,系统直接限制访问。
  • READ_PRIVILEGED_PHONE_STATE 是系统级权限,仅对系统应用、厂商预装应用开放,普通APP即使在Manifest声明也无法获取授权。

具体解决方案

1. 放弃通过系统获取手机号,改用用户手动输入

这是目前普通APP获取手机号唯一合规且可靠的方式。系统返回的line1Number在很多机型上本来就可能为空(取决于运营商是否写入SIM卡),API29+更是直接无法获取,别依赖这个接口。

2. IMSI的替代方案

API29+普通应用无法获取IMSI,若需标识用户/设备,可改用以下替代方案:

  • Android ID:通过Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)获取,恢复出厂设置会变更,同一设备不同应用的Android ID不同(API29+)。
  • 广告ID(Advertising ID):通过Google Play服务获取,用户可手动重置,适合广告追踪场景。

3. 调整现有代码,适配API29+权限限制

修正你代码里的几个问题,并针对API版本做适配:

  • 你把subscriptionId当成IMSI是错误的,subscriptionId是SIM卡的订阅ID,不是IMSI。
  • API29+下仅能获取非敏感SIM信息(运营商名称、SIM序列号、卡槽索引等)。

调整后的代码示例:

private var carrierName: String? = ""
private var displayName: String? = ""
private var slotIndex = 0
private var number: String? = ""
private var countryIso: String? = ""
private var imsi: String? = ""
private var simId: String? = ""

init {
    // 初始化默认值
    carrierName = ""
    displayName = ""
    slotIndex = 0
    number = ""
    countryIso = ""
    imsi = ""
    simId = ""

    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
            // API29+ 仅能获取非敏感信息
            if (subscriptionInfo != null) {
                carrierName = subscriptionInfo.carrierName.toString()
                displayName = subscriptionInfo.displayName.toString()
                slotIndex = subscriptionInfo.simSlotIndex
                simId = subscriptionInfo.iccId
                countryIso = if (subscriptionInfo.countryIso?.isNotEmpty() == true) {
                    subscriptionInfo.countryIso
                } else {
                    telephonyManager.simCountryIso
                }
            } else {
                carrierName = telephonyManager.simOperatorName
                displayName = telephonyManager.simOperatorName
                countryIso = telephonyManager.simCountryIso
                simId = telephonyManager.simSerialNumber
            }
            // API29+ 无法获取手机号和IMSI,此处留空或提示用户输入
            number = null
            imsi = null
        }
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && subscriptionInfo != null -> {
            // API21-API28 逻辑保留,注意subscriptionId不是IMSI
            carrierName = subscriptionInfo.carrierName.toString()
            displayName = subscriptionInfo.displayName.toString()
            slotIndex = subscriptionInfo.simSlotIndex
            number = subscriptionInfo.number
            imsi = telephonyManager.subscriberId // 这里才是IMSI
            simId = subscriptionInfo.iccId
            countryIso = if (subscriptionInfo.countryIso?.isNotEmpty() == true) {
                subscriptionInfo.countryIso
            } else {
                telephonyManager.simCountryIso
            }
        }
        else -> {
            // API21以下逻辑保留
            carrierName = telephonyManager.simOperatorName
            displayName = telephonyManager.simOperatorName
            countryIso = telephonyManager.simCountryIso
            imsi = telephonyManager.subscriberId
            simId = telephonyManager.simSerialNumber
            number = telephonyManager.line1Number.takeIf { it?.isNotEmpty() == true }
        }
    }
}

4. 权限申请的正确操作

即使API29+拿不到敏感信息,仍需动态申请READ_PHONE_STATE权限才能获取非敏感SIM信息:

// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
    // 动态申请权限
    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), REQUEST_CODE_PHONE_STATE)
}

注意事项

  • 不要尝试绕过系统权限限制,比如使用反射等手段,这会违反隐私政策,导致APP被Google Play拒审,甚至触发系统安全机制。
  • 若你的应用是系统应用/厂商预装应用,可联系厂商获取系统签名,配合READ_PRIVILEGED_PHONE_STATE权限获取敏感信息,但普通第三方APP无法使用此方式。

内容的提问来源于stack exchange,提问作者php fox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 18:42:49