首页 > 解决方案 > 如何使用 AlarmManager 在特定的未来一天在后台显示通知

问题描述

我正在显示一个 DatePicker 以使用户选择将来的日期,并且我想在所选日期的前一天通知用户。例如,如果用户选择日期 [Apr 26, 2020] 我想在 [Apr 25, 2020] 通知用户,即使应用程序没有运行。但是,就我而言,通知仅在应用程序运行时出现,但在应用程序未运行时通知不起作用。

这是我的主要活动

class MainActivity : AppCompatActivity() {
    private lateinit var dateFormat: SimpleDateFormat
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.US)

        edit_text_date.setOnClickListener {
            showDatePicker()
        }
        notify_switch.setOnCheckedChangeListener { buttonView, isChecked ->
            if (isChecked) {
                val deadlineDate = dateFormat.parse(edit_text_date.text.toString())!!
                val c = Calendar.getInstance()
                c.time = deadlineDate
                c.add(Calendar.DATE, -1)
                val pastDay = dateFormat.format(c.time)
                val calender = Calendar.getInstance()
                val currentDate = dateFormat.format(calender.time)
                if (currentDate == pastDay) {
                    val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
                    val intent = Intent(this, AlarmReceiver::class.java)
                    val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0)
                    alarmManager.set(
                        AlarmManager.RTC_WAKEUP,
                        c.timeInMillis,
                        pendingIntent
                    )
                }
            }
        }
    }

    private fun showDatePicker() {
        val c = Calendar.getInstance()
        DatePickerDialog(this,DatePickerDialog.OnDateSetListener { view, year, month, dayOfMonth ->
                val daySelected = Calendar.getInstance()
                daySelected.apply {
                    set(Calendar.YEAR, year)
                    set(Calendar.MONTH, month)
                    set(Calendar.DAY_OF_MONTH, dayOfMonth)
                }
                edit_text_date.setText(dateFormat.format(daySelected.time))
            },
            c.get(Calendar.YEAR),
            c.get(Calendar.MONTH),
            c.get(Calendar.DAY_OF_MONTH)
        ).show()
    }
}

这是 AlarmReceiver 类

class AlarmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        showNotification(context,"title","notification message")

    }
    private fun showNotification(context: Context,title:String,body:String){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val notificationChannel = NotificationChannel("CHANNEL_ID","My Channel",NotificationManager.IMPORTANCE_HIGH)
            val notificationManager = context.getSystemService(NotificationManager::class.java)!!
            notificationManager.createNotificationChannel(notificationChannel)
        }
        val notificationManagerCompat = NotificationManagerCompat.from(context)
        val notification = NotificationCompat.Builder(context,"CHANNEL_ID")
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentTitle(title)
            .setContentText(body)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .build()
        notificationManagerCompat.notify(0,notification)
    }
}

我还在清单中注册了接收者

标签: androidkotlinnotificationsalarmmanager

解决方案


为了更有效地安排任务,您应该使用新引入的 WorkManager 类。它处理所有 API 级别,您不必担心您的应用程序将使用的 Android 版本。

要在设定的所需时间调用您的函数,

OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(WorkerClass.class)
                                                        .setConstraints(constraints)
                                                        .setInitialDelay(delayToPass, TimeUnit.MILLISECONDS)
                                                        .build();
WorkManager.getInstance(getApplicationContext())
    .enqueueUniqueWork(oneTimeWorkRequest);

有关更多信息,请查看:https ://developer.android.com/reference/androidx/work/WorkManager

"WorkerClass" 是一个类,它将在

public Result doWork() // method

确保你也读过它。


推荐阅读