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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:39:30