Android AlarmManager-RTC_WAKEUP vs ELAPSED_REALTIME_WAKEUP


87

誰かがAlarmManager.RTC_WAKEUPとの違いを私に説明できますかAlarmManager.ELAPSED_REALTIME_WAKEUP?ドキュメントを読みましたが、どちらか一方を使用することの意味をまだよく理解していません。

コード例:

    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 
                     scheduledAlarmTime, 
                     pendingIntent);

    alarmManager.set(AlarmManager.RTC_WAKEUP, 
                     scheduledAlarmTime, 
                     pendingIntent);

2行のコードの実行はどのように異なりますか?これらの2行のコードはいつ相互に実行されますか?

私はあなたの助けに感謝します。

回答:


140

AlarmManager.ELAPSED_REALTIME_WAKEUP typeは、起動時からアラームをトリガーするために使用されます。

alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 600000, pendingIntent);

実際には、デバイスの起動から10分後にアラームが鳴ります

デバイスの起動時に実行を開始してデバイスの稼働時間を測定するタイマーがあります。これは、デバイスの稼働時間に応じてアラームをトリガーするタイプです。

一方、AlarmManager.RTC_WAKEUPは時計の時刻に応じてアラームをトリガーします。たとえば、次の場合:

long thirtySecondsFromNow = System.currentTimeMillis() + 30 * 1000;
alarmManager.set(AlarmManager.RTC_WAKEUP, thirtySecondsFromNow , pendingIntent);

一方、これは30秒後にアラームをトリガーします

AlarmManager.ELAPSED_REALTIME_WAKEUPタイプは、と比較してほとんど使用されませんAlarmManager.RTC_WAKEUP


1
私もそう思っていました。確認が必要でした。したがって、次のようなことをした場合:alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP、System.currentTimeMills()+ 30 * 1000、pendingIntent); 奇妙なことが起こるかもしれません(それが思ったように機能していないことに気付くまで私が持っていたものです。
CamilleSévigny

2
コードは次のSystem.currentTimeMillis()代わりに使用する必要があることに注意してくださいSystem.currentTimeMills():)
HasanAboShally 2013年

17
「AlarmManager.RTC_WAKEUPと比較して、AlarmManager.ELAPSED_REALTIME_WAKEUPタイプが使用されることはめったにありません。」これは憶測と悪いアドバイスです。ドキュメントによると: developer.android.com/training/scheduling/alarms.html "特定の間隔(たとえば、30分ごと)でアラームを鳴らす必要がある場合は、経過したリアルタイムタイプのいずれかを使用してください。一般的に、これがより良い選択です。」
Jared Kells 2014

1
@mborsukの答えの方が優れており、この答えを修正していますthirtySecondsFromNow。のように、経過時間にRTCを使用しないでください。
Micha F.

2
かなり良い説明:)!重要なコメントを追加したいと思います。Androidの公式ドキュメントに関して、「AlarmManager.ELAPSED_REALTIME_WAKEUP」を使用することは、サーバーにHTTPリクエストを送信するアプリケーションに関しては興味深いものになる可能性があり、生成する必要はありません。 Webサーバーにロードします。午後10時30分にウェブサーバーでGETを実行している数千のAndroidデバイスについて考えてみてください。デバイスの起動時間にわたって機能するため、「AlarmManager.ELAPSED_REALTIME_WAKEUP」はこれらの「数千」のデバイスにリクエストを送信させる可能性があります。同時に、負荷を回避します:)。
ivanleoncz 2016年

107

現在受け入れられ、賛成票を投じられている回答にもかかわらず、AlarmManager.ELAPSED_REALTIME *タイプとSystemClock.elapsedRealtime()は、アラームとタイミングに関してRTCクロックよりも常に信頼性があります。

ELAPSED_REALTIME_WAKEUPをAlarmManagerで使用すると、起動時から始まる単調なクロックに依存し、CPUが省電力モードの場合でも刻々と変化するため、汎用インターバルタイミングの推奨基準です。そう、

alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
                 + 60*1000, pendingIntent);

1分(60 * 1000ミリ秒)でPendingIntentを起動します。

一方、AlarmManager.RTC_WAKEUPは、エポックからのミリ秒単位の標準「壁」時間です。そう、

alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
                 + 60*10000, pendingIntent);

SystemClockのドキュメントに記載されているように、今から60秒後にアラームがトリガーされることもありますが、確実ではありません。

壁掛け時計はユーザーまたは電話ネットワークで設定できるため(setCurrentTimeMillis(long)を参照)、時刻が予期せず前後にジャンプする可能性があります。この時計は、カレンダーや目覚まし時計のアプリケーションなど、実際の日付と時刻との対応が重要な場合にのみ使用してください。間隔または経過時間の測定では、別のクロックを使用する必要があります。System.currentTimeMillis()を使用している場合は、ACTION_TIME_TICK、ACTION_TIME_CHANGED、およびACTION_TIMEZONE_CHANGEDインテントブロードキャストをリッスンして、時刻がいつ変更されるかを確認することを検討してください。

また、この質問は* _WAKEUPアラームのみを参照していましたが、ウェイクアップアラームと非ウェイクアップアラームが何を提供するかを確実に理解するために、AlarmManagerのドキュメントも参照してください。


あなたの反応は素晴らしいですが、私のアプリケーションでは、今から60秒だけでなく、実際の日付/時刻と一致するアラームを設定する必要がありました。その場合、RTC_WAKEUPが私にとって最良の解決策です。
カミーユ・セヴィニー

