SmsManager sendTextMessage部分场景无法发送问题排查求助
嘿,这种无崩溃但功能失效的问题确实头疼,尤其是和网络类型挂钩的情况,我之前也遇到过类似的,给你几个实用的排查和解决思路:
排查与修复方案
1. 先抓准网络类型对应的失败原因
首先,Android的SmsManager在不同蜂窝网络(5G/4G/3G/2G)下的底层逻辑差异很大,部分运营商会限制5G网络下的普通短信发送(需要回落至4G/2G才能触发发送)。你可以在模拟器里细化测试:
- 强制切换到2G网络,验证短信是否能正常发出
- 切换回5G/4G,观察发送失败的触发时机,是否是特定网络下必现
2. 别忽略SmsManager的发送结果回调
Crashlytics没报错,大概率是发送操作没崩溃,但被系统/运营商拦截了。你可以通过监听sendTextMessage返回的PendingIntent,获取具体的失败码,这比只看崩溃日志有用得多:
String phoneNum = "用户手机号"; String content = "测试短信内容"; // 创建发送结果监听的PendingIntent PendingIntent sentIntent = PendingIntent.getBroadcast( getContext(), 0, new Intent("SMS_SENT_ACTION"), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 临时注册广播接收器获取结果 BroadcastReceiver resultReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (getResultCode()) { case Activity.RESULT_OK: Log.d("SMS", "发送成功"); break; case SmsManager.RESULT_ERROR_NO_SERVICE: Log.e("SMS", "当前网络无短信服务"); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: Log.e("SMS", "通用发送失败"); break; case SmsManager.RESULT_ERROR_RADIO_OFF: Log.e("SMS", "无线电已关闭"); break; } context.unregisterReceiver(this); } }; getContext().registerReceiver(resultReceiver, new IntentFilter("SMS_SENT_ACTION")); // 执行发送 SmsManager.getDefault().sendTextMessage(phoneNum, null, content, sentIntent, null);
通过这段代码,你能精准定位是网络服务问题、运营商拦截,还是其他底层错误。
3. 适配Android 12+的短信权限限制
从Android 12(API 31)开始,系统对非默认短信应用的发送权限做了更严格的限制:
- 确保你已经动态申请了
SEND_SMS权限(Android 6+必须) - 如果用户设备是Android 12+,可以考虑引导用户将你的应用设置为默认短信应用(如果业务允许),这能绕过大部分发送限制
4. 多SIM卡场景的适配
部分用户的设备是多SIM卡,SmsManager.getDefault()可能会自动选择没有短信服务的SIM卡,导致发送失败。你可以指定具体的SIM卡发送:
TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); List<SubscriptionInfo> simList = telephonyManager.getSubscriptionInfoList(); if (simList != null && !simList.isEmpty()) { // 选择第一个可用的SIM卡(也可以让用户手动选择) int targetSimId = simList.get(0).getSubscriptionId(); SmsManager targetSmsManager = SmsManager.getSmsManagerForSubscriptionId(targetSimId); targetSmsManager.sendTextMessage(phoneNum, null, content, sentIntent, null); }
5. 应对运营商的网络回落要求
如果测试后发现是5G网络下无法发送,部分运营商要求短信发送必须回落至4G/2G。你可以尝试引导用户手动切换网络,或者(如果有权限的话)临时切换网络类型:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); // 临时切换到2G网络 telephonyManager.setNetworkTypeOverride(TelephonyManager.NETWORK_TYPE_GSM); // 发送短信... // 发送完成后恢复自动选择 telephonyManager.setNetworkTypeOverride(TelephonyManager.NETWORK_TYPE_UNKNOWN); }
注意:MODIFY_PHONE_STATE权限在Android 10+只对系统应用开放,普通应用只能引导用户手动切换。
内容的提问来源于stack exchange,提问作者Happy Meal




