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

API 31+下无需READ_PHONE_NUMBERS权限获取自定义PhoneAccount的方法

解决API31+下调用TelecomManager.getPhoneAccount()无需READ_PHONE_NUMBERS权限的方案

核心原因

API 31(Android 12)起,TelecomManager.getPhoneAccount()要求READ_PHONE_NUMBERS权限,哪怕是你自己应用创建并注册的PhoneAccount——这是系统权限机制的限制,和是否访问真实手机号无关。

方案1:直接复用自己构建的PhoneAccount实例

你已经通过PhoneAccount.builder()创建并完成了注册,完全不需要再调用getPhoneAccount()去获取。直接使用你build好的phoneAccount对象即可:

// 构建并注册
val builder = PhoneAccount.builder(
    phoneAccountHandle,
    this.resources.getText(R.string.app_name)
)
val uri = Uri.parse("tel:1236547")
builder.setSubscriptionAddress(uri)
builder.setAddress(uri)
builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
val phoneAccount = builder.build()
manager.registerPhoneAccount(phoneAccount)

// 直接使用这个phoneAccount,无需再调用getPhoneAccount()
// 后续逻辑直接用phoneAccount变量即可

方案2:获取当前应用注册的所有PhoneAccount(无权限要求)

如果需要在注册后(比如应用重启后)重新获取自己的PhoneAccount,使用TelecomManager.getPhoneAccountsForPackage()方法——这个方法从API26开始支持,不需要任何权限,只会返回当前应用注册的PhoneAccount列表:

val manager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
val myPhoneAccounts = manager.getPhoneAccountsForPackage(packageName)
// 筛选出匹配自己的PhoneAccountHandle的项
val targetAccount = myPhoneAccounts.firstOrNull { it.accountHandle == phoneAccountHandle }

为什么这两个方案可行?

  • 方案1:你手动构建的PhoneAccount是完整的实例,和系统中注册的内容完全一致,直接复用就不会触发权限检查。
  • 方案2:getPhoneAccountsForPackage()是系统为应用提供的、仅访问自身注册账号的方法,设计上就不需要权限,完美避开了READ_PHONE_NUMBERS的限制。

内容的提问来源于stack exchange,提问作者Mohammad Taqi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:25:19