简体   繁体   English

重复通知问题

[英]Repeating notifications issue

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).我想在通知中随机显示 select 文本(在来自单独的 object 文件NotificationData的 String 对象数组上使用random()方法,其中我只有一个名为notificationData的不可变变量),它应该每天在特定时间出现一次(但现在,为了测试的目的,我在代码中写了每小时出现一次)。 I'm using AlarmManager for scheduling.我正在使用AlarmManager进行调度。 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:这是NotificationUtils class,我在其中创建通知并将数组中的一个字符串放入setContentText()方法中:

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:第二个 class,我在其中创建重复警报:

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 (:这是我的AlarmReceiver ,在这种情况下,我会在一小时后设置下一个警报(:

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 inAndroidManifest.xml文件中我只添加了一行tag:标签:

<receiver android:name=".notification.AlarmReceiver" />

And the last thing - in MainActivity class I put those three lines just after setContentView() method:最后一件事 - 在MainActivity class 中,我将这三行放在setContentView()方法之后:

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:AlarmReceiver你这样做:

    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).您想要使用当前时间,加上一小时并在该时间(未来 1 小时)安排闹钟。 However, look at what initRepeatingAlarm() is doing:但是,看看initRepeatingAlarm()正在做什么:

    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).initRepeatingAlarm()中,您将小时、分钟和秒设置为固定值(这是闹钟最初响起的时间)。 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.您正在覆盖传入的Calendar中设置的时间。在这种情况下,设置闹钟时,时间是过去的时间,因此会立即触发闹钟。


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).关于为什么当设备处于休眠状态时闹钟不起作用,对AlarmManager.set()的调用不被认为是“准确的”,系统可能会延迟闹钟以确保设备不会不断被唤醒(保护电池)。 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)如果你想让 go 的闹钟正好在这个时候关闭,你需要使用不同的方法,比如setExact() ,你需要声明一个额外的权限SCHEDULE_EXACT_ALARM (如果你的目标是 API 级别 31 或更高)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM