Android应用完全销毁时实现推送通知的代码修改及原理说明
解决Android应用销毁后发送通知的方案
应用完全销毁后,原Activity进程已被系统回收,靠Activity内部代码无法触发通知,必须依赖系统级组件实现。下面给出基于AlarmManager + BroadcastReceiver的精准提醒方案,适配Android全版本。
修改后的完整代码
1. MainActivity.java(设置定时提醒)
import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; import java.util.Calendar; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button setReminderBtn = findViewById(R.id.set_reminder_btn); setReminderBtn.setOnClickListener(v -> { // 设置10秒后触发提醒(可替换为用户指定的时间) Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND, 10); // 创建触发广播的Intent Intent intent = new Intent(MainActivity.this, NotificationReceiver.class); // 用PendingIntent让系统在指定时间触发广播 PendingIntent pendingIntent = PendingIntent.getBroadcast( MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 获取系统AlarmManager服务 AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); if (alarmManager != null) { // Android 12+ 用精确闹钟API(绕过省电策略) if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent ); } else { alarmManager.setExact( AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent ); } } }); } }
2. NotificationReceiver.java(广播接收器,发送通知)
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Build; public class NotificationReceiver extends BroadcastReceiver { private static final String CHANNEL_ID = "REMINDER_CHANNEL"; private static final int NOTIFICATION_ID = 1; @Override public void onReceive(Context context, Intent intent) { // Android 8.0+ 必须创建通知渠道 createNotificationChannel(context); // 构建通知内容 Notification.Builder builder = new Notification.Builder(context) .setSmallIcon(R.drawable.ic_notification) // 替换为你的通知图标 .setContentTitle("提醒") .setContentText("这是你的定时提醒!") .setPriority(Notification.PRIORITY_HIGH); // 适配Android 8.0+渠道要求 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_ID); } // 发送通知 NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { notificationManager.notify(NOTIFICATION_ID, builder.build()); } } private void createNotificationChannel(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "提醒渠道"; String description = "用于发送定时提醒的通知渠道"; int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); NotificationManager notificationManager = context.getSystemService(NotificationManager.class); if (notificationManager != null) { notificationManager.createNotificationChannel(channel); } } } }
3. AndroidManifest.xml(权限与组件注册)
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.reminderapp"> <!-- Android 12+ 精确闹钟权限 --> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <!-- 可选:唤醒屏幕权限,确保通知能触发亮屏 --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.ReminderApp"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 注册广播接收器 --> <receiver android:name=".NotificationReceiver" android:exported="false" /> </application> </manifest>
工作原理
AlarmManager 系统级触发:
- AlarmManager是Android系统内置服务,不受应用进程生命周期影响。即使应用被完全销毁,系统会在指定时间执行我们设置的
PendingIntent。 setExactAndAllowWhileIdle是Android 12+推荐的精确闹钟API,能绕过系统省电策略,确保提醒准时触发;旧版本用setExact。
- AlarmManager是Android系统内置服务,不受应用进程生命周期影响。即使应用被完全销毁,系统会在指定时间执行我们设置的
BroadcastReceiver 独立执行:
NotificationReceiver是注册在Manifest中的独立组件,应用销毁后,系统仍能启动它执行onReceive方法,在这里完成通知的构建与发送。
通知渠道适配:
- Android 8.0+要求所有通知必须归属到指定渠道,否则无法显示。
createNotificationChannel方法用于创建并配置通知渠道的优先级、描述等。
- Android 8.0+要求所有通知必须归属到指定渠道,否则无法显示。
权限说明:
SCHEDULE_EXACT_ALARM是Android 12+强制要求的精确闹钟权限,部分机型需用户手动开启(可在代码中引导跳转权限设置页面)。WAKE_LOCK可选,用于确保设备在休眠状态下也能触发通知并唤醒屏幕。
内容的提问来源于stack exchange,提问作者user20097957
相关产品推荐
相关产品推荐

