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

能否通过Telephony获取短信发送方的联系人姓名?

如何通过Android Telephony获取短信发送方的联系人姓名

完全可以实现,核心思路是通过Telephony获取短信发送方的电话号码(message.address),再结合Android的Contacts Provider查询匹配对应的联系人姓名,不需要额外依赖。

步骤说明

  • 权限准备:需要申请READ_SMS和READ_CONTACTS权限,Android 6.0及以上版本需动态申请。
  • 获取短信发送方号码:在短信监听逻辑中,通过SmsMessage的getOriginatingAddress()或直接读取message.address拿到发送方号码。
  • 匹配联系人姓名:通过Contacts Provider的ContactsContract.CommonDataKinds.Phone表,以拿到的号码为查询条件,获取对应的联系人显示名称。

代码示例

  1. 动态申请权限(Activity中实现)
private fun requestRequiredPermissions() {
    val permissions = arrayOf(Manifest.permission.READ_SMS, Manifest.permission.READ_CONTACTS)
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, permissions, 1001)
    }
}
  1. 短信监听BroadcastReceiver(简化实现)
class SmsReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION == intent?.action) {
            val smsMessages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
            for (message in smsMessages) {
                val senderNumber = message.originatingAddress
                val senderName = getContactNameByNumber(context, senderNumber)
                // 此处可直接使用senderName,未匹配到联系人则返回原号码
                Log.d("SmsReceiver", "发送方:$senderName | 号码:$senderNumber")
            }
        }
    }

    private fun getContactNameByNumber(context: Context?, phoneNumber: String?): String? {
        if (context == null || phoneNumber.isNullOrEmpty()) return phoneNumber

        // 统一号码格式,去除空格、括号、加号等特殊字符,提升匹配率
        val normalizedNumber = phoneNumber.replace("[^0-9]".toRegex(), "")
        
        val contentResolver = context.contentResolver
        val projection = arrayOf(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
        val selection = "${ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER} LIKE ?"
        val selectionArgs = arrayOf("%$normalizedNumber%")

        contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            null
        )?.use { cursor ->
            if (cursor.moveToFirst()) {
                return cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
            }
        }
        // 未匹配到联系人时返回原号码
        return phoneNumber
    }
}

注意事项

  • 号码格式处理:短信中的号码可能带区号、空格等格式,统一格式能有效提升匹配成功率。
  • 权限校验:必须确保用户授予了对应权限,否则会导致查询失败。
  • 性能优化:若频繁接收短信,建议对查询结果做缓存,避免重复查询Contacts Provider消耗资源。

内容的提问来源于stack exchange,提问作者Blue M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:35:44