为何单次锁屏操作后BroadcastReceiver多次接收SCREEN_OFF Intent?
解决Android Service中SCREEN_ON/OFF广播多次接收的问题
你遇到的核心问题是BroadcastReceiver被重复注册——哪怕你认为只调用了一次onStartCommand(),但该方法实际可能被系统或业务代码多次触发(比如Service被系统重启、多次调用startService()),每次触发都会新增一个接收器实例。当锁屏/亮屏广播发送时,所有已注册的接收器都会响应,最终出现多次日志输出。
根治方案:
1. 增加注册状态标记,避免重复注册
在Service类中添加布尔变量标记注册状态,确保接收器仅被注册一次:
public class YourService extends Service { private boolean isReceiverRegistered = false; private EventsReceiver mScreenReceiver; @Override public int onStartCommand(Intent intent, int flags, int startId) { // 仅当未注册时执行注册操作 if (!isReceiverRegistered) { mScreenReceiver = new EventsReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(mScreenReceiver, filter); isReceiverRegistered = true; } // 根据业务需求返回启动模式,比如START_STICKY return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); // 注销时校验状态,避免空指针或重复注销 if (isReceiverRegistered && mScreenReceiver != null) { unregisterReceiver(mScreenReceiver); isReceiverRegistered = false; mScreenReceiver = null; } } // 自定义BroadcastReceiver实现 private class EventsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { Log.d("InternetConnectionCheck", "ACTION_SCREEN_ON is received"); Log.i("InternetConnectionCheck", "EventsReceiver.onReceive() " + action); } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 处理锁屏逻辑 } } } }
2. 检查Service启动逻辑
确认代码中是否存在多次调用startService()的情况,若为绑定+启动的混合场景,需避免重复触发onStartCommand()。如果无需多次启动Service,可考虑用bindService()替代重复调用startService()。
3. 补充异常场景下的注销逻辑
Service的onDestroy()不一定会被系统调用(比如内存不足时被直接杀掉),可在onTaskRemoved()中也添加注销逻辑,进一步兜底:
@Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); if (isReceiverRegistered && mScreenReceiver != null) { unregisterReceiver(mScreenReceiver); isReceiverRegistered = false; mScreenReceiver = null; } stopSelf(); }
通过以上调整,就能彻底解决重复注册导致的广播多次接收问题,无需再依赖计数器的临时方案。
内容的提问来源于stack exchange,提问作者AmenAllah HAMDI
相关产品推荐
相关产品推荐

