AlarmManager 报警设置后随机消失

AlarmManager alarm disappears randomly after being set

为了快速总结问题,设置的闹钟在我设置时和第二天某个时间之间消失了。我的代码似乎都正常工作,警报已设置并在适当的时间关闭。在初始警报触发并完成后,它会自动设置为第二天。我可以用 adb shell 的 dumpsys 警报检查并查看它。

更新:我在下面添加了一些日志信息

[14/01/2017 20:57:41] Registering start alarm 1 with Alarm Manager event time: 14/01/2017 21:00:00
[14/01/2017 20:57:41] Registering stop alarm 1001 with Alarm Manager event time: 14/01/2017 21:01:00
[14/01/2017 21:00:00] Receiver has received INTENT_ACTION_ALARM_START and is launching the music player for task #1.
[14/01/2017 21:01:00] Receiver has received INTENT_ACTION_ALARM_STOP and is stopping the music player, and sending a restart request to the MusicService.
[14/01/2017 21:01:00] Restart requested on alarm 1, attempting to add new alarms for tomorrow.
[14/01/2017 21:01:00] Registering start alarm 1 with Alarm Manager event time: 15/01/2017 21:00:00
[14/01/2017 21:01:00] Registering stop alarm 1001 with Alarm Manager event time: 15/01/2017 21:01:00

Batch{43d23730 num=1 start=86684689 end=86684689}:

  RTC_WAKEUP #0: Alarm{438c1740 type 0 org.hudsoft.music}

    type=0 whenElapsed=86684689 when=+23h55m1s357ms window=0 repeatInterval=0 count=0

    operation=PendingIntent{43af9370: PendingIntentRecord{43ddd9a8 org.hudsoft.music broadcastIntent}}

Batch{43d1e348 num=1 start=86744688 end=86744688}:

  RTC_WAKEUP #0: Alarm{438c10d8 type 0 org.hudsoft.music}

    type=0 whenElapsed=86744688 when=+23h56m1s357ms window=0 repeatInterval=0 count=0

    operation=PendingIntent{438ea450: PendingIntentRecord{4393a970 org.hudsoft.music broadcastIntent}}

当我上床睡觉并醒来并在第二天检查时,adb shell dumpsys 输出中奇怪地丢失了警报,它也从不执行。 我的问题是在没有任何用户交互的情况下警报会去哪里?我怎样才能设置一个持续的闹钟?该文档声称 "The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running"

我目前的设计是,当应用程序打开或接收器接收到 BOOT 事件时,我 运行 一个设置我所有警报并消失的 IntentService,假设警报管理器将处理 其余的部分。我的接收器应该等待响应,问题是每天晚上我睡觉时醒来,我的闹钟管理器 rtc 唤醒神秘地消失了。

如果您需要任何其他信息来帮助诊断问题,请告诉我这是我的第一个 post 我已经苦苦挣扎并寻找解决方案大约一个星期了!

在我的接收器中,这将触发以停止音乐播放服务并重新启动第二天的新闹钟:

 if (intent.getAction().equals("INTENT_ACTION_ALARM_END")) {
    Intent stopIntent = new Intent(context, MusicPlayer.class);
    Task thisTask = (Task) intent.getSerializableExtra("thisTask");
    stopIntent.putExtra("thisTask", thisTask);
    context.stopService(stopIntent);
    Intent restartAlarmIntent = new Intent(context, MusicService.class);
    restartAlarmIntent.setAction("INTENT_ACTION_ALARM_RESTART");
    restartAlarmIntent.putExtra("thisTask", thisTask);
    context.startService(restartAlarmIntent);
}

这是我用来构建和启动警报的代码

    Intent myIntent = new Intent(this, MusicReceiver.class);
    myIntent.setAction("INTENT_ACTION_ALARM_START");
    myIntent.putExtra("thisTask", task);
    Log.d("Intent", "Sending start intent now");
    PendingIntent pendingStartIntent = buildAlarmIntent(task, "INTENT_ACTION_ALARM_START");
    setSingleExactAlarm(endTime, pendingStartIntent);

    myIntent = new Intent(this, MusicReceiver.class);
    myIntent.setAction("INTENT_ACTION_ALARM_END");
    myIntent.putExtra("thisTask", task);
    Log.d("Intent", "Sending end intent now");
    PendingIntent pendingStopIntent = buildAlarmIntent(task, "INTENT_ACTION_ALARM_END");
    setSingleExactAlarm(endTime, pendingStopIntent);

public PendingIntent buildAlarmIntent (Task task, String action) {
    PendingIntent pendingIntent;
    Intent myIntent = new Intent(this, MusicReceiver.class);
    myIntent.setAction(action);
    myIntent.putExtra("thisTask", task);
    Integer idNum = task.getId();
    if (action.equals("INTENT_ACTION_ALARM_END")) {
        idNum += 1000;
        pendingIntent = PendingIntent.getBroadcast(this, idNum, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    } else {
        pendingIntent = PendingIntent.getBroadcast(this, idNum, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
    return pendingIntent;
}

private void setSingleExactAlarm(long time, PendingIntent pIntent) {
    AlarmManager mAlarmManager;
    mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    if (android.os.Build.VERSION.SDK_INT >= 19) {
        mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, pIntent);
    } else {
        mAlarmManager.set(AlarmManager.RTC_WAKEUP, time, pIntent);
    }
}

这是我的 AndroidManifest 的接收器部分

    <receiver
        android:name=".MusicReceiver"
        android:enabled="true"
        android:exported="true"
        android:process=":remote">
        <intent-filter>
            <action android:name="INTENT_ACTION_ALARM_START" />
            <action android:name="INTENT_ACTION_ALARM_END" />
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

提前感谢您抽出宝贵时间调查我的问题!

我没有足够的声誉来发表评论,因为我没有明确的答案。但是,您的 phone 是否有可能关机?根据 Android 文档:

https://developer.android.com/reference/android/app/AlarmManager.html

"Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted."

没有接收后的代码很难进一步诊断BOOT_COMPLETED。

以前我都是用下面的方法设置闹钟的,没有遇到你描述的问题:

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, MyBroadcastReceiver.class);
    PendingIntent pendingIntent  = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmStartTime.getTimeInMillis(), pendingIntent);

希望对您有所帮助,祝您好运。

我发现了我的问题,我想我会 post 以防其他人遇到类似问题。我的闹钟会按照我之前设置的时间重新启动。由于时间已经过去,它们会立即分解并消失。这也导致了一个循环,它会尝试一次又一次地重新启动它,但我相信警报管理器意识到这是在事件发生后发生的,并停止将它们排队以防止无限循环重置过去有开始时间的警报。希望这对某人有所帮助!