如何在android系统中使用闹钟管理器设置多个闹钟



我正在构建一个警报应用程序。我已经成功实现了基本报警功能。

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);

在我的应用中,用户可以选择每周重复报警的天数(sunday,monday...)。我试图创建多个警报,每周重复,但不知道如何做到这一点。我可以使用(重复)间隔创建它还是应该创建多个警报管理器?

需要用different Broadcast id's代替pending intents。类似的:

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);

使用系统时间应该是每个挂起的唯一标识符意图你开火。

From the docs:

如果已经为这个Intent安排了一个警报(使用由filterEquals(Intent)定义的两个意图的相等性它将被删除并被这个

所取代。

多个AlarmManagers不能解决您的问题。如果他们有多个不同的闹钟(不同的时间和不同的日子),那么你需要在BroadcastReceiver中设置闹钟,每次你触发上一个闹钟。

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

要设置多个警报,您需要每次定义您的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参数(如@parag所建议的)是未使用的,因此这不是正确的方法。

set Broadcast id for pendingIntent

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);
}

使用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())
    }
}

我所做的类似于如何移动到链表中的下一个元素。我在数据库中保留了一个ReminderEntity,其中包含用户启用闹钟的所有日子。然后我只安排第一天。当第一天开始的时候,我就开始安排第二天的工作,以此类推。同样的道理,如果用户删除第一个即将到来的警报发生之前。在本例中,我从实体中清除已删除的日期,并为下一个可用的日期安排闹钟。

对挂起的意图使用不同的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);

最新更新