Android问题:如何修复JobIntentService中通知计数重置失效问题?
你的需求是在通知被清除(滑动删除或点击全部清除)时重置SharedPreferences里的计数器,但当前没生效,核心问题出在广播接收的方式和PendingIntent的目标设置上,具体来看:
主要问题点
1. 动态注册的BroadcastReceiver无法在Service销毁后接收广播
你在AlarmService的onHandleWork方法里动态注册了内部BroadcastReceiver,但JobIntentService是一次性组件——执行完onHandleWork后很快就会调用onDestroy,此时Receiver会被注销。而通知被删除的动作是在未来某个时间发生的,这时候AlarmService早已停止运行,Receiver自然收不到广播。
2. DeleteIntent的PendingIntent目标错误
你用PendingIntent.getBroadcast()创建意图,但Intent的目标是AlarmService(一个Service类),这完全不对——广播应该发送给BroadcastReceiver类型的组件,而不是Service。
3. SharedPreferences操作冗余
在Receiver里你先clear()再重新设置0,其实直接putInt("total-messages", 0)就可以完成重置,不需要额外的初始化步骤。
修正方案
步骤1:创建独立的BroadcastReceiver类
新建一个专门处理通知删除的Receiver,不要放在Service内部:
public class NotificationDeleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if ("notification_cleared".equals(intent.getAction())) { // 直接重置计数器为0 SharedPreferences sp = context.getSharedPreferences(AlarmService.NOTIFICATIONS_COUNTER, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putInt("total-messages", 0); editor.apply(); } } }
步骤2:在AndroidManifest.xml里静态注册这个Receiver
静态注册的Receiver不需要依赖Service运行,即使App在后台也能接收广播:
<receiver android:name=".NotificationDeleteReceiver" android:exported="false"> <intent-filter> <action android:name="notification_cleared" /> </intent-filter> </receiver>
步骤3:修改DeleteIntent的PendingIntent设置
在sendNotification()方法里,把PendingIntent的目标改为刚才新建的NotificationDeleteReceiver,同时注意API级别对应的PendingIntent flag(Android 12+需要指定FLAG_IMMUTABLE或FLAG_MUTABLE):
private void sendNotification() { // ... 省略其他代码 ... // 修正DeleteIntent的Intent目标 Intent deleteIntent = new Intent(this, NotificationDeleteReceiver.class); deleteIntent.setAction("notification_cleared"); // 根据API级别选择合适的flag int pendingIntentFlag; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { pendingIntentFlag = PendingIntent.FLAG_IMMUTABLE; } else { pendingIntentFlag = PendingIntent.FLAG_CANCEL_CURRENT; } PendingIntent deletePendingIntent = PendingIntent.getBroadcast( this, REQUEST_CODE_DELETE_INTENT, deleteIntent, pendingIntentFlag ); mBuilder.setDeleteIntent(deletePendingIntent); // ... 省略其他代码 ... }
步骤4:移除Service里的动态Receiver代码
既然已经用静态注册的独立Receiver,就可以删掉AlarmService里的内部Receiver、registerReceiver和unregisterReceiver相关代码,简化Service逻辑。
额外提醒:别忘了创建NotificationChannel(Android 8.0+)
如果你的App目标SDK是26及以上,必须创建NotificationChannel才能显示通知,建议在App启动时添加创建逻辑:
private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( NOTIFICATION_CHANNEL_ID, "你的通知渠道名称", NotificationManager.IMPORTANCE_DEFAULT ); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } }
这样修改后,当用户清除通知时,系统会发送广播到NotificationDeleteReceiver,进而完成SharedPreferences计数器的重置。
内容的提问来源于stack exchange,提问作者AJW

