短信重复发送:是应用重复请求还是网络问题?
嘿,我来帮你捋捋这个重复发短信的问题——你说应用日志里只触发了一次send操作,但客户收到多条,这大概率不是应用层的重复调用,而是Android系统或者SmsManager相关的机制在搞事情。咱们一步步拆解可能的原因和排查方案:
1. 系统自动重试机制在“搞鬼”
Android系统本身有短信发送失败后的自动重试逻辑,比如当短信发送遇到网络波动、无服务等问题时,系统会自动重试发送,但你的自定义日志只记录了应用调用send的次数,没追踪系统层面的重试动作。
排查方案:
完善发送结果的监听逻辑,在PendingIntentSent对应的广播接收器里记录每一次发送结果(包括系统触发的重试):
public class SmsSentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 把发送结果写入你的SQLite日志,包括结果码和请求标识 String logContent = String.format("短信发送结果:%d,请求ID:%d", getResultCode(), intent.getIntExtra("sms_request_id", -1)); // 调用你的日志存储方法 saveToCustomLog(logContent); switch (getResultCode()) { case Activity.RESULT_OK: // 发送成功 break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: case SmsManager.RESULT_ERROR_NO_SERVICE: case SmsManager.RESULT_ERROR_NULL_PDU: case SmsManager.RESULT_ERROR_RADIO_OFF: // 发送失败,系统可能会自动重试 break; } } }
通过这个日志,你就能清楚看到是不是系统在自动重试发送,而应用层确实只触发了一次send。
2. PendingIntent的FLAG设置或复用问题
如果创建PendingIntentSent/PendingIntentDelivered时没有用唯一的请求码(requestCode),或者FLAG设置不当,可能导致系统误判请求,触发重复发送。尤其是Android 12+之后,对PendingIntent的FLAG有更严格的要求。
修复方案:
每次发送短信时,用唯一的requestCode(比如短信ID、当前时间戳)来创建PendingIntent,同时添加适配Android 12+的FLAG:
// 生成唯一请求码,比如用当前时间戳 int uniqueRequestCode = (int) System.currentTimeMillis(); // 创建发送结果的PendingIntent PendingIntent sentPI = PendingIntent.getBroadcast( this, uniqueRequestCode, new Intent("YOUR_SMS_SENT_ACTION"), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 同理创建送达结果的PendingIntent PendingIntent deliveredPI = PendingIntent.getBroadcast( this, uniqueRequestCode + 1, new Intent("YOUR_SMS_DELIVERED_ACTION"), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE );
3. 长短信被分段发送,被客户误认为“重复”
你的代码里用到了ArrayList<St...,应该是SmsManager.divideMessage()对长短信的分段处理——当短信内容超过单条短信的字符限制(比如ASCII字符70个,Unicode字符160个),SmsManager会自动把内容拆分成多条发送,客户收到的多条连续内容可能被误认为是重复发送。
排查方案:
在send方法里添加分段数量的日志:
private void send(String message, String phoneNumber, PendingIntent pendingIntentSent, PendingIntent pendingIntentDelivered) { SmsManager smsManager = getSMSManager(); ArrayList<String> smsParts = smsManager.divideMessage(message); // 记录分段数量到日志 saveToCustomLog("短信内容过长,被拆分为" + smsParts.size() + "段发送"); // 后续发送逻辑... }
如果是这种情况,属于正常的长短信拆分,可以在应用里给用户添加提示,或者告知客户这是正常现象。
4. 运营商侧的异常
极少数情况下,重复发送可能是运营商短信中心的问题——比如短信中心在转发过程中出现异常,导致同一短信被多次下发。
排查方案:
让客户测试发送给不同运营商的号码,看看是不是只有特定运营商出现这个问题;或者尝试更换测试设备的SIM卡,验证是否是特定运营商的问题,必要时联系运营商排查。
内容的提问来源于stack exchange,提问作者Zbarcea Christian