8
それは問題ありませんが、これは質問に対するより正確な回答であり、現在受け入れられている回答の内容を修正します。
mborsuk 2013年

この情報は+1ですが、がでelapsedRealtime()SystemClockなく下にあることに注意してくださいSystem。EDIT:...毎日投票制限は...達した
ホルヘ・フエンテス・ゴンサレス

これは、そこでの問題における最良の答えの1つです。私は高さ50mの干し草の山(別名「私のコードのバグ!」)で針を探していましたが、あなたの答えが私を針に直行させました!
AlxDroidDev 2016

17

ただのメモ。稼働時間のミリ秒の呼び出しを取得できます。

long uptimeMillis =  SystemClock.elapsedRealtime();

したがって、今から30秒後にアラームを発生させ、通常の時計の代わりに稼働時間の時計を使用する場合は、次のようにすることができます。

long thirtySecondsFromNow =  SystemClock.elapsedRealtime() + 30 * 1000;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, thirtySecondsFromNow, pendingIntent);

特定の日時ではなく経過時間を確認する場合は、稼働時間を使用することをお勧めします。これは、ユーザーが設定を使用して変更すると、ユーザーがデバイスに設定した現在の時刻が変更される可能性があるためです。


3
「経過時間を確認したいときはいつでも」それを使用することを指摘するための+1。完全に理にかなっています。
sulai 2012

繰り返しになりますが、私の理解では、デバイスがシャットダウンするなどの事態が発生しない限り、これは30秒後に確実に起動します。具体的には、RTC_WAKEUPを使用する際の問題は、理論的には15秒後、10月末近くの土曜日の午前1時のようになり、システムクロックが1時間戻る可能性があることだと思います(米国および少なくともヨーロッパ)なので、アラームは設定されてから1時間30秒後まで実際にはトリガーされません。
ヤニック2015年

2

私はこの問題を自分のプロジェクトでこのようにプログラムしました。以下のコードで私は使用しています

AlarmManager.ELAPSED_REALTIME_WAKEUP

特定の時間にアラームを設定します。変数 'intentName'は、このアラームを受信するためにintentFilterで使用されます。私はこのタイプの多くのアラームを発しているからです。すべてのアラームをキャンセルしたとき。キャンセルメソッドを使用します。下部に記載されています。

//アラームを保持し、必要に応じてキャンセルします

     public static ArrayList<String> alarmIntens = new ArrayList<String>();

//

    public static String setAlarm(int hour, int minutes, long repeatInterval,
        final Context c) {
    /*
     * to use elapsed realTime monotonic clock, and fire alarm at a specific time
     * we need to know the span between current time and the time of alarm.
     * then we can add this span to 'elapsedRealTime' to fire the alarm at that time
     * this way we can get alarms even when device is in sleep mood
    */
    Time nowTime = new Time();
    nowTime.setToNow();
    Time startTime = new Time(nowTime);
    startTime.hour = hour;
    startTime.minute = minutes;
    //get the span from current time to alarm time 'startTime'
    long spanToStart = TimeUtils.spanInMillis(nowTime, startTime);
    //
    intentName = "AlarmBroadcast_" + nowTime.toString();
    Intent intent = new Intent(intentName);
    alarmIntens.add(intentName);
    PendingIntent pi = PendingIntent.getBroadcast(c, alarms++, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    //
    AlarmManager am = (AlarmManager) c
            .getSystemService(Context.ALARM_SERVICE);
    //adding span to elapsedRealTime
    long elapsedRealTime = SystemClock.elapsedRealtime();
    Time t1 = new Time();
    t1.set(elapsedRealTime);
    t1.second=0;//cut inexact timings, seconds etc
    elapsedRealTime = t1.toMillis(true);

    if (!(repeatInterval == -1))
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                elapsedRealTime + spanToStart, repeatInterval, pi);
    else
        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, elapsedRealTime
                + spanToStart, pi);

ここで、スパン関数は次のとおりです。

 public static long spanInMillis(Time startTime, Time endTime) {
    long diff = endTime.toMillis(true) - startTime.toMillis(true);
    if (diff >= 0)
        return diff;
    else
        return AlarmManager.INTERVAL_DAY - Math.abs(diff);
}

アラームキャンセル機能はこちらです。

public static void cancel(Context c) {
    AlarmManager am = (AlarmManager) c
            .getSystemService(Context.ALARM_SERVICE);
    // cancel all alarms
    for (Iterator<String> iterator = alarmIntens.iterator(); iterator
            .hasNext();) {
        String intentName = (String) iterator.next();
        // cancel
        Intent intent = new Intent(intentName);
        PendingIntent pi = PendingIntent.getBroadcast(c, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        am.cancel(pi);
        //
        iterator.remove();
    }
}

1

使用するアラームを選択する際のいくつかの重要な注意事項:(賛成票をすでに読んだ人)

RTC_WAKEUP 死の谷-時間の変更:
ユーザが過去に手動で変更する時間を持っている場合、アラームがオフに行くことはありませんし、将来はそれならば、アラームが過ぎてすぐに消えてしまいますRTCのタイムスタンプ。
しない失敗する可能性があるため、このアラームを使用してクライアント側の検証/重要なジョブを実行。

WAKEUP 意味(上記のマシュマロと)
一般的には-あまりありません。そのため、または(Doze&Idle)にいるとき、idleまたは中にデバイスをウェイクアップしませんdozealarmManager.setExactAndAllowWhileIdlealarmManager.setAndAllowWhileIdle

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.