Android 5.0电话状态广播重复触发致Service A重复调用引发数据丢失
解决Android 5.0中PhoneStateReceiver重复触发导致Service重复启动的问题
我之前也踩过Android 5.0里PhoneState广播重复触发的坑,结合你的场景(Service A插入多表多记录,重复启动导致数据丢失),给你几个实用的解决思路:
1. 在广播接收器中添加状态去重逻辑
Android 5.0对电话状态广播的发送机制有调整,会出现相同状态重复推送的情况。我们可以在接收器里维护一个当前状态的缓存,每次触发时先判断是否和上次一致,一致就直接跳过后续处理:
public class PhoneStateReceiver extends BroadcastReceiver { // 初始化为空闲状态 private String currentPhoneState = TelephonyManager.EXTRA_STATE_IDLE; @Override public void onReceive(Context context, Intent intent) { String newState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); // 过滤空状态或重复状态 if (newState == null || newState.equals(currentPhoneState)) { return; } // 更新当前状态缓存 currentPhoneState = newState; // 按原逻辑处理不同状态,比如触发Service A handlePhoneStateChange(context, newState, intent); } private void handlePhoneStateChange(Context context, String state, Intent intent) { if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) { // 启动Service A的逻辑 Intent serviceIntent = new Intent(context, ServiceA.class); context.startService(serviceIntent); } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { // 过滤无呼叫号码的无效触发 String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); if (incomingNumber == null || incomingNumber.isEmpty()) { return; // 无呼叫号码,不触发Service A } // 若业务需要再处理RINGING状态 } // OFFHOOK状态同理,可根据业务判断是否需要过滤重复触发 } }
2. 在Service A内部添加执行锁,避免重复任务
即使广播去重了,也可能因为系统调度问题导致Service A被重复启动。我们可以在Service A里加一个执行状态标记,确保同一时间只有一个插入任务在运行:
public class ServiceA extends Service { private boolean isInsertingData = false; private ExecutorService executor = Executors.newSingleThreadExecutor(); @Override public int onStartCommand(Intent intent, int flags, int startId) { if (isInsertingData) { // 当前正在执行插入任务,直接返回,避免重复执行 return START_STICKY; } isInsertingData = true; // 用单线程池执行插入操作,保证串行执行 executor.execute(() -> { try { // 执行插入MULTIPLE_TABLES和MULTIPLE_RECORDS的逻辑 insertMultipleRecords(); } catch (Exception e) { // 处理插入异常,避免状态一直锁死 e.printStackTrace(); } finally { // 任务完成后释放标记 isInsertingData = false; } }); return START_STICKY; } private void insertMultipleRecords() { // 你的多表多记录插入逻辑 } // 其他Service生命周期方法... }
3. 针对性过滤OFFHOOK的无效触发
OFFHOOK状态可能会因为系统的不同场景(比如通话中切换状态)多次触发,你可以根据业务需求,只在特定场景下处理该状态。比如仅当从IDLE状态切换到OFFHOOK时才触发Service A,或者结合通话状态的持续时间过滤重复触发。
这些方法组合起来,应该能有效解决你遇到的重复触发、Service重复启动以及数据丢失的问题,我之前在类似的Android 5.0项目中用状态去重加Service内部锁的方案完美解决了问题。
内容的提问来源于stack exchange,提问作者sandhya sasane
相关产品推荐
相关产品推荐

