선생님, 개발을 잘하고 싶어요.

[안드로이드] AlarmManager 기본 정의, 정리 본문

개발/android 개발

[안드로이드] AlarmManager 기본 정의, 정리

알고싶은 승민 2020. 12. 30. 22:51

안드로이드 백그라운드 가이드

https://developer.android.com/guide/background

백그라운드 작업 분류

  • 즉시 (Immediate)

    사용자와 상호작용 해야 하는가?

  • 지연 (Deferred)

    사용자와 상호작용 하지 않아도 되는가?

    정확한 시간에 작동하지 않아도 되는가?

  • 정시 (Exact)

    사용자와 상호작용 하지 않아도 되는가?

    정확한 시간에 작동해야 하는가?

적어도 공식 홈페이지에선 이렇게 정의한다.

백그라운드 작업 분류에 따른 해결

  • 즉시 (Immediate)

    앱의 스코프 내부에서만 유요한: 코틀린 코루틴, RxJava

    앱 외부 스코프에서도 유요한: WorkManager(with long running support)

    미디어나 스마트키 위젯에 유요한: Foreground Service

  • 지연 (Deferred)

    WorkManager

  • 정시 (Exact)

    AlarmManager

정확한 시간에 동작해야 하며 사용자와 상호작용 하지 않아도 되는 작업은 AlarmManager사용을 고려하자.

AlarmManager

어떤 특징이 있는가.

  • 주어진 시간이나 기간마다 Intent를 실행한다.
  • Broadcast Receiver와 조합해서 서비스를 시작하고 다른 작업을 시작할 수 있다.
  • 앱이 실행 중이 아닐 때도 작업을 트리거할 수 있다.
  • busy wait 없이 작업을 예약할 수 있다. → 앱 리소스 최적화에 도움이 된다.

※ 백그라운드 분류에도 말 했지만, 앱의 스코프 내부에서 유요한 경우 Timer, Thread, Handler가 더 유용하다.

알람 등록

알람 유형

  • ELAPSED_REALTIME

    시스템 부팅 시간 이후 (SystemClock.elapsedRealtime)을 기준으로

  • ELAPSED_REALTIME_WAKEUP

    ﹢기기의 절전 모드 해제

  • RTC

    UTC 시계 시간 (System.currentTimeMillis)를 기준으로

  • RTC_WAKEUP

    ﹢디바이스가 꺼져있을 때 깨우는 것 까지

알람 함수

  • set
    • API 19이후, inexact 하게 동작한다. 연기되고 시간이 지난 이후에 전달된다.
    • OS에서 전체 시스템 알람을 "batch"하는 정책을 사용한다.
      • device가 wake up 하는 것을 최소화하고 배터리 사용량을 최적화한다.
      • 실제 알람의 순서도 일치하지 않는다.
        • 정확한 순서가 필요하면, setWindow, setExact를 써라.
  • setExact
    • OS가 전달 시간 최적화하지 않는다.
    • 요청된 시간에서 가능한 한 가까운 시간내에 전달한다.
  • setAndAllowWhileIdle
    • doze 모드일 때도 실행되는 set → 배치 정책을 사용한다.
    • 실제로 doze 모드일 때 실행 되야하는 알람의 경우에만 다루자.
      • ex) 일정이 되었다는 알람이 오는 캘린더
    • doze 모드일 때 동작해야 하므로, 과도한 사용을 막았다.
      • 특정 앱의 빈도수 제한이 있다. (15분 정도?)
  • setExactAndAllowWhileIdle
    • setExact + setAndAllowWhileIdle

  • setIneactRepeating

    • 반복적으로 실행되는 알람을 예약한다.
    • 시스템에서 배치한다.
  • setRepeating

    • 반복적으로 실행되는 알람을 예약한다.

    • 알람이 지연되면 가능한 한 빨리 스킵된 알람이 전달된다.

      • 전달이 늦어져도 스케쥴은 정상적으로 동작한다.

      한 시간마다 repeating, 7:45부터 8:45까지 폰이 자고 있다면 (8시 발생 알람 스킵)

      8시 45분에 폰을 킬 때, 8시 발생 알람이 울리고

      다음 알람은 9시에 잡힌다. (9시 45분이 아님!)

      ⇒ 실제 발생 시간 기준 몇 시간 후 반복되는 알람을 하고 싶다면 일회성 알람을 사용해 자체 스케줄 할 것

    • API 19 이후, inexact 하게 동작한다. 연기되고 시간이 지난 이후에 전달된다.

  • setAlarmClock

    • AlarmClockInfo로 표현되는 시간에 알람을 예약한다.
    • 알람이 실행될 때, 디바이스를 깨우고, 사용자에게 알림을 주는 용도로 사용한다.
      • 화면을 키고, 소리를 재생하고, 진동을 울리고...

doze모드에 동작하는 기능은 주의해서 넣어야 한다.

doze 모드 제약사항

중간 결

  • 일반적인 알람은 set, setRepeating을 사용할 것
    • 배터리 효율은 OS의 배치 알고리즘에 의해 최적화됨
  • doze 모드에서도 동작하려면 setAndAllowWhileIdle, setExactAndAllowWhileIdle를 사용할 것
    • 배터리 효율을 위한 OS 배치 알고리즘은 동작됨
  • 알람 앱처럼 완벽하게 엄격한 알람이 필요한 경우는 setAlarmClock을 사용할 것

참고로 코드는...

알람이 버전마다 동작 방식이 다르기 때문에, AlarmManagerCompat를 제공한다.

AlarmManagerCompat.setAlarmClock

AlarmManagerCompat.setAndAllowWhileIdle

AlarmManagerCompat.setExact

AlarmManagerCompat.setExactAndAllowWhileIdle

알람 취소

  • cancel
    • Intent.filterEquals에 해당하는 알람이 취소된다.
      • Pending Intent 생성 시 등록한 RequestCode가 같아야 한다.
      • Action, Categories, Data, Mimetype, Package, Component가 같아야 한다.
        • Extras는 비교 대상이 아니다.

※ PendingIntent가 FLAG_ONE_SHOT으로 생성된 경우 취소할 수 없다.

기기가 다시 시작할 때

  • 기기를 종료하면 모든 알람이 취소된다.

  • 재부팅 시점에 알람을 다시 시작하도록 해야 한다.

    현재 시점보다 과거 시점에 알람을 트리거하도록 하면 알람을 등록하는 즉시 실행된다.

  • 따라서 Boot시점을 받아오는 Receiver를 작성해야 한다.

부트 시점 받아오는 Receiver 등록

  • Boot 시점을 받아오는 이벤트가 다르다.
<receiver
    android:name=".core.alarm.RebootReceiver"
    android:directBootAware="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
    </intent-filter>
</receiver>

 

참고자료

공식 문서

안드로이드 공식 알람 앱 DeskClock

반복 알람 예약

doze 모드 제약사항

PendingIntent 일치 스택 오버 플로우

기기가 켜지고 암호화된 저장소에 접근할 수 있는 순간

Comments