Android中如何防止常驻通知在应用被划掉后被清除
问题解决:多任务关闭应用后Ongoing通知被清除
你的问题核心在于:直接在Activity中创建的通知依附于应用主进程,当从多任务面板划掉应用时,系统会终止主进程,连带清除该进程创建的所有通知——哪怕你设置了setOngoing(true)也没用。
要让Ongoing通知在应用关闭后依然保留,必须使用**前台服务(Foreground Service)**来托管通知,因为前台服务是独立的后台组件,只要服务处于运行状态,通知就会被系统持续保留。
具体实现步骤:
- 创建前台服务类
把通知的创建逻辑移到Service中,通过startForeground()将服务与通知绑定:
public class MyForegroundService extends Service { private static final String CHANNEL_ID = "C1"; private static final int NOTIFICATION_ID = 1; @Override public void onCreate() { super.onCreate(); createNotificationChannel(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 创建跳转至主页面的PendingIntent Intent activityIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, activityIntent, PendingIntent.FLAG_IMMUTABLE); // 构建Ongoing通知 Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("XXXX") .setContentText("XXXXXXXX") .setPriority(NotificationCompat.PRIORITY_MAX) .setContentIntent(pendingIntent) .setOngoing(true) .setAutoCancel(false) .build(); // 启动前台服务,绑定通知 startForeground(NOTIFICATION_ID, notification); // 返回START_STICKY,让系统在服务意外终止后尝试重启 return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "C1"; String description = "C1 is C1"; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } }
- 在Manifest中声明权限与服务
添加前台服务和通知权限,并注册服务:
<!-- 前台服务基础权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Android 13+ 必须的通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application ...> <service android:name=".MyForegroundService" /> </application>
- 在Activity中启动前台服务
在主页面初始化时启动服务,注意Android 13+需要先申请通知权限:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 处理Android 13+的通知权限申请 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) startForegroundService(); }).launch(Manifest.permission.POST_NOTIFICATIONS); } else { startForegroundService(); } } else { startForegroundService(); } } private void startForegroundService() { Intent serviceIntent = new Intent(this, MyForegroundService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); } else { startService(serviceIntent); } }
关键说明:
- 前台服务的通知会被系统标记为“正在运行的服务”,无法手动清除(除非停止服务),符合你需要的持久快捷入口需求。
START_STICKY参数能让系统在资源充足时,自动重启意外终止的服务,进一步保障通知的持久性。
内容的提问来源于stack exchange,提问作者Jammy Lee
相关产品推荐
相关产品推荐

