如何在Android中用Kotlin从SIM卡获取手机号?代码调试求助
如何在Android上用Kotlin获取SIM卡手机号码
首先得说,你遇到的问题其实很常见——SubscriptionInfo.number返回空,大多和运营商是否将手机号码写入SIM卡以及权限配置有关。咱们一步步来解决:
1. 先确认权限是否到位
从Android 6.0(API 23)开始,读取手机号需要动态申请敏感权限,不同版本的权限要求还有点区别:
- Android 9及以下:需要
READ_PHONE_STATE权限 - Android 10+:需要
READ_SMS或者READ_PHONE_NUMBERS权限(READ_PHONE_STATE不再返回手机号相关信息)
首先在AndroidManifest.xml里声明权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="28" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
然后在代码里动态申请权限(以Activity为例):
private val REQUIRED_PERMISSIONS = arrayOf( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.READ_SMS else Manifest.permission.READ_PHONE_STATE ) private fun checkPermissions() { if (REQUIRED_PERMISSIONS.any { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED }) { ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, 1001) } else { fetchPhoneNumbers() } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 1001 && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { fetchPhoneNumbers() } else { // 权限被拒绝,提示用户 Toast.makeText(this, "需要权限才能获取手机号", Toast.LENGTH_SHORT).show() } }
2. 优化获取手机号的代码
你的基础代码没问题,但可以补充更多兼容逻辑,同时要明确:不是所有SIM卡都存储了手机号,如果运营商没写入,任何方法都拿不到。
更新后的fetchPhoneNumbers()方法:
private fun fetchPhoneNumbers() { val subscriptionManager = SubscriptionManager.from(this) // 检查是否有读取订阅信息的权限(Android 11+需要) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !subscriptionManager.canReadPhoneNumbers()) { Toast.makeText(this, "缺少读取号码权限", Toast.LENGTH_SHORT).show() return } val activeSubscriptions = subscriptionManager.activeSubscriptionInfoList for (subscriptionInfo in activeSubscriptions) { val number = subscriptionInfo.number if (number.isNotEmpty()) { Log.e("Test", "Number is $number") } else { // 尝试用TelephonyManager获取备选 val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager val line1Number = telephonyManager.line1Number Log.e("Test", "Subscription number empty, line1Number: ${line1Number.takeIf { it.isNotEmpty() } ?: "Still empty"}") } } }
为什么还是拿不到?
如果权限都给了还是返回空,大概率是这几个原因:
- 运营商没有将手机号码写入SIM卡(很多虚拟运营商或者老SIM卡会这样)
- 双卡设备中,其中一张卡未激活或者未写入号码
- 系统隐私设置限制了应用读取手机号的权限
替代方案
如果必须获取用户手机号,建议用短信验证码的方式,这是最可靠的方法——因为不管SIM卡有没有存号码,只要能接收短信就能验证用户的手机号。
内容的提问来源于stack exchange,提问作者Govind Rastogi
相关产品推荐
相关产品推荐

