为什么我每次打开 Android 应用程序时都会显示通知?

Why does my notification show every time I open my Android app?

我设置此代码(或者我认为)每 7 天在用户的 Android 设备上显示一次通知,即使用户重新启动他们的设备也是如此。但我看到的副作用是,每次用户打开应用程序时,它也会弹出该通知。

我该如何设置才能使通知正确设置,即使在重新启动后也是如此,但要到要求的时间才会显示。

我有一个 MainActivity 这个:

override fun onCreate(savedInstanceState: Bundle?) {
  val bootRec = BootReceiver()
  bootRec.scheduleNotifications(this)
}

它用这个调用 BootReceiver:

class BootReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == "android.intent.action.BOOT_COMPLETED") {
            scheduleNotifications(context)
        }
    }

    fun scheduleNotifications(context: Context) {
        val receiver = ComponentName(context, BootReceiver::class.java)

        context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
        )

        val alarmMgr: AlarmManager?

        alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val alarmIntent: PendingIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
            PendingIntent.getBroadcast(context, 0, intent, 0)
        }

        // Set the alarm to start at 8:30 a.m.
        val calendar: Calendar = Calendar.getInstance().apply {
            timeInMillis = System.currentTimeMillis()
            set(Calendar.DAY_OF_WEEK, 1)
            set(Calendar.HOUR_OF_DAY, 15)
            set(Calendar.MINUTE, 13)
        }

        // setRepeating() lets you specify a precise custom interval--in this case,
        // 1 week.
        alarmMgr.setRepeating(
            AlarmManager.RTC_WAKEUP,
            calendar.timeInMillis,
            AlarmManager.INTERVAL_DAY * 7,
            alarmIntent
        )
    }
}

依次调用 AlarmReceiver:

class AlarmReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val notificationManager = context.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
        val notChanId = "icollecteverything"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationChannel = NotificationChannel(notChanId, "My Notifications", NotificationManager.IMPORTANCE_MAX)
            notificationChannel.enableLights(true)
            notificationChannel.lightColor = Color.BLUE
            notificationChannel.vibrationPattern = longArrayOf(0, 1000, 500, 1000)
            notificationChannel.enableVibration(true)
            notificationManager.createNotificationChannel(notificationChannel)
        }

        // Create an explicit intent for an Activity in your app
        val intentMain = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intentMain, 0)

        val notification = NotificationCompat.Builder(context, notChanId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(NotificationManagerCompat.IMPORTANCE_HIGH)
            .setContentIntent(pendingIntent)
            .setContentTitle("Title")
            .setContentText("Notification Text.")
            .setStyle(
                NotificationCompat.BigTextStyle()
                    .bigText("Notification Text."))
            .build()
        notificationManager.notify(1, notification)
    }

}

AndroidManifest 里面有这个:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<receiver android:name=".helper.AlarmReceiver" android:enabled="true"/>
<receiver android:name=".helper.BootReceiver"
        android:exported="true"
        android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

你读过the documentation on AlarmManager.setRepeating了吗?

If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.

我怀疑这是你问题的根源。

如果是这样,解决方案就是确保将 triggerAtMillis 设置为将来的某个时间。可能通过一些 additional/different Calendar 调用是可行的。