【问题标题】:Alarm manger & Broadcast receiver not triggered on long term警报管理器和广播接收器不会长期触发
【发布时间】:2022-03-24 01:27:37
【问题描述】:

我正在尝试在我的应用程序中构建提醒模块以如下方式工作,当用户在确切时间设置警报时它会触发通知。

但是,有两种情况会失败:

1- 当我将闹钟时间设置为下一个 2 小时及以上时

2- 如果我从任务管理器中删除了应用程序(完全关闭)

不会触发任何通知,但是当我第一次打开应用程序时,我会立即收到所有丢失的通知。

我正在使用闹钟管理器将闹钟设置如下:

            val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val pendingIntent = PendingIntent.getBroadcast(context, requestCode, myIntent, 0)
            when {
                            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
                                manager.setExactAndAllowWhileIdle(
                                    AlarmManager.RTC_WAKEUP,
                                    timeOnDayCalender.timeInMillis,
                                    pendingIntent
                                )
                            }
                            else -> {
                                manager.setExact(
                                    AlarmManager.RTC_WAKEUP,
                                    timeOnDayCalender.timeInMillis,
                                    pendingIntent
                                )
                            }
                        }

并在广播接收器中接收我的警报管理器,如下所示:

class AlarmBroadcast : BroadcastReceiver() {


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

        val newIntent = Intent(context, AlarmService::class.java)
        newIntent.type = intent?.type
        newIntent.action = intent?.action

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context?.startForegroundService(newIntent)
        } else {
            context?.startService(newIntent)
        }

    }

}

我的AlarmService 班级是:

class AlarmService : Service() {

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        // show foreground notification to let user there is action happening in background
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            showForegroundNotification()
        else
            startForeground(
                1,
                Notification()
            )

        handleAlarmRedirection(intent)
        stopSelf(startId) // to destroy service after work is done & remove the fixed notification.

        return START_STICKY
    }

    private fun showForegroundNotification() {
        val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel()
            } else {
                // If earlier version channel ID is not used
                // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
                ""
            }

        val notificationBuilder = NotificationCompat.Builder(this, channelId)
        val notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(NotificationCompat.PRIORITY_MIN)
            .setContentTitle("title")
            .setContentText("body")
            .setCategory(Notification.CATEGORY_SERVICE)
            .build()
        startForeground(101, notification)
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(): String {
        val chan = NotificationChannel(
            "my_service",
            "My Background Service",
            NotificationManager.IMPORTANCE_NONE
        )
        chan.lightColor = Color.BLUE
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return "my_service"
    }

    private fun handleAlarmRedirection(intent: Intent?) {
        // logic for pushing the notification is here
    }

    override fun onDestroy() {
        super.onDestroy()
        stopForeground(true)
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

}

我也添加了 manifest 的权限:

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

希望有人知道这个案子。

如果有人有好的教程或最佳实践建议,请告诉我,我的目标是 android 31。

【问题讨论】:

  • setExact 在打盹模式下不会触发尝试使用setExactAllowWhileIdle()
  • 好的,我会试试这个,但是,这是否与应用打开后调用广播有关?
  • 不!当我们需要在设备处于打盹/空闲模式时触发警报时,我们可以使用 setExactAllowWhileIdle() 在准确的时间触发警报。而 setExact 与下一个维护窗口的时间不同。
  • 好的,我知道了,我试试看,你
  • 好的!谢谢,我不知道。感谢您更新我的信息。

标签: android service broadcastreceiver alarmmanager


【解决方案1】:

对于那些还和我一样纠结的人,那是因为我的手机是小米的电池优化。

一旦允许应用在没有电池优化的情况下工作,它就可以正常工作。

但是,要求用户这样做是一种糟糕的用户体验,因此,如果我发现我会更新答案,我正在寻找更好的解决方案。

【讨论】:

  • 如果您禁用电池优化,您将无法在商店中发布它
  • 我重定向用户以禁用它而不是强迫他。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-31
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多