Android通知异常:锁屏解锁后自动清除问题排查
嘿,我来帮你搞定这个通知自动消失的问题!你的核心需求是让通知只能被用户手动清除,但现在锁屏点亮后就自动消失,其他APP却没这情况,问题主要出在这几个代码细节上:
1. setAutoCancel(true) 违背了你的需求
你代码里设置了mBuilder.setAutoCancel(true),这个配置会让通知在被点击时自动清除——虽然这不是锁屏点亮就消失的直接原因,但首先得把它改成false,这是实现"仅手动清除"的基础。
2. 随机requestCode导致通知被系统判定为无效
你创建PendingIntent时用了new Random().nextInt()作为requestCode:
PendingIntent resultPendingIntent = TSB.getPendingIntent( new Random().nextInt(), PendingIntent.FLAG_UPDATE_CURRENT );
每次生成通知都用随机requestCode,会导致每个通知对应的PendingIntent都是全新的。当屏幕锁屏再点亮时,系统会重新梳理通知队列,旧通知因为找不到匹配的PendingIntent,会被系统当成无效通知自动清除。
建议你用一个稳定且唯一的requestCode,比如根据通知的标题、内容生成哈希值,确保同一个通知对应的PendingIntent是一致的,比如:
int requestCode = title.hashCode() + message.hashCode();
3. Intent Flags被错误覆盖
你先给Intent加了FLAG_ACTIVITY_NEW_TASK,之后又用setFlags()直接覆盖了这个设置:
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 这里的setFlags会直接替换掉之前的所有Flags resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
setFlags()会清空之前的所有Flags,如果你需要同时保留FLAG_ACTIVITY_NEW_TASK,应该用addFlags()来追加,或者合并成一行设置:
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
这个问题虽然不是通知消失的直接原因,但可能导致通知跳转Activity时出现异常,间接影响通知的稳定性。
4. 通知渠道的设置(针对Android 8.0+)
如果你的APP运行在Android 8.0及以上版本,要确保通知渠道没有设置自动清除的属性。创建渠道时要这样写:
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "自定义渠道名称", NotificationManager.IMPORTANCE_DEFAULT); channel.setDescription("渠道描述"); // 不要设置任何自动删除相关的属性 NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel);
修改后的完整代码示例
// 构建Intent,正确设置Flags Intent resultIntent = new Intent(mContext, intentClass); // 合并所有需要的Flags,避免覆盖 resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); resultIntent.putExtra("onvan", title); resultIntent.putExtra("message", message); resultIntent.putExtra("link", link); resultIntent.putExtra("linktype", linktype); // 构建TaskStackBuilder TaskStackBuilder TSB = TaskStackBuilder.create(mContext); TSB.addParentStack(intentClass); TSB.addNextIntent(resultIntent); // 使用稳定的requestCode int requestCode = title.hashCode() + message.hashCode(); PendingIntent resultPendingIntent = TSB.getPendingIntent( requestCode, PendingIntent.FLAG_UPDATE_CURRENT ); // 构建通知,关闭自动清除 mBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID); mBuilder.setSmallIcon(R.mipmap.ic_launcher); mBuilder.setContentIntent(resultPendingIntent); mBuilder.setContentTitle(title) .setContentText(message) // 改为false,禁止点击自动清除 .setAutoCancel(false) .setSound(Settings.System.DEFAULT_NOTIFICATION_URI) .setContentIntent(resultPendingIntent); // 发送通知,注意使用唯一的通知ID,避免新通知替换旧通知 NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); // 这里的uniqueNotificationId建议用每个通知的唯一标识,比如自增ID或者内容哈希值 notificationManager.notify(uniqueNotificationId, mBuilder.build());
额外提醒
- 发送通知时一定要用唯一的通知ID,如果重复用同一个ID,新通知会直接替换旧的,导致旧通知消失。
- 如果希望通知在设备重启后依然保留,确保你的通知渠道是持久化的(默认就是),不需要额外设置废弃的
setPersisted(true)。
内容的提问来源于stack exchange,提问作者Navid Abutorab

