I'm trying to build module of reminder in my app to work as following, when user set alarm at exact time it fires a notification.
but, it fails for two cases:
1- when i set alarm time to next 2h and above
2- if i removed the app from task manger ( totally closed )
no notification is triggered but, when i open app for first time i receive all missing notifications at once.
I'm using alarm manger to set the alarm as following:
val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent = PendingIntent.getBroadcast(context, requestCode, myIntent, 0)
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
manager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
timeOnDayCalender.timeInMillis,
pendingIntent
)
}
else -> {
manager.setExact(
AlarmManager.RTC_WAKEUP,
timeOnDayCalender.timeInMillis,
pendingIntent
)
}
}
and receiving my alarm manger in broadcast receiver as following:
class AlarmBroadcast : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val newIntent = Intent(context, AlarmService::class.java)
newIntent.type = intent?.type
newIntent.action = intent?.action
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context?.startForegroundService(newIntent)
} else {
context?.startService(newIntent)
}
}
}
and my AlarmService
class is:
class AlarmService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// show foreground notification to let user there is action happening in background
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
showForegroundNotification()
else
startForeground(
1,
Notification()
)
handleAlarmRedirection(intent)
stopSelf(startId) // to destroy service after work is done & remove the fixed notification.
return START_STICKY
}
private fun showForegroundNotification() {
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel()
} else {
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
""
}
val notificationBuilder = NotificationCompat.Builder(this, channelId)
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setContentTitle("title")
.setContentText("body")
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(101, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String {
val chan = NotificationChannel(
"my_service",
"My Background Service",
NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return "my_service"
}
private fun handleAlarmRedirection(intent: Intent?) {
// logic for pushing the notification is here
}
override fun onDestroy() {
super.onDestroy()
stopForeground(true)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
}
I added the permission to manifest too:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
I hope if anyone have idea about this case.
if anyone have good tutorial or advice for best practice please let me know, I target android 31.