如何在Android通知中添加按钮以取消指定时间触发的闹钟
Android通知添加闹钟取消按钮实现方案
核心实现逻辑是给通知添加动作按钮绑定自定义广播,接收取消事件后停止铃声、移除对应通知。以下是修改后的完整代码:
import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.media.Ringtone; import android.media.RingtoneManager; import android.os.Build; import android.util.Log; import android.widget.Toast; import androidx.core.app.NotificationCompat; import com.example.oceansscheduler.MainActivity; import com.example.oceansscheduler.R; public class AlarmReceiver extends BroadcastReceiver { public static final String ACTION_STOP_ALARM = "com.example.oceansscheduler.STOP_ALARM"; private static Ringtone alarmRingtone; // 全局保存铃声实例方便控制停止 public void showNotification(Context context, String title, String message, Intent intent, int reqCode) { int pendingFlag = PendingIntent.FLAG_ONE_SHOT; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { pendingFlag |= PendingIntent.FLAG_IMMUTABLE; } PendingIntent pendingIntent = PendingIntent.getActivity(context, reqCode, intent, pendingFlag); String CHANNEL_ID = "alarm_channel"; // 构建取消闹钟的PendingIntent Intent stopIntent = new Intent(context, AlarmReceiver.class); stopIntent.setAction(ACTION_STOP_ALARM); stopIntent.putExtra("NOTIFICATION_ID", reqCode); PendingIntent stopPendingIntent = PendingIntent.getBroadcast(context, reqCode, stopIntent, pendingFlag); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_baseline_alarm_24) .setContentTitle(title) .setStyle(new NotificationCompat.BigTextStyle()) .setPriority(NotificationCompat.PRIORITY_MAX) .setContentText(message) .setAutoCancel(true) .setContentIntent(pendingIntent) // 添加取消闹钟按钮,第一个参数可替换为你自己的取消图标 .addAction(R.drawable.ic_baseline_cancel_24, "取消闹钟", stopPendingIntent); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "闹钟提醒通道"; int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance); // 关闭通道自带铃声,改为代码手动控制播放 mChannel.setSound(null, null); notificationManager.createNotificationChannel(mChannel); } notificationManager.notify(reqCode, notificationBuilder.build()); // 手动播放闹钟铃声,方便后续控制停止 if (alarmRingtone == null) { alarmRingtone = RingtoneManager.getRingtone(context, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)); } if (!alarmRingtone.isPlaying()) { alarmRingtone.play(); } Log.d("showNotification", "showNotification: " + reqCode); } @Override public void onReceive(Context context, Intent intent) { // 优先处理取消闹钟的广播事件 if (ACTION_STOP_ALARM.equals(intent.getAction())) { // 停止正在播放的铃声 if (alarmRingtone != null && alarmRingtone.isPlaying()) { alarmRingtone.stop(); alarmRingtone = null; } // 移除对应通知 int notificationId = intent.getIntExtra("NOTIFICATION_ID", 1); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(notificationId); return; } // 原有闹钟触发逻辑 SQLiteDatabase db = context.openOrCreateDatabase("NotificationDatabase", Context.MODE_PRIVATE, null); Cursor data = db.rawQuery("SELECT * FROM PersonalNotif", null); Log.d("Count", String.valueOf(data.getCount())); if (data.getCount() > 0) { data.moveToFirst(); String NameOfNotif = data.getString(0); Toast.makeText(context, NameOfNotif, Toast.LENGTH_LONG).show(); // 实际使用时reqCode需替换为每个闹钟唯一的标识,避免多个闹钟互相覆盖 int reqCode = 1; Intent intentNotif = new Intent(context, MainActivity.class); showNotification(context, NameOfNotif, "您的提醒已触发!", intentNotif, reqCode); } } }
注意事项
- 需在
AndroidManifest.xml中为AlarmReceiver注册自定义动作:
<receiver android:name=".AlarmReceiver" android:exported="true"> <intent-filter> <action android:name="com.example.oceansscheduler.STOP_ALARM" /> <!-- 保留你原有配置的闹钟触发action --> </intent-filter> </receiver>
- 若你有多个闹钟同时存在,必须保证每个闹钟的
reqCode唯一,否则通知和PendingIntent会互相覆盖 - 若需要闹钟长时间响铃,建议将铃声播放逻辑放到前台服务中管理,避免进程被系统回收导致铃声意外中断
内容的提问来源于stack exchange,提问作者user15473634
相关产品推荐
相关产品推荐

