Can't cancel alarm with AlarmManager.cancel() on 24 API - android

Have 2 methods:
addAlarm()
val myIntent = Intent(context, AlarmReceiver::class.java)
if (SDK_INT > Build.VERSION_CODES.M) {
myIntent.action = "ADD_ALARM"
} else {
myIntent.putExtra("alarm", alarm)
}
val pendingIntent = PendingIntent.getBroadcast(context, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
if (SDK_INT < Build.VERSION_CODES.M)
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
else
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
/*
if I try to cancel alarm after creating like this:
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(pendingIntent)
it would work and alarm would be canceled. Seems like problem is
in pendingIntent.
*/
deleteAlarm()
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
var myIntent = Intent(context, AlarmReceiver::class.java)
//with flag FLAG_NO_CREATE return null
val pendingIntent = PendingIntent.getBroadcast(context, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.cancel(pendingIntent)
Everything works great on api 23, but on api 24 alarm do not canceling. Is it problem with intent.action? What did i miss?

Ok, I solved it with adding intent.action like this:
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
var myIntent = Intent(context, AlarmReceiver::class.java)
if (SDK_INT > Build.VERSION_CODES.M) {
myIntent.action = "ADD_ALARM"
}
val pendingIntent = PendingIntent.getBroadcast(context, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.cancel(pendingIntent)

Related

AlarmManager.setExact() is always slow

The alarms in my app are consistently around 40-50 seconds late.
I'm assuming this is due to a problem in the AlarmManager.setExact() but I can't be sure.
Here is my schedule function calling setExact():
fun schedule(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, AlarmReceiver::class.java)
intent.putExtra("recurring", recurring)
val alarmPendingIntent = PendingIntent.getBroadcast(
context,
alarmId, intent, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
)
val calendar: Calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis()
calendar.set(Calendar.HOUR_OF_DAY, hour)
calendar.set(Calendar.MINUTE, minute)
//if alarm time has already passed, increment day by 1
if (calendar.timeInMillis <= System.currentTimeMillis()) {
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + 1)
}
val toastTime = if (minute < 10) {
"$hour:0$minute"
} else {
"$hour:$minute"
}
if (!recurring) {
Toast.makeText(
context,
"One Time Alarm set for $toastTime",
Toast.LENGTH_LONG
).show()
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
alarmPendingIntent
)
} else {
Toast.makeText(context, "Alarm set daily for $toastTime", Toast.LENGTH_LONG)
.show()
val runDaily = (24 * 60 * 60 * 1000).toLong()
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
runDaily,
alarmPendingIntent
)
}
started = true
}
If there is no solution available, is there maybe a better alternative to the AlarmManager?

How to cancel alarm set with setAlarmClock() Android

How can I cancel an alarm set with setAlarmClock()?
val alarmReceiver = Intent(applicationContext, AlarmReceiver::class.java)
val alarmReceiverPi = PendingIntent.getBroadcast(applicationContext, 0, alarmReceiver, 0)
val alarmInfo = AlarmManager.AlarmClockInfo(time, alarmReceiverPi)
alarmManager.setAlarmClock(alarmInfo, alarmReceiverPi)
The id to used to locate the PendingIntent, following is my example:
fun setAlarm() {
val alarmPendingIntent = getAlarmPendingIntent(alarmId)
alarmManager.setExact(AlarmManager.RTC_WAKEUP, _timeLong.value, alarmPendingIntent)
showToast("Alarm has been set")
}
fun cancelAlarm() {
val alarmPendingIntent = getAlarmPendingIntent(alarmId)
alarmManager.cancel(alarmPendingIntent)
showToast("Alarm has bee canceled")
}
private fun getAlarmPendingIntent(id: Long): PendingIntent {
val intent = Intent(getApplication(), AlarmReceiver::class.java)
return PendingIntent.getBroadcast(getApplication(), id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) //will override if same id
}
Helpful reading:
How to cancel alarm from AlarmManager

AlarmManager set is not firing broadcast

