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

Android中使用Intent.ACTION_SENDTO跳转短信应用后,监听状态失败问题排查

Android短信状态监听问题排查与解决

核心问题分析

  1. 跳转系统短信应用无法触发自定义PendingIntent广播
    Intent.ACTION_SENDTO是启动第三方系统短信应用,第三方应用不会识别你附加的SENT_SMS_ACTION和SMS_DELIVERED_ACTION自定义Extra,自然不会触发对应的BroadcastReceiver回调。只有通过SmsManager直接发送短信时,系统才会根据传入的PendingIntent触发状态广播。

  2. onActivityResult中REQUEST_CODE_SENT/DELIVERED分支永远不会执行
    你通过startActivityForResult启动的是REQUEST_CODE_SEND_SMS,第三方短信应用只会返回这个请求码的结果,不会返回REQUEST_CODE_SENT或REQUEST_CODE_DELIVERED的结果,这部分代码完全无效。

  3. 状态计数逻辑错误
    sentDeliveredReceiver中用messageDelivered == selectedContacts.size()判断是否全部送达,但selectedContacts集合从未被赋值,实际选中的联系人存在referralCustomers中;此外如果单个联系人有多个手机号,需要统计总短信发送条数而非联系人数量。

  4. 系统短信应用返回resultCode不可靠
    大多数系统短信应用在用户发送短信后,不会将resultCode设置为RESULT_OK,所以依赖REQUEST_CODE_SEND_SMS的resultCode判断发送状态完全不准确。

解决方案

方案一:使用SmsManager直接发送短信(推荐,可准确监听状态)

放弃跳转系统短信应用,直接通过SmsManager发送短信,这样可以正常监听发送和送达状态。

修改sendReferralSMS方法:

private void sendReferralSMS() {
    if (referralCustomers.isEmpty()) {
        Toast.makeText(this, "No Referral Contacts to send SMS", Toast.LENGTH_SHORT).show();
        return;
    }

    // 重置计数
    messageSent = 0;
    messageDelivered = 0;
    int totalMessages = 0;

    // 统计总短信条数(单个联系人可能有多个号码)
    for (Invite contact : referralCustomers) {
        totalMessages += contact.getPhones().length;
    }

    SmsManager smsManager = SmsManager.getDefault();
    for (Invite contact : referralCustomers) {
        for (String phone : contact.getPhones()) {
            // 为每条短信创建唯一的PendingIntent请求码,避免覆盖
            int sentRequestCode = messageSent + 1000;
            int deliveredRequestCode = messageDelivered + 2000;

            PendingIntent sentPI = PendingIntent.getBroadcast(this, sentRequestCode,
                    new Intent(SENT_SMS_ACTION), PendingIntent.FLAG_IMMUTABLE);
            PendingIntent deliveredPI = PendingIntent.getBroadcast(this, deliveredRequestCode,
                    new Intent(SMS_DELIVERED_ACTION), PendingIntent.FLAG_IMMUTABLE);

            // 发送短信
            smsManager.sendTextMessage(phone, null, message, sentPI, deliveredPI);
        }
    }
}

修改BroadcastReceiver的计数逻辑:

private final BroadcastReceiver sentDeliveredReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (getResultCode()) {
            case RESULT_OK:
                messageDelivered++;
                // 计算总短信条数
                int totalMessages = 0;
                for (Invite contact : referralCustomers) {
                    totalMessages += contact.getPhones().length;
                }
                if(messageDelivered == totalMessages){
                    executeReferralAPI();
                    Toast.makeText(context, "All SMS delivered", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context, "SMS delivered: " + messageDelivered + "/" + totalMessages, Toast.LENGTH_SHORT).show();
                }
                break;
            case RESULT_CANCELED:
                Toast.makeText(context, "SMS not delivered", Toast.LENGTH_SHORT).show();
                // 可在这里触发全局错误提示
                break;
        }
    }
};

方案二:必须跳转系统短信应用(无法准确监听送达状态)

如果业务要求必须让用户手动在系统短信应用中发送,那么无法监听送达状态,只能通过ContentObserver监听短信内容变化,判断是否发送成功(仅能判断是否已发送,无法确认送达)。

示例ContentObserver实现:

private class SmsContentObserver extends ContentObserver {
    public SmsContentObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        // 查询已发送的短信,判断是否包含你的推荐内容
        Cursor cursor = getContentResolver().query(Uri.parse("content://sms/sent"),
                new String[]{"body"}, null, null, "date DESC limit 1");
        if (cursor != null && cursor.moveToFirst()) {
            String body = cursor.getString(cursor.getColumnIndex("body"));
            if (body.contains(message)) {
                Toast.makeText(NewReferralActivity.this, "SMS sent via system app", Toast.LENGTH_SHORT).show();
                // 这里无法确认送达,只能提示发送成功
            }
            cursor.close();
        }
    }
}

// 在onCreate中注册,onDestroy中注销
private SmsContentObserver smsObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_referral);
    // ...其他初始化
    smsObserver = new SmsContentObserver(new Handler());
    getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, smsObserver);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceivers();
    getContentResolver().unregisterContentObserver(smsObserver);
}

额外注意事项

  • 确保已申请SEND_SMS和READ_SMS(方案二需要)权限,且在Android 13+动态申请。
  • 多手机号发送时,务必为每个PendingIntent设置唯一的请求码,避免广播被覆盖。
  • 送达状态的监听依赖运营商支持,部分地区或运营商可能无法返回送达通知。

内容的提问来源于stack exchange,提问作者Sairam balu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:22:02