【问题标题】:AlarmManager with Notification in Android does not show any notificationsAndroid中带有通知的AlarmManager不显示任何通知
【发布时间】:2020-11-12 13:56:19
【问题描述】:

我尝试为我的应用程序创建每日通知。为了测试应用程序,我将通知的间隔设置为 15 分钟。不幸的是,没有显示通知。无论是在应用程序运行时还是关闭时。我试图用这些解决方案来激励自己:

https://stackoverflow.com/questions/33055129/how-to-show-a-notification-everyday-at-a-certain-time-even-when-the-app-is-close

https://developer.android.com/codelabs/android-training-alarm-manager#0

https://github.com/google-developer-training/android-fundamentals-apps-v2/tree/master/StandUp(上一个链接的存储库)

我将 uses-permissionsreceiver 添加到 ma​​nifest 文件

ma​​nifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ovu">

    <uses-permission android:name = "android.permission.VIBRATE" />
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
    <!-- Permission to start Alarm on device reboot -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
          ...
        </activity>

        <receiver android:name= ".DailyNotificationReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

该类扩展了 BroadcastReceiver 类并覆盖了 onReceive 方法。

DailyNotificationReceiver

class DailyNotificationReceiver : BroadcastReceiver() {
    companion object {

        // Notification ID.
        private const val NOTIFICATION_ID = 0

        // Notification channel ID.
        private const val PRIMARY_CHANNEL_ID = "primary_notification_channel"

    }
    private lateinit var mNotificationManager: NotificationManager
    private val notificationContent = "Please measure your temperature and cervical mucus"
    private val contentTitle = "Provide me your temperature and cervical mucus!"

    override fun onReceive(context: Context, intent: Intent) {
        mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Deliver the notification.
        deliverNotification(context);

    }

    private fun deliverNotification(context: Context) {
        val contentIntent = Intent(context, MainActivity::class.java)

        val contentPendingIntent = PendingIntent.getActivity(context, NOTIFICATION_ID, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
        // Build the notification
        val builder = NotificationCompat.Builder(context, PRIMARY_CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_dialog_alert)
                .setContentTitle(contentTitle)
                .setContentText(notificationContent)
                .setContentIntent(contentPendingIntent)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true)
                .setDefaults(NotificationCompat.DEFAULT_ALL)
        // Deliver the notification
        mNotificationManager.notify(NOTIFICATION_ID, builder.build())
    }


}

在这个活动中,AlarmManager 的实例应该设置每天重复。

活动通知

class ActivityNotification : AppCompatActivity() {

    companion object {
        // Notification ID.
        private const val NOTIFICATION_ID = 0

        // Notification channel ID.
        private const val PRIMARY_CHANNEL_ID = "primary_notification_channel"
    }

    private lateinit var mNotificationManager: NotificationManager

    private fun notifyUser(){

        val notifyIntent = Intent(this, DailyNotificationReceiver::class.java)

        val notifyPendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_ID, notifyIntent,
                PendingIntent.FLAG_UPDATE_CURRENT)

        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

        val repeatInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES

        val triggerTime = (SystemClock.elapsedRealtime()
                + repeatInterval)

        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                triggerTime, repeatInterval,
                notifyPendingIntent)

        // Create the notification channel.
        createNotificationChannel();

        Toast.makeText(this, "Alarm's set", Toast.LENGTH_LONG).show()
    }

    private fun createNotificationChannel() {

        // Create a notification manager object.
        mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

        // Notification channels are only available in OREO and higher.
        // So, add a check on SDK version.
        if (Build.VERSION.SDK_INT >=
                Build.VERSION_CODES.O) {

            // Create the NotificationChannel with all the parameters.
            val notificationChannel = NotificationChannel(PRIMARY_CHANNEL_ID,
                    "Stand up notification",
                    NotificationManager.IMPORTANCE_HIGH)
            notificationChannel.enableLights(true)
            notificationChannel.lightColor = Color.RED
            notificationChannel.enableVibration(true)
            notificationChannel.description = "Notifies every 15 minutes to " +
                    "stand up and walk"
            mNotificationManager.createNotificationChannel(notificationChannel)
        }
    }
     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_notification)
        editTextNotificationHour = findViewById(R.id.editTextChangedNotification)
        mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
    }

  fun changeNotificationHour(view: View){
        notifyUser()
        val intent = Intent(this, ProfileActivity::class.java)
        startActivity(intent)
        finish()
    }


