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

Android Oreo中已注册广播接收器但无法接收短信Intent问题

排查Oreo+动态注册短信广播接收器无响应的问题

我来帮你一步步排查这个短信接收的问题,结合你给出的代码,咱们从几个核心关键点入手:

1. 权限授予后再注册接收器是核心前提

你已经写了权限申请的代码,但一定要确保用户授予权限后再注册广播接收器!如果在权限还没通过的时候就调用registerReceiver,接收器是无法正常工作的。

你需要在权限申请的回调方法里完成注册逻辑,示例代码如下:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == SMS_PERMISSION_REQ_CODE_SUBMIT) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限确认授予后,再注册广播接收器
            IntentFilter smsFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
            smsFilter.setPriority(Integer.MAX_VALUE); // 提高优先级,避免被其他App抢占
            registerReceiver(broadcast, smsFilter);
        } else {
            Toast.makeText(this, "需要开启短信接收权限才能正常提取验证码", Toast.LENGTH_SHORT).show();
        }
    }
}

2. 动态注册的生命周期绑定问题

动态注册的广播接收器和注册它的组件(比如你的otpreadertwo Activity)生命周期绑定:如果Activity被销毁(比如退到后台、用户返回),接收器会被系统自动注销,自然收不到短信广播。

如果需要App在后台也能接收短信,建议用前台Service来注册接收器(Oreo+对后台Service限制严格,前台Service更难被系统回收):

public class SmsListenerService extends Service {
    private Bcast smsReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        // 注册短信广播接收器
        smsReceiver = new Bcast();
        IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
        filter.setPriority(Integer.MAX_VALUE);
        registerReceiver(smsReceiver, filter);

        // 启动前台服务,避免被系统回收
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("sms_listener", "验证码监听服务", NotificationManager.IMPORTANCE_LOW);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, "sms_listener")
                    .setContentTitle("正在监听验证码")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .build();
            startForeground(1001, notification);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY; // 服务被杀死后尝试自动重启
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 注销接收器,避免内存泄漏
        if (smsReceiver != null) {
            unregisterReceiver(smsReceiver);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

然后在Activity中启动这个服务:

// 启动短信监听服务
Intent serviceIntent = new Intent(this, SmsListenerService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(serviceIntent);
} else {
    startService(serviceIntent);
}

3. 广播优先级的抢占问题

很多第三方短信App或系统自带的短信应用会抢占SMS_RECEIVED广播,给你的IntentFilter设置最高优先级,可以提升抢到广播的概率(注意不要滥用,但测试阶段可以先试试)。

4. 其他排查点

  • 确认你的App没有被系统电池优化策略限制:在系统设置里把App加入电池优化白名单,允许后台活动。
  • 用真实设备测试:部分模拟器的短信广播机制可能存在异常,真实设备测试更准确。
  • 悬浮窗权限和短信接收无关:你申请的悬浮窗权限不影响短信广播接收,可以不用在这个点上纠结。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:53:52