如何在Android中使用闹钟管理器设置多个闹钟

63

我正在开发一个闹钟应用程序。我已经成功实现了基本的闹钟功能。

Calendar calendar = Calendar.getInstance();
calendar.set(calendar.HOUR_OF_DAY, sHour);
calendar.set(calendar.MINUTE, sMin);
calendar.set(calendar.SECOND, 0);
calendar.set(calendar.MILLISECOND, 0);
long sdl = calendar.getTimeInMillis();

Intent intent = new Intent(AlarmList.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmList.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager ALARM1 = (AlarmManager)getSystemService(ALARM_SERVICE);
ALARM1.set(AlarmManager.RTC_WAKEUP, sdl, sender);

在我的应用程序中,用户可以选择每周重复的日期(星期日、星期一...)来设置闹钟。

我正在尝试创建多个每周重复的闹钟,但不知道如何操作。

我应该使用(重复)间隔来创建它,还是应该创建多个闹钟管理器?


只需使用id字段...检查set on alarmmanager的文档。 - Warpzit
请查看我在此帖子中的回答:https://dev59.com/Nmcs5IYBdhLWcg3wgkWu#31805171 - Junaid
7个回答

176
你需要为不同的待定 intent 使用不同的广播 ID。像这样:

你需要为不同的 pending intents 使用不同的广播 ID。类似这样:

Intent intent = new Intent(load.this, AlarmReceiver.class);
final int id = (int) System.currentTimeMillis();
PendingIntent appIntent = PendingIntent.getBroadcast(this, id, intent, PendingIntent.FLAG_ONE_SHOT);

使用系统时间作为您触发的每个挂起意图的唯一标识符。


5
如何最终取消它们?我们需要保留 _id 的引用吗? - TootsieRockNRoll
1
@user2427819 是的,对于取消操作,我们需要传递与 PendingIntent.getBroadcast 中使用的相同的 id。 - Parag Chauhan
1
@ULHASPATIL 当然可以工作。它取决于其广播ID,所以不用担心闹钟时间,您可以根据自己的要求设置任何时间。 - Parag Chauhan
5
@Parag Chauhan: 由于某些原因,谷歌并没有实现一个简单的cancelAll()调用。就像在附近消息中没有cancelAll()一样,我们必须实现大量的代码来实现简单的功能。而我们的经理们不会很高兴,因为没人会计算这个成本。 - Roel
1
@hosseinAmini,PendingIntent.FLAG_ONE_SHOT - 表示此 PendingIntent 只能使用一次。 - 4xMafole
显示剩余4条评论

11

来自文档

如果已经为此Intent安排了一个闹钟(两个意图的相等性由filterEquals(Intent)定义),那么它将被删除并替换为这个。

多个AlarmManagers不能解决您的问题。如果它们有多个不同的闹钟(不同的时间和不同的天数),则每次触发上一个闹钟时,您都需要在BroadcastReceiver中设置闹钟。

您还需要持有RECEIVE_BOOT_COMPLETED,并有一个BroadcastReceiver来接收引导,以便如果手机重新启动,您可以重新安排闹钟。


7
要设置多个闹钟,您需要每次定义您的Intent,以便它与其他Intent区分开来。我发现最简单的方法是将Intentdata字段设置为以下内容:
// give your alarm an id and save it somewhere
// in case you want to cancel it in future
String myAlarmId = ...;

// create your Intent
Intent intent = new Intent(AlarmList.this, AlarmReceiver.class);
intent.setData(Uri.parse("myalarms://" + myAlarmId));
...

你的代码@Hassy31是没问题的,不需要改动。

需要注意的是,根据文档,PendingIntent.getBroadcast()方法中的requestCode参数未使用,因此这并不是正确的方法。


1
嗨,哪里标明它是未使用的? - blacharnia
这在写作时可能是正确的,但现在可能不再正确。 - Adil Hussain

2

设置待处理意图的广播id

for (int id = 0; id < 3; id++) {
        // Define pendingintent
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id,ntent, 0); 
        // set() schedules an alarm 
        alarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
}

1
使用Android闹钟管理器设置多个闹钟。
//RC_ARRAY is store all the code that generate when alarm is set 
private lateinit var RC_ARRAY:ArrayList<Int>
//tick is just hold the request when new alarm set
private var tick :Int=0

//setAlarm method set alarm
fun setAlarm(c: Calendar, context: Context) {
    val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

//when alarm store set the request assign to tick variable
    tick = System.currentTimeMillis().toInt()
//Add all the alarm Request into RC_ARRAY for just cancel the alarm
    RC_ARRAY.add(tick)

//Notification Broadcast intent
    val intentAlarm = Intent(context, AlaramFireReceiver::class.java).let {
        PendingIntent.getBroadcast(context, tick, it, PendingIntent.FLAG_ONE_SHOT)
    }


//alarm fire next day if this condition is not statisfied 
    if (c.before(Calendar.getInstance())) {
        c.add(Calendar.DATE, 1)
    }
//set alarm
    manager.setExact(AlarmManager.RTC_WAKEUP, c.timeInMillis, intentAlarm)


}
//remove specific alarm
private fun removeAlarm(context: Context) {
    val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    //remove specific alarm according to alarm request code
    for (i in RC_ARRAY){
        val intentAlarm = Intent(context, AlaramFireReceiver::class.java).let {
            PendingIntent.getBroadcast(context, i, it, 0)
        }
//cancel alarm
        manager.cancel(intentAlarm)
    }
}



//delivers notification for alarm
class AlaramFireReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
//Notification ID
       val channelid="channelId"
        val manger=context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//check for device only available for Oreo and above  
        if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.O){
            val channel= NotificationChannel(channelid,"alarm notification",NotificationManager.IMPORTANCE_HIGH)
            channel.enableLights(true)
            manger.createNotificationChannel(channel)
        }
//build notification
        val build=NotificationCompat.Builder(context,channelid)
            .setSmallIcon(R.drawable.ic_access_time_black_24dp)
            .setContentTitle("alarm")
            .setContentTitle("time done")
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setColor(Color.RED)
//Deliver notification 
        manger.notify(0,build.build())
    }
}

0
我所做的类似于在链表中移动到下一个元素。我在数据库中保留了一个ReminderEntity,其中包含用户启用闹钟响铃的所有星期几。然后我仅安排第一天。当第一天触发时,我会安排下一天,以此类推。 如果用户在第一个闹钟发生之前删除了它,则会清除实体中已删除的日期,并为下一个可用日期安排闹钟。

0

使用不同的requestCode来为待处理意图设置标识,并使用.FLAG_MUTABLE作为标记类型

int requestCode = (int) System.currentTimeMillis();
Intent intent = new Intent(load.this, AlarmReceiver.class);
return PendingIntent.getBroadcast(this, requestCode , intent, PendingIntent.FLAG_MUTABLE);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接