如果你们能帮我找到解决方案,我会很高兴。

【问题讨论】:

    标签: android kotlin android-notifications alarmmanager


    【解决方案1】:

    首先,让我们在 Manifest 中启用我们的 BroadcastReceiver,将我们的代码更改为:

    <receiver 
      android:name= ".DailyNotificationReceiver"
      android:enabled="true"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
      </intent-filter>
    </receiver>
    

    其次,我有点不确定ActivityNotification 活动的目的。 创建一个像Alarms 这样的简单类就绰绰有余了。

    您可以从那里定义设置警报所需的所有方法。像这样的:

    class InternetDaysLeftAlarm @Inject constructor(
        @ApplicationContext val context: Context
    ) {
        /**
         * Function is used to schedule one-time Alarm that will trigger on specific time.
         *
         * @param hourOfDay -> parameter defines what o'clock should the alarm be triggered at. (24-hour)
         *      default value is:
         * @see INTERNET_DAYS_LEFT_ALARM_DEFAULT_TRIGGER_HOUR
         */
        fun scheduleAlarm(hourOfDay: Int = INTERNET_DAYS_LEFT_ALARM_DEFAULT_TRIGGER_HOUR) {
            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val intent = Intent(context, InternetDaysLeftReceiver::class.java)
            intent.action = INTENT_ACTION_INTERNET_DAYS_LEFT_ALARM
            val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
    
            val msUntilTriggerHour: Long = TimeUnit.MINUTES.toMillis(minutesUntilOClock(hourOfDay))
    
            // Calculating and adding jitter in order to ease load on server
            val jitter: Long = TimeUnit.MINUTES.toMillis(Random.nextInt(0, 420).toLong())
    
            val alarmTimeAtUTC: Long = System.currentTimeMillis() + msUntilTriggerHour + jitter
    
            // Enabling BootReceiver
            val bootReceiver = ComponentName(context, BootReceiver::class.java)
            context.packageManager.setComponentEnabledSetting(
                bootReceiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP
            )
    
            /**
             * Schedules the Alarm based on Android Version.
             *
             * As per AlarmManager documentation to guarantee Alarm execution at specified time we use following methods:
             *
             * @see AlarmManager.setExactAndAllowWhileIdle -> Android.M [API 23] and above.
             * @see AlarmManager.setAlarmClock -> Everything below Android M.
             */
    
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, pendingIntent)
            } else {
                alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(alarmTimeAtUTC, pendingIntent), pendingIntent)
            }
        }
    

    可以通过以下方式处理通知:

    • 创建一个单独的Notifications

    • 当您收到警报时,处理所有通知事项,例如创建频道并在 BroadcastReceiver 内发送它们。

    【讨论】:

    • 我省略了将此活动中的代码粘贴到我的问题中,以使其更具可读性。在此活动中,用户可以更改每日通知的时间。我刚刚按照您的建议将代码添加到清单文件和活动中。我在模拟器上运行该应用程序,令人惊讶的是它可以工作。我试图在我的手机(小米红米)上调试它,但它不起作用。我检查了应用程序的权限,并授予了通知权限。您可能知道是什么原因造成的吗?
    • 您是否使用我编写的方法安排了警报? (setExactAndAllowWhileIdle 和 setAlarmClock)?
    • 是的,我做到了。我也有 bootReceiver 的问题。它会抛出异常“在包中找不到组件”
    • 它只显示一次通知。
    • 引导接收器应该像任何其他广播接收器一样创建。我拥有的代码只是用于以编程方式启用它。您应该只收到一次。您需要做的就是从广播接收器重新安排时间。您不使用重复警报的原因是因为 Android 省电功能可能会延迟这些警报。如果您不关心确切的执行,那么您应该替换方法,否则只需在每次接收时重新安排它。我明天会考虑在小米上收到它,但是,在我的应用程序中,它适用于我测试的每台设备:小米、Moto 等......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多