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

Android端接收短信时如何获取对应接收方手机号码

解答

可以获取短信对应的本机接收号码,不存在全版本通用的直接API,需要按Android版本做适配,具体方案如下:

实现原理

SmsMessage类本身没有提供接收方号码的公开字段,核心思路是先从短信广播Intent中拿到当前收件的SIM卡标识,再查询对应SIM卡绑定的本机号码即可。

分版本实现

Android 5.1(API 22)及以上

从API 22开始系统原生支持多SIM卡,短信广播Intent会直接携带当前收件SIM的订阅ID,配合SubscriptionManager就能查询到对应号码。
首先在清单文件声明权限,Android 6.0及以上版本需要动态申请该权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

核心取值代码:

// 从短信广播Intent取当前收件SIM的订阅ID
val subscriptionId = intent.getIntExtra("subscription", -1)
var recipientNumber: String? = null
if (subscriptionId != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    val subscriptionManager = getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
        recipientNumber = runCatching {
            subscriptionManager.getActiveSubscriptionInfo(subscriptionId)?.number
        }.getOrNull()
    }
}

注意:如果运营商没有将本机号码写入SIM卡,该字段会返回空,属于硬件/运营商限制,没有通用解决办法。

Android 5.0(API 21)及以下

低版本系统没有开放多SIM卡相关公开API,各厂商实现逻辑不统一:

  • 可以先遍历Intent的extras字段,查找常见的SIM标识key,包括simId、sim_num、slot,拿到卡槽ID
  • 拿到卡槽ID后需要通过反射调用厂商定制的TelephonyManager内部方法,查询对应卡槽的本机号码,需要针对主流机型单独适配,没有统一代码。

现有代码修正

你贴的原有代码存在递归调用getFullMessage的问题,会触发栈溢出,整合接收方号码逻辑后的完整可运行代码如下:

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.provider.Telephony.Sms.Intents.getMessagesFromIntent
import android.telephony.SubscriptionManager
import android.telephony.SmsMessage
import androidx.core.content.ContextCompat

data class CompleteSmsMessage(
    val originatingAddress: String?,
    val recipientAddress: String?,
    val body: String
)

fun parseSmsFromIntent(intent: Intent, context: Context): CompleteSmsMessage {
    val messageParts = getMessagesFromIntent(intent)
    val fullBody = messageParts.joinToString(separator = "") { it.messageBody ?: "" }
    val sender = messageParts.lastOrNull()?.originatingAddress
    var recipient: String? = null

    val subId = intent.getIntExtra("subscription", -1)
    if (subId != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
        val subManager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            recipient = runCatching {
                subManager.getActiveSubscriptionInfo(subId)?.number
            }.getOrNull()
        }
    }

    return CompleteSmsMessage(
        originatingAddress = sender,
        recipientAddress = recipient,
        body = fullBody
    )
}

补充说明

  • 部分定制ROM会修改SubscriptionManager的返回逻辑,即使权限正常、SIM卡已写入号码也可能返回空,这类情况只能单独针对机型做适配
  • 不需要尝试解析短信PDU数据获取接收号码,国内运营商下发的短信PDU中通常不携带本机接收号码字段

内容的提问来源于stack exchange,提问作者Aero Wang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:15:42