I'm trying to display a notification using the AlarmManager at a specific date, but I'm encountering issues on Android 10 and above. The notification only appears when the app is running. However, when the app is closed, the notification doesn't show up. Can you help me identify the potential problems in the provided code?
For Broadcast Reciever
class MyNotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val taskId = intent?.getIntExtra("taskId", -1)
if (taskId != null && taskId != -1) {
val serviceIntent = Intent(context, MyForegroundService::class.java).apply {
putExtra("taskId", taskId)
}
ContextCompat.startForegroundService(context!!, serviceIntent)
}
In manifest
<activity
android:name=".MyNotificationActivity"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:exported="false" />
<service
android:name=".utils.MyForegroundService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="location"
>
</service>
class MyForegroundService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val taskId = intent?.getIntExtra("taskId", -1)
if (taskId != null && taskId != -1) {
// Load the task from the database using a coroutine
val myTaskDao = AppDatabase.getDatabase(this).myTaskDao()
GlobalScope.launch {
val myTask = myTaskDao.getMyTaskById(taskId)
// Create the notification channel
createNotificationChannel()
// Create the notification intent
val notificationIntent =
Intent(this@MyForegroundService, MyNotificationActivity::class.java).apply {
putExtra("taskId", taskId)
}
val pendingIntent = PendingIntent.getActivity(
this@MyForegroundService,
taskId,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val sharedPreferences = getSharedPreferences("currency_prefs", Context.MODE_PRIVATE)
val selectedCurrency = sharedPreferences.getString("selected_currency", "USD")
val currencySymbols = mapOf("USD" to "$", "EUR" to "€", "GBP" to "£", "JPY" to "¥")
// Get the symbol for the selected currency
val selectedCurrencySymbol = currencySymbols[selectedCurrency] ?: "$"
// Create the notification
val notification = NotificationCompat.Builder(this@MyForegroundService, CHANNEL_ID)
.setContentTitle("Payment for ${myTask[0].description}")
.setContentText("Total amount ${selectedCurrencySymbol + myTask[0].price} is due.")
.setSmallIcon(myTask[0].image)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent) // Set the pending intent
.setAutoCancel(false) // Make the notification dismiss when clicked
.build()
// Start the service in the foreground
startForeground(NOTIFICATION_ID, notification)
}
}
// Return START_STICKY to ensure the service is restarted if it gets killed by the system
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelName = "My Channel"
val channelDescription = "Notification Channel"
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(CHANNEL_ID, channelName, importance).apply {
description = channelDescription
}
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
override fun onTaskRemoved(rootIntent: Intent?) {
val restartServiceIntent = Intent(applicationContext, this.javaClass)
restartServiceIntent.setPackage(packageName)
val restartServicePendingIntent = PendingIntent.getService(
applicationContext, 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT
)
val alarmService: AlarmManager =
applicationContext.getSystemService(ALARM_SERVICE) as AlarmManager
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent
)
super.onTaskRemoved(rootIntent)
}
In Activity
val alarmManager =
requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(requireActivity(), MyNotificationReceiver::class.java)
intent.putExtra("taskId", myTaskId.toInt())
//
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
requireContext(),
0,
intent,
PendingIntent.FLAG_MUTABLE // add the FLAG_MUTABLE flag here
)
} else {
PendingIntent.getBroadcast(requireContext(), 0, intent, 0)
}
// Set the alarm to start at the specified time
alarmManager.set(AlarmManager.RTC_WAKEUP, customTime, pendingIntent)
private val CHANNEL_ID = "my_channel"
private val NOTIFICATION_ID = 1