如何在特定时间向用户发送一次通知?

How to send a notification to the user once at a particular time?

用户应该会在特定的日期和时间收到通知,但通知会立即出现,而不是在需要时到达。如何确保通知在正确的时间到达,而不是立即到达?

class MyReceiver: BroadcastReceiver() {

    private var title = ""
    private var desc = ""

    override fun onReceive(context: Context?, intent: Intent?) {

                try {
                    intent?.let {
                        title = it.getStringExtra(Constants.EXTRA_NOTIFICATION_TITLE).toString()
                        desc = it.getStringExtra(Constants.EXTRA_NOTIFICATION_MESSAGE).toString()
                    }
                }
                catch (e: Exception) {
                    Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
                    e.printStackTrace()
                }

        context?.let {
            showNotification(it, title, desc)
        }
    }

    private fun showNotification(context: Context, title: String, message: String) {
        val name = "Notification"
        val desc = "A Description of the Channel"

        val notificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val builder: NotificationCompat.Builder

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationChannel =
                NotificationChannel(Constants.CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
            notificationChannel.description = desc
            notificationChannel.enableLights(true)
            notificationChannel.lightColor = Color.CYAN
            notificationChannel.enableVibration(true)
            notificationChannel.vibrationPattern = longArrayOf(1000, 1000, 1000, 1000, 1000)
            notificationManager.createNotificationChannel(notificationChannel)

            builder = NotificationCompat.Builder(context, Constants.CHANNEL_ID)
                .setChannelId(Constants.CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(message)
                .setSmallIcon(R.drawable.baseline_access_time_blue)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                .setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
                .setContentIntent(
                    PendingIntent.getActivity(
                    context,
                    0,
                    Intent(context, MainActivity::class.java),
                    PendingIntent.FLAG_UPDATE_CURRENT
                    ))

        } else {
            builder = NotificationCompat.Builder(context, Constants.CHANNEL_ID)
                .setChannelId(Constants.CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(message)
                .setSmallIcon(R.drawable.baseline_access_time_blue)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                .setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
        }
        notificationManager.notify(Constants.NOTIFICATION_ID, builder.build())
    }
}

来电activity:

private fun sendNotification() {
        val intent = Intent(applicationContext, MyReceiver::class.java)
        val title = etTask.text.toString()
        val message = etTime.text.toString()
        intent.putExtra(Constants.EXTRA_NOTIFICATION_TITLE, title)
        intent.putExtra(Constants.EXTRA_NOTIFICATION_MESSAGE, message)

        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext,
            Constants.NOTIFICATION_ID,
            intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val time = getTime()
        alarmManager.setExactAndAllowWhileIdle(
            AlarmManager.RTC_WAKEUP,
            time,
            pendingIntent
        )
    }

清单:

<receiver android:name=".receiver.MyReceiver"
            android:enabled="true"/>

P.S。我不知道使用 AlarmManager 还是 WorkManager 来完成这个任务更好。

WorkManager 几乎是做任何与日程相关的事情的标准方法