I've been trying to implement Notifications in my app without effectively succeeding. The following are my observations:
Requirements:
- After scheduling a Notification it has to be repeated on a monthly basis.
- The notification will be inflated with some model object data, so the object needs to be passed to the notification builder.
How I tackled the problem so far:
I created a NotificationScheduler object that basically creates a PendingIntent for the notification to be fired.
object NotificationScheduler {
fun scheduleNotification(context: Context, model: Model, cal: Calendar) {
cal.set(Calendar.HOUR_OF_DAY, 11)
val notificationIntent = Intent(context, NotificationPublisher::class.java)
notificationIntent.putExtra("model", Utils.parcelToBytes(model))
val pendingIntent = PendingIntent.getBroadcast(context, 1, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
}
}
Then I have a NotificationPublisher class that should show the notification and set the next one by calling NotificationScheduler again.
class NotificationPublisher: BroadcastReceiver() {
var model: Model? = null
override fun onReceive(context: Context?, intent: Intent?) {
val modelBytes = intent?.getByteArrayExtra("model")
if (modelBytes != null) {
model = Utils.bytesToParcel(modelBytes, Model.CREATOR)
}
val notificationBuilder = NotificationBuilder(context!!, model!!)
val notification = notificationBuilder.buildNotification()
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(1, notification)
//schedules the next notification
NotificationScheduler.scheduleNotification(context, model!!, Calendar.getInstance())
}
}
Where the NotificationBuilder class just takes the context and the model and builds the notification
class NotificationBuilder(val context: Context, val model: Model) {
fun buildNotification(): Notification {
generateNotificationChannel(context)
val builder = NotificationCompat.Builder(context, "ID")
.setSmallIcon(R.drawable.sub)
.setContentTitle(model.title)
.setPriority(NotificationCompat.PRIORITY_HIGH)
return builder.build()
}
private fun generateNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Test"
val description = "description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel("ID", name, importance)
channel.description = description
val notificationManager = context.getSystemService(NotificationManager::class.java)
notificationManager?.createNotificationChannel(channel)
}
}
My problem with this approach:
It works if I purposely display the notification as soon as it is created, but I get a NullPointerException whenever the user, for example, reboots his device or kills the process. While debugging I found out that the data I store in the notificationIntent in NotificationScheduler, once the device is rebooted, isn't available anymore in the onReceive() of the NotificationPublisher and therefore will generate a NPE.
I think I am doing something conceptually wrong with this approach, and I'd like you to help me figure out how to achieve the above mentioned requirements.
from Android Notification - How to create a system based on model properties
No comments:
Post a Comment