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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:06:03