AlarmManager with Notification in Android does not show any notifications

早过忘川 提交于 2021-01-29 19:03:05

问题


I try to create daily notification for my application. In order to test the application I set the interval for the notifications to 15 minutes. Unfortunately, no notification is shown. Neither when the application is running nor when it is closed. I tried to inspire myself with these solutions:

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 (repository for the previous link)

I added uses-permissions and receiver to the manifest file.

manifest.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>

This class extends BroadcastReceiver class and overrides onReceive method.

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())
    }


}

In this activity, instance of AlarmManager should set daily repeating.

ActivityNotification

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()
    }


I'd be really happy if you guys can help me to find the solution.


回答1:


Firstly, let's start by enabling our BroadcastReceiver in Manifest by changing our code to this:

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

Secondly, I am a bit unsure of the purpose of the ActivityNotification Activity. It would be more than enough to create a simple class like Alarms.

From there you can define all the methods you need to set up an alarm. Something like this:

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 can be handle by:

  • Creating a separate Notifications class

or

  • Handling all the notification things like creating channel and sending them inside BroadcastReceiver when you receive an Alarm.


来源:https://stackoverflow.com/questions/64805288/alarmmanager-with-notification-in-android-does-not-show-any-notifications

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!