Home > other >  AlarmManager fires too early
AlarmManager fires too early

Time:02-18

I have this code in my class:

public void setAlarm(Context context)
{
    AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, StepCountUpdaterAlarm.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    Long startOfTommorowMillis = calendar.getTimeInMillis();

    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    Long startOfTodayMillis = calendar.getTimeInMillis();

    calendar.set(Calendar.HOUR_OF_DAY, 6);
    calendar.set(Calendar.MINUTE, 30);
    calendar.set(Calendar.SECOND, 0);
    Long startOfAlarmMillis = calendar.getTimeInMillis() - startOfTodayMillis;

    Long totalWaitMillis = (startOfTodayMillis   startOfAlarmMillis) - System.currentTimeMillis();

    if(totalWaitMillis < 0) return;
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
                totalWaitMillis,
                pendingIntent);
    } else {
        alarmManager.set(AlarmManager.RTC_WAKEUP,
                totalWaitMillis,
                pendingIntent);
    }
}

What I am trying to do is to have this alarm fire at 6:30am UTC every day. To do that I use Long totalWaitMillis = (startOfTomorrowMillis startOfAlarmMillis) - System.currentTimeMillis(); but for testing purposes, i changed it to use startOfTodayMillis so i can test the alarm. I managed to get the calendar to show the correct firing times with startOfTodayMillis - startOfAlarmMillis. When i subtract System.currentTimeMillis(), it seems to provide the correct amount of millisecond delay for the alarm to fire next. In effect, it calculates the time in milliseconds till it hits 6:30 today (I have not fired it in the past in this scenario). Yet despite this, it fires extremely early and does its task far earlier than expected. When I use startOfTomorrowMillis startOfAlarmMillis as well, it fires practically a day early and multiple times. I am a novice when it comes to working with AlarmManager so any help here would be appreciated.

EDIT: I am aware that these alarm timers are not exact. I expected a few seconds offset but not minutes or near enough a day. To add a bit of detail, I just tried setting the alarm an hour from now, it fired at least 5 times within around 20 seconds, after an initial 30 seconds from the alarm being set. My device currently uses the setAndAllowWhileIdle method.

CodePudding user response:

For recurring alarm why you are doing like that.. alarm manager already has own method for alarm in every 24 hour.

first create a class with broadcast receiver like

                class AlarmReceiver : BroadcastReceiver() {
                
                    override fun onReceive(context: Context, intent: Intent?) {
                        Log.d("this", "notify")
                
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                
                            val intent = Intent(context, AlarmActivity2::class.java)
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
                            val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
                
                            val builder = NotificationCompat.Builder(context, "111")
                                .setSmallIcon(R.drawable.blue_stringart)
                                .setContentTitle("Alarm is running")
                                .setAutoCancel(true)
                                .setDefaults(NotificationCompat.DEFAULT_ALL)
                                .setDefaults(NotificationCompat.DEFAULT_SOUND)
                                .setDefaults(NotificationCompat.DEFAULT_VIBRATE)
                                .setPriority(NotificationCompat.PRIORITY_HIGH)
                                .addAction(R.drawable.ic_baseline_stop_24,"Stop",pendingIntent)
                                .setContentIntent(pendingIntent)
                
                            val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
                            val r = RingtoneManager.getRingtone(context, notification)
                            r.play()
                
                            val notificationManagerCompat = NotificationManagerCompat.from(context)
                            notificationManagerCompat.notify(123, builder.build())
                
                        }
                
                    }
                
                } 
        

after that go to your activity class make 2 method and call in oncreate

            private fun setAlarm1() {
            var calender: Calendar
          calender = Calendar.getInstance()
                        calender.set(Calendar.HOUR_OF_DAY, PUT_YOUR_ALARM HOUR)
                        calender.set(Calendar.MINUTE, PUT_YOUR_ALARM MINUTE)
                        calender.set(Calendar.SECOND, 0)
                    alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
                    val thuReq: Long = Calendar.getInstance().timeInMillis   1
                    var reqReqCode = thuReq.toInt()
                    if (calender.timeInMillis < System.currentTimeMillis()) {
                        calender.add(Calendar.DAY_OF_YEAR, 1)
                    }
                    val alarmTimeMilsec = calender.timeInMillis
                    val intent = Intent(this, AlarmReceiver::class.java)
                    intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
                    val pendingIntent = PendingIntent.getBroadcast(this, reqReqCode, intent, 0)
            
                    alarmManager.setRepeating(
                        AlarmManager.RTC_WAKEUP,
                        calender.timeInMillis,
                       24 * 60 * 60 * 1000,// or AlarmManager.INTERVAL_DAY
                        pendingIntent
                    )
    
    
        private fun createNotificationChannel() {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val name = "Alarmclock Channel"
                val description = " Reminder Alarm manager"
                val importance = NotificationManager.IMPORTANCE_HIGH
                val notificationChannel = NotificationChannel(CHANNELID, name, importance)
                notificationChannel.description = description
                val notificationManager =
                    getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
                notificationManager.createNotificationChannel(notificationChannel)
            }
        }

Note - Must to do(go to your app setting and give notification permission on) 1.alarmManager.setRepeating here you can use your alarm type as your wish. 2.requestcode must be unique for each alarm. 3. you must take a alarm time and keep in calender.timeInMillis which is you expecting alarm time.

still problem comments below

  • Related