I'm trying to schedule notifications using the AlarmManager but for whatever reason, the onReceive method on my receiver isn't firing.
Here's how I'm scheduling the alarm
val intent = Intent(this, ReminderReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
val cal: Calendar = Calendar.getInstance()
cal.add(Calendar.SECOND, 5)
val amanager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
amanager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
and here's the onReceive method
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,"notification", Toast.LENGTH_SHORT).show()
}
I tried manually sending a broadcast to see if it works and there's no problem there so the issue shouldn't be related to the manifest.
I'm running this on MIUI12 android 10
I see no issue with your logic if your problem still prevails, try the following as a workaround
val intent = Intent(this, ReminderReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
// val cal: Calendar = Calendar.getInstance()
// cal.add(Calendar.SECOND, 5)
val triggerTime = SystemClock.elapsedRealtime() + 5_000 // five seconds from now
val amanager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// amanager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
AlarmManagerCompat.setExactAndAllowWhileIdle(
amanager,
AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerTime,
pendingIntent
)

How to set multiple alarms in kotlin?

so I'm new to coding and I'm making an app for Muslims prayer times and I want an alarms to be set repeatedly on these times
I tried to many things but It doesn't works!
I have a praytimes class and if anyone wants it I'll put it
I will be more thankful, if you could help me on how to set an alarm for 1 prayer so I could do the rest.
Main Activity
val latitude = 30.354802
val longitude = 42.2461069
val timezonoffset = 3.0
val timeZoneId = "Middle East/Alowiqila"
val prayTimes = PrayTimes()
prayTimes.timeFormat = prayTimes.time12//
prayTimes.calcMethod = prayTimes.makkah// Muslim World League (MWL)
prayTimes.asrJuristic = prayTimes.hanafi// Shafii (standard)
prayTimes.adjustHighLats = prayTimes.angleBased
val offsets = intArrayOf(0, 0, 0, 0, 0, 0, 0) // {Fajr,Sunrise,Dhuhr,Asr,Sunset,Maghrib,Isha}
prayTimes.tune(offsets)
val cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneId))
cal.time = Date()
val times = prayTimes.getPrayerTimes(cal, latitude, longitude, timezonoffset)
println("prayer times for Alowiqila")
System.out.println("Fajr : " + times.get(0))
System.out.println("Sunrise : " + times.get(1))
System.out.println("Duhr : " + times.get(2))
System.out.println("Asr : " + times.get(3))
System.out.println("Sunset : " + times.get(4))
System.out.println("Magrib : " + times.get(5))
System.out.println("Isha : " + times.get(6))
// I want the Alarm to be set to the code above it
fun startAlarm(isNotification:Boolean, isRepeat:Boolean) {
val manager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val myIntent= Intent(this#MainActivity, AlarmReceiver::class.java)
val pendingIntent:PendingIntent
// SET TIME HERE
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 15)
calendar.set(Calendar.MINUTE, 20)
pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0)
if (!isRepeat)
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 3000, pendingIntent)
else
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, pendingIntent)
}
AlarmReceiver.kt
and here is my alarm receiver in witch I've added me notifications
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val builder = NotificationCompat.Builder(context)
val myIntent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context,
0,
myIntent,
FLAG_ONE_SHOT
)
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setContentTitle("موعد الاذان")
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_LIGHTS or Notification.DEFAULT_SOUND)
.setContentInfo("Info")
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(1, builder.build())
}
You have to put different requestCode in pending intent, each alarm manager requires different requestCode.
in your mainActivity
pendingIntent = PendingIntent.getBroadcast(this, (0..2147483647).random(), myIntent, 0)

How to check if alarm does not have a pending intent?

After I call schedulePing my alarm fires at set time period. With pingScheduled I can see if pending intent exists. However, if I cancel the alarm with cancelPing the pingScheduled still return true.
fun schedulePing(context: Context) {
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, EventReceiver::class.java)
intent.action = EventReceiver.PING
val pendingIntent = PendingIntent.getBroadcast(context, PING, intent,
PendingIntent.FLAG_CANCEL_CURRENT)
val s = SettingsUtil.load(context)
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + s.periodPing, s.periodPing,
pendingIntent)
}
fun cancelPing(context: Context) {
if (pingScheduled(context).not()) return
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, EventReceiver::class.java)
intent.action = EventReceiver.PING
val pendingIntent = PendingIntent.getBroadcast(context, PING, intent,
PendingIntent.FLAG_CANCEL_CURRENT)
am.cancel(pendingIntent)
}
fun pingScheduled(context: Context): Boolean {
val intent = Intent(context, EventReceiver::class.java)
intent.action = EventReceiver.PING
return PendingIntent.getBroadcast(context, PING,
intent, PendingIntent.FLAG_NO_CREATE) != null
}
am.cancel(pendingIntent) cancel alram, but does not discard the pending intent. So it is important to call
pendingIntent.cancel after am.cancel to be able to check correct presence with PendingIntent.FLAG_NO_CREATE

Categories

Resources