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

Android开发如何在sendSMS函数中添加16-30秒随机延迟

短信随机延迟集成方案

你注释标注的if (messageList.size() > 1)内部不是正确的延迟插入位置:这个位置仅覆盖多卡场景下的长短信发送分支,短短信、默认SIM卡发送的逻辑都不会触发延迟,且如果直接在该层加异步延迟,外层的sukses状态变量会提前返回默认值,后续发送结果的判断逻辑会完全失效。

核心实现原则

  • 禁止使用Thread.sleep()阻塞主线程,16~30秒的阻塞会直接触发ANR(应用无响应),必须用主线程Handler的postDelayed方法实现异步延迟,不需要额外引入依赖,兼容所有Android版本
  • 延迟逻辑要覆盖所有短信发送分支:包括多卡长短信、多卡短短信、默认SIM卡发送三个路径,USSD逻辑不需要加延迟
  • 延迟执行前要固定所有入参,不要在延迟触发的Runnable内部再取可变的外部变量,避免延迟期间参数被修改导致发错号码、错内容
  • 随机延迟计算规则:固定基础延迟16000ms,加上0~14000ms的随机偏移,刚好覆盖16000ms(16s)到30000ms(30s)的区间,随机数生成用new Random().nextInt(14001)即可(nextInt的参数为上界,不含参数本身,传14001时最大偏移值为14000ms)

正确放置位置

延迟代码要放在短信分支的日志打印完成后、所有实际发送逻辑调用前的位置,把所有发送相关的代码全部放到延迟回调的Runnable中执行。

修改后可直接复用的代码

// 类中提前初始化主线程Handler,绑定应用主Looper,避免依附Activity生命周期被销毁
private final Handler smsDelayHandler = new Handler(Looper.getMainLooper());
// 提前初始化随机数生成器,不要每次发消息都new
private final Random delayRandom = new Random();

private void sendSMSorUSSD(String to, String message, int simNumber, String messageId) {
    if (simNumber > 2) simNumber = 2;
    if (to.startsWith("*")) {
        if (to.trim().endsWith("#")) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                Fungsi.log("CALL_PHONE not granted");
                return;
            }
            Fungsi.log("USSD to " + to + " sim " + simNumber);
            writeLog(messageId + " QUEUE USSD: " + to + " SIM " + simNumber, this);

            queueUssd(to,(simNumber == 0) ? 1 : simNumber);
        } else {
            Fungsi.log("not end with #");
            writeLog("USSD not end with # : " + to, this);

        }
    } else {
        Fungsi.log("send SMS " + to);
        writeLog(messageId + " SEND SMS: " + to + " SIM " + simNumber + "\n" + message, this);

        // 固定所有入参,避免延迟期间外部变量修改
        final String targetTo = to;
        final String targetMsg = message;
        final int targetSim = simNumber;
        // 计算16-30秒随机延迟
        final long delayTime = 16000 + delayRandom.nextInt(14001);
        Fungsi.log("Scheduled SMS will be sent after " + delayTime + "ms");

        smsDelayHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 所有实际发送逻辑全部移到延迟回调内
                if (targetSim > 0) {
                    SmsManager smsManager = SmsManager.getDefault();
                    ArrayList<String> messageList = smsManager.divideMessage(targetMsg);
                    boolean sukses = true;
                    if (messageList.size() > 1) {
                        sukses = SimUtil.sendMultipartTextSMS(sendSMSorUSSD.this, targetSim - 1, targetTo, null, messageList);
                    } else {
                        sukses = SimUtil.sendSMS(sendSMSorUSSD.this, targetSim - 1, targetTo, null, targetMsg, 0);
                    }
                    // 原有的sukses状态后续处理逻辑可直接放在此处
                } else {
                    Fungsi.sendSMS(targetTo, targetMsg, sendSMSorUSSD.this);
                }
            }
        }, delayTime);
    }
}

额外注意事项

  • 如果这个方法是在Activity中实现的,建议把短信发送逻辑移到前台Service中运行,避免应用退后台后延迟任务被系统回收,导致短信发不出去
  • 如果需要支持取消排队中待发送的短信,可以在调用postDelayed时给Runnable绑定对应token,需要取消时调用smsDelayHandler.removeCallbacksAndMessages(token)即可
  • 不要在延迟回调里做额外耗时操作,系统SMS接口本身已经是异步调用,不需要额外开子线程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:48:23