Android AlarmManager-RTC_WAKEUP 대 ELAPSED_REALTIME_WAKEUP


87

누군가가 나에게 사이의 차이 설명 할 수 AlarmManager.RTC_WAKEUPAlarmManager.ELAPSED_REALTIME_WAKEUP? 나는 문서를 읽었지만 여전히 하나를 사용하는 것의 의미를 실제로 이해하지 못합니다.

예제 코드 :

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

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

두 줄의 코드가 얼마나 다르게 실행됩니까? 이 두 줄의 코드는 언제 서로 상대적으로 실행됩니까?

도와 주셔서 감사합니다.

답변:


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_WAKEUPtype은에 비해 거의 사용되지 않습니다 AlarmManager.RTC_WAKEUP.


1
그것이 내가 생각했던 거죠. 확인이 필요했습니다. 그래서 이렇게하면 : alarmManager.set (AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMills () + 30 * 1000, pendingIntent); 이상한 일이 일어날 수 있습니다 (내 생각대로 작동하지 않는다는 것을 알아 차릴 때까지 내가
가진

2
코드는 다음 System.currentTimeMillis()과 같아야합니다. System.currentTimeMills():)
HasanAboShally

17
"AlarmManager.ELAPSED_REALTIME_WAKEUP 유형은 AlarmManager.RTC_WAKEUP에 비해 거의 사용되지 않습니다." 이것은 추측이며 나쁜 조언입니다. 문서에 따르면 developer.android.com/training/scheduling/alarms.html "단순히 특정 간격 (예 : 30 분마다)으로 알람을 실행해야하는 경우 경과 된 실시간 유형 중 하나를 사용하십시오. 일반적으로 이것이 더 나은 선택입니다. "
자레드 켈스

1
@mborsuk의 대답이 더 낫고이 대답을 수정합니다. 경과 시간에 대해 RTC를 사용해서는 안됩니다 thirtySecondsFromNow.
Micha F.

2
꽤 좋은 설명 :)! 중요한 의견을 추가하고 싶습니다. Android의 공식 문서와 관련하여 "AlarmManager.ELAPSED_REALTIME_WAKEUP"를 사용하는 것은 서버에 HTTP 요청을 실행하는 응용 프로그램과 관련하여 흥미로운 일이 될 수 있으며 생성하고 싶지 않은 웹 서버에로드하십시오. 오후 10시 30 분에 웹 서버에서 GET을 수행하는 수천 개의 Android 기기를 생각해보세요. 기기의 부팅 시간 동안 작동하는 "AlarmManager.ELAPSED_REALTIME_WAKEUP"는 이러한 "수천 개의"기기에서 요청을 실행할 수 있습니다. 동시에 부하를 피하십시오 :).
ivanleoncz 2016

107

현재 승인되고 찬성 된 답변에도 불구하고 SystemClock.elapsedRealtime ()과 함께 AlarmManager.ELAPSED_REALTIME * 유형은 항상 알람 및 타이밍에 대한 RTC 시계보다 더 안정적이었습니다.

AlarmManager와 함께 ELAPSED_REALTIME_WAKEUP를 사용하면 부팅 시간부터 시작되는 단조로운 시계에 의존하고 " CPU가 절전 모드에있을 때도 계속 틱하므로 범용 간격 타이밍의 권장 기준입니다 ." 그래서,

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

PendingIntent가 1 분 (60 * 1000 밀리 초) 안에 실행됩니다.

반면에 AlarmManager.RTC_WAKEUP는 epoch 이후 표준 "월"시간 (밀리 초)입니다. 그래서,

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 Intent 브로드 캐스트를 수신하여 시간이 언제 변경되는지 확인하는 것이 좋습니다.

또한이 질문은 * _WAKEUP 경보 만 참조했지만 , wakeup과 non-wakeup 경보가 제공하는 내용을 이해할 수 있도록 AlarmManager 설명서 도 참조 하세요.


귀하의 응답은 훌륭하지만 제 애플리케이션에서는 지금부터 60 초가 아닌 실제 날짜 / 시간과 일치하는 알람을 설정해야했습니다. 이 경우 RTC_WAKEUP가 가장 좋은 솔루션입니다.
Camille Sévigny 2013 년

8
괜찮지 만 이것은 질문에 대한 더 정확한 대답이며 현재 받아 들여진 대답의 문제를 수정합니다.
mborsuk 2013 년

이 정보에 대해 +1하지만이 대신 elapsedRealtime()아래 SystemClockSystem있습니다. 편집 : ... 일일 투표 제한에 도달했습니다 ...
Jorge Fuentes González

이것은 그 문제에서 가장 좋은 답변 중 하나입니다. 나는 50m 높이의 건초 더미에서 바늘을 찾고 있었는데 (일명 "내 코드의 버그!"), 당신의 대답은 나를 곧바로 바늘로 이끌었습니다!
AlxDroidDev

17

메모입니다. 가동 시간 밀리 호출을 얻을 수 있습니다.

long uptimeMillis =  SystemClock.elapsedRealtime();

따라서 지금부터 30 초 후에 알람을 실행하고 일반 시계 대신 가동 시간 시계를 사용하려면 다음을 수행 할 수 있습니다.

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

특정 날짜 / 시간 대신 경과 된 시간을 확인하려면 가동 시간을 사용하는 것이 가장 좋습니다. 사용자가 설정을 통해 시간을 변경하면 장치에서 사용자가 설정 한 현재 시간이 변경 될 수 있기 때문입니다.


3
"경과 시간을 확인하고 싶을 때마다"사용을 지적하는 +1. 완벽하게 이해됩니다.
sulai

다시 강조하지만 내 이해는 장치가 종료되는 것과 같은 일이 발생하지 않는 한 지금부터 30 초 후에 확실히 실행된다는 것입니다. 구체적으로 RTC_WAKEUP 사용의 문제는 이론적으로 지금부터 15 초 후 10 월 말에 토요일 오전 1시와 같을 수 있고 시스템 시계가 1 시간 뒤로 돌아갈 수 있다는 것입니다 (미국과 최소한 유럽), 따라서 알람은 설정 후 1 시간 30 초까지 실제로 트리거되지 않습니다.
Yannick

2

이 문제를 내 프로젝트에서 이런 식으로 프로그래밍했습니다. 아래 코드에서 내가 사용하고 있습니다.

AlarmManager.ELAPSED_REALTIME_WAKEUP

특정 시간에 알람을 설정합니다. 이 알람을 수신하기 위해 인 텐트 필터에서 변수 'intentName'이 사용됩니다. 이런 유형의 알람을 많이 발동하고 있기 때문입니다. 모든 알람을 취소 할 때. 취소 방법을 사용합니다. 하단에 주어집니다.

// 알람을 보류하고 필요할 때 취소

     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 의미 (위의 산들과)
일반적으로 -별로. , 또는 ( 잠자기 및 유휴 )에 있을 때 idle또는 동안 장치를 깨우지 않습니다.dozealarmManager.setExactAndAllowWhileIdlealarmManager.setAndAllowWhileIdle

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.