You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动