I'm struggling with notifications.
I want to randomly select text to display in the notification (using random() method on the array of String objects from separate object file NotificationData where I only had one immutable variable called notificationData ), which should appear once a day at a specific time (but for now, for the purpose of the test, I wrote in the code to appear every hour). I'm using AlarmManager for scheduling. The first thing is the notifications does not appear at the specified hour when the app is not currently working (or during the device sleep mode), but after launching the app. And second thing is that after launching the app, notifications appear almost one by one within few seconds. I don't really understand why it happens in this way. It's quite strange for me.
Here's the NotificationUtils class, where I create my notification and put one String from Array inside setContentText() method:
package com.example.quit.notification
class NotificationUtils(context: Context) {
private var mContext = context
private lateinit var notificationBuilder: NotificationCompat.Builder
val notificationManager = NotificationManagerCompat.from(mContext)
private val CHANNEL_ID = "Notification_Channel"
init {
createNotificationChannel()
initNotificationBuilder()
}
fun launchNotification() {
with(NotificationManagerCompat.from(mContext)) {
notificationManager.notify(0, notificationBuilder.build())
}
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Rady"
val description = "Codzienne rady dla zdrowiejących osób uzależnionych"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
this.description = description
}
val notificationManager: NotificationManager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
private fun initNotificationBuilder() {
val sampleIntent = Intent(mContext, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, sampleIntent, 0)
val data = NotificationData.notificationData.random()
notificationBuilder = NotificationCompat.Builder(mContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_support)
.setContentTitle("Rada na dziś")
.setContentText(data)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
}
}
Second class, where I create repeating alarm:
package com.example.quit.notification
@SuppressLint("UnspecifiedImmutableFlag")
class AlarmUtils(context: Context) {
private var mContext = context
private var alarmManager: AlarmManager? = null
private var alarmIntent: PendingIntent
init {
alarmManager = mContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(mContext, AlarmReceiver::class.java).let { mIntent ->
PendingIntent.getBroadcast(mContext, 100, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
fun initRepeatingAlarm(calendar: Calendar) {
calendar.apply {
set(Calendar.HOUR_OF_DAY, 20)
set(Calendar.MINUTE, 30)
set(Calendar.SECOND, 0)
}
alarmManager?.set(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
alarmIntent
)
}
}
Here's my AlarmReceiver , where I set next alarm after one hour in this case (:
package com.example.quit.notification
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val notificationUtils = NotificationUtils(context!!)
notificationUtils.launchNotification()
val calendar = Calendar.getInstance()
calendar.add(Calendar.HOUR_OF_DAY, 1)
val alarmUtils = AlarmUtils(context)
alarmUtils.initRepeatingAlarm(calendar)
}
}
In AndroidManifest.xml file I only added one line intag:
<receiver android:name=".notification.AlarmReceiver" />
And the last thing - in MainActivity class I put those three lines just after setContentView() method:
val calendar = Calendar.getInstance()
val alarmUtils = AlarmUtils(this)
alarmUtils.initRepeatingAlarm(calendar)
I'll be very grateful for any help and explanations.
It is obvious why your notifications appear immediately. In AlarmReceiver
you do this:
val calendar = Calendar.getInstance()
calendar.add(Calendar.HOUR_OF_DAY, 1)
val alarmUtils = AlarmUtils(context)
alarmUtils.initRepeatingAlarm(calendar)
You want to take the current time, add one hour and schedule an alarm at that time (1 hour in the future). However, look at what initRepeatingAlarm()
is doing:
calendar.apply {
set(Calendar.HOUR_OF_DAY, 20)
set(Calendar.MINUTE, 30)
set(Calendar.SECOND, 0)
}
in initRepeatingAlarm()
you are setting the hour, minute and seconds to a fixed value (which is the time that the alarm originally went off). You are overwriting the time that was set in the Calendar
that was passed in. In this case, when the alarm is set, the time is in the past so the alarm triggers immediately.
Regarding why the alarms do not work when the device is sleeping, the call to AlarmManager.set()
is not considered "exact" and the system may delay the alarm to ensure that the device is not constantly awakened (preservation of battery). See this explanation found in the documentation.
If you want the alarm to go off at exactly this time, you need to use a different method, such as setExact()
, and you will need to declare an additional permission SCHEDULE_EXACT_ALARM
(if you target API level 31 or higher)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.