Android SMS BroadcastReceiver运行一段时间后停止响应问题排查
解决短信转发应用Broadcast Receiver停止响应的问题
本质原因
Android 8.0(API 26)开始,系统对静态注册的隐式广播(比如SMS_RECEIVED)做了严格限制。就算设备处于充电状态,应用闲置1-2小时后,后台进程会被系统回收,静态注册的接收器也就跟着失效了——只有当你打开应用,进程重新启动,接收器才会再次工作。
核心解决方案
1. 改用前台Service+动态注册广播
静态注册的路子已经走不通,必须用前台Service来承载动态注册的广播接收器,前台Service因为有常驻通知,系统不会轻易杀死它:
- 先创建一个前台Service类:
class SmsGuardService : Service() { private lateinit var smsReceiver: SmsReceiver override fun onCreate() { super.onCreate() // 初始化并注册短信接收器 smsReceiver = SmsReceiver() val smsFilter = IntentFilter("android.provider.Telephony.SMS_RECEIVED") smsFilter.priority = 999 // 设高优先级,确保能抢到短信事件 registerReceiver(smsReceiver, smsFilter) // 启动前台通知(Android 8.0+必须创建通知渠道) val channel = NotificationChannel( "sms_forward_channel", "短信转发服务", NotificationManager.IMPORTANCE_LOW ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) val notification = NotificationCompat.Builder(this, "sms_forward_channel") .setSmallIcon(R.drawable.ic_service_notify) .setContentTitle("短信转发服务运行中") .setContentText("持续监听短信") .setPriority(NotificationCompat.PRIORITY_LOW) .build() startForeground(1001, notification) } override fun onDestroy() { super.onDestroy() // 销毁时注销接收器,避免内存泄漏 unregisterReceiver(smsReceiver) } override fun onBind(intent: Intent): IBinder? = null }
- 在Manifest里注册Service,同时声明前台服务类型(Android 12+要求):
<service android:name=".SmsGuardService" android:foregroundServiceType="dataSync" android:exported="false" />
- 在应用启动的Activity里启动这个Service(比如MainActivity的onCreate方法):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(Intent(this, SmsGuardService::class.java)) } else { startService(Intent(this, SmsGuardService::class.java)) }
2. 申请忽略电池优化权限
就算用了前台Service,部分厂商的定制系统还是会偷偷杀后台,所以要引导用户给应用开「忽略电池优化」权限:
- 先在Manifest加权限:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
- 代码里检查并跳转设置页面:
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager if (!powerManager.isIgnoringBatteryOptimizations(packageName)) { val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:$packageName") startActivity(intent) }
3. 适配国内厂商的后台管理
小米、华为、OPPO这些厂商有自己的后台管控逻辑,必须让用户手动设置:
- 把应用加入「后台运行白名单」
- 关闭应用的「智能省电」「深度睡眠」模式
- 开启应用的「自启动权限」
这些设置入口每个厂商不一样,你可以在应用里加个引导页面,告诉用户怎么操作。
为什么静态注册没用?
Android 8.0之后,只有少数系统级广播允许静态注册(比如开机广播),SMS_RECEIVED不在这个列表里。当应用进程被回收,静态接收器不会被系统唤醒——只有应用有活跃组件(比如前台Service)时,动态注册的接收器才能持续工作。
内容的提问来源于stack exchange,提问作者thst
相关产品推荐
相关产品推荐

