有时使用 AlarmManager 无法触发警报

问题描述 投票:0回答:2

我有一个提醒应用程序,可以通知用户执行特定任务。一切都按预期工作,但有时警报不会被触发。近 100 位用户报告了此问题。我怀疑当设备处于睡眠模式时,警报不会被触发。我面对这个问题已经快一年了,但还没有找到任何解决方案。

这就是闹钟的安排方式:

public void schedule(Context context, long nextTrigger, Intent intent) {
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQ_CODE_ALARM, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    int ALARM_TYPE = AlarmManager.RTC_WAKEUP;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(ALARM_TYPE, nextTrigger, pendingIntent);
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        alarmManager.setExact(ALARM_TYPE, nextTrigger, pendingIntent);
    }
    else {
        alarmManager.set(ALARM_TYPE, nextTrigger, pendingIntent);
    }
}

这是来自待处理意图的广播接收器:

public class ReminderAlarm extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = null;
        if (pm != null) {
            wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, APP_NAME);
            if (wl != null)
                wl.acquire(10000L);
        }

        Log.log("Reminder alarm received");

        ReminderJobIntentService.enqueueWork(context, ReminderJobIntentService.class, JOB_ID_REMINDER_ALARM, intent);

        if (wl != null)
            wl.release();
    }
}

这是从广播中排队的工作意向服务:

public class ReminderJobIntentService extends JobIntentService {

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        Log.log("Reminder job intent service");

        // Creates a notification on the UI
        Utils.createNotification();

        // Schedule the next task (alarm). Actually it's schedule(context, long, intent) but it calculates the next trigger. That's it
        Scheduler.getInstance().scheduleNext();
    }
}
  1. 我有日志表明警报已正确安排。当收到广播时(当警报被触发时)我也会记录这一点。当没有广播日志时,表示警报没有触发。
  2. 闹钟安排在
    Boot Complete
  3. 我曾多次尝试使用不同的 Android 设备和版本重现此问题,但无法重现。我什至尝试将设备放入
    Doze Mode
    Battery Unpluged
    中,但没有成功。警报被触发。我近 3 天没有碰设备,警报延迟了 4 分钟才触发(因为 Android 操作系统正在批量处理警报)。
  4. 当用户抱怨未收到提醒时,通常我会将其重定向到“设置 -> 电池 -> 忽略应用程序的电池优化”。但有时这并不能解决问题。

我注意到抱怨此问题的人正在使用三星设备:带有 Android 6、7 的 S6、S7、S8 型号。(也许是因为我的用户中有 45% 使用此类设备?)

您遇到过这个具体问题吗?我错过了什么吗?三星型号是否会在后台杀死应用程序?也许某些 3rd 方应用程序正在杀死这些应用程序?

android alarmmanager android-alarms
2个回答
0
投票

我在构建一个获取每日通知的应用程序时遇到了类似的问题。问题不在于代码,而在于 Android Kitkat 及以上版本中处理警报的方式。警报现已经过优化,可最大程度地减少唤醒和电池使用。因此它们可能会在不同的时间开火或者根本不开火。您可以在这里查看更多信息:

AlarmManager 无法正常工作


0
投票

最近我遇到了这个问题并按以下方式处理: 使用 setAlarmClock 而不是 setExactAndAllowWhileIdle !!!

    class AndroidAlarmScheduler(private val context: Context): AlarmScheduler {

    //ALARM MANAGER
    private val alarmManager = context.getSystemService(AlarmManager::class.java)

    //SCHEDULE THE ALARM
    override fun schedule(entity: MessageEntity) {
        //INTENT NEEDS TO SEND
        val intent = Intent(context, AlarmReceiver::class.java).apply {
            putExtra("EXTRA_MESSAGE", entity.message)
            putExtra("EXTRA_PHONE", entity.phone)
            putExtra("EXTRA_MESSAGE_ID", entity.id.toString())
        }
        //SETTING ALARM USING setAlarmClock
        //PENDING INTENT
        val pendingIntent = PendingIntent.getBroadcast(
            context,
            entity.id.hashCode(),
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
        //IN CASE THAT USER CLICKED ON ALARM ICON NOTIFICATION TO CANCEL THE ALARM
        val i2 = Intent(context, MainActivity::class.java)
        val pi2 = PendingIntent.getActivity(context, entity.id.hashCode(), i2, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
        val alarmClockInfo = AlarmClockInfo(entity.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000, pi2)

        alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
        Log.i("LOG:","${entity.id}")
    }

    //CANCELING THE SCHEDULED ALARM
    override fun cancel(entity: MessageEntity) {
        alarmManager.cancel(
            PendingIntent.getBroadcast(
                context,
                entity.id.hashCode(),
                Intent(context, AlarmReceiver::class.java),PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        )
        Log.e("LOG:","Alarm related to ${entity.id}-Canceled")
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.