[AlarmManager] 알람 매니저 사용법

2 분 소요

👩🏻‍💻 AlarmManager

우선 알람 매니저의 특징을 살펴보자!

  1. 지정된 시간에 또는 정해진 간격으로 인텐트를 실행한다.
  2. broadcast receiver와 함께 사용 -> 다른 작업을 실행할 수 있다.
  3. 애플리케이션 외부에서 작동하므로 앱이 실행 중이 아니거나 절전 모드일 떄도 이벤트를 사용하여 작업을 트리거할 수 있다.
  4. 타이머나 지속적으로 실행되는 서비스에 의존하지 않고 작업할 수 있다.

그렇다면 본격적으로 알람 매니저를 사용하는 방법에 대해 다뤄보고자 한다. 사용법이 비교적 매우 간단하다!

그 과정을 정리해보면 다음과 같다.

  1. 알람을 받을 broadcast receiver를 정의한다.
  2. 정의한 broadcast receiver를 등록한다.
  3. 각 알람에 대한 pendingIntent를 정의한다.
  4. alarmManager에 해당 pendingIntent를 전달한다.
  5. broadcast receiver에 의해 알람을 받는다.
  6. 정의된 후처리를 진행한다.

1. broadcast receiver 정의

class AlarmReceiver : BroadcastReceiver() {
    override fun onReceive(p0: Context?, p1: Intent?) {
        // broadcast를 받고 진행할 처리 작업 정의
    }
}


2. broadcast receiver 등록

broadcast receiver를 등록하는 방법은 크게 두 가지가 있다.

  1. manifest에 등록하는 방법 (정적 등록)
  2. activity에 등록하는 방법

각 방법의 차이점은 앱이 실행 중이냐에 따라 달라진다.

  1. manifest에 등록하는 방법
    • 앱이 실행 중이지 않을 때도 broadcast receiver가 동작한다.
  2. activity에 등록하는 방법
    • 등록한 activity의 lifecycle를 따르게 된다.
    • 단, 등록한 broadcast를 제거해줘야 메모리 낭비가 되지 않는다.
        // manifest를 이용한 등록의 경우
        <receiver
            android:name=".common_ui.receiver.AlarmReceiver"
            android:enabled="true" />
  • 여기서 enabledfalse으로 설정하면 앱 외부 소스의 브로드캐스트를 수신하지 않는다.


3. 알림에 대한 pendingIntent 정의 및 alarmManager에게 전달

    fun setPreorderAlarm() {
        // 알람 매니저 가져오기
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        // 현재 시간 이후인 지 확인 후 알람 등록
        val currentTime = Calendar.getInstance().time.getUTCDateTime()
        val alarmTime = Formatter.getDateFromString(preorderDate)
        if (alarmTime.after(currentTime)) {
            val alarmIntent = Intent(context, AlarmReceiver::class.java)
            // intent를 활용해 원하는 값 넘김
            alarmIntent.putExtra("preorderDate", preorderDate)
            alarmIntent.putExtra("phoneNumber", phoneNumber)
            alarmIntent.putExtra("totalOrderCount", totalOrderCount)
            // broadcast를 수행할 pendingIntent 선언
            val pendingIntent = PendingIntent.getBroadcast(
                context,
                UUID.randomUUID().variant(), // unique한 아이디 생성
                alarmIntent,
                PendingIntent.FLAG_IMMUTABLE
            )
          
            // alarmManager에 알람 등록
            alarmManager.setExact(
                AlarmManager.RTC, // 밑 알람 유형 참고
                alarmTime.time - TimeUnit.MINUTES.toMillis(10), // 해당 시간 10분 전
                pendingIntent
            )
        }
    }


+ 등록된 알람 취소하기

구글링을 해본 결과, alarmManager에 등록된 전체 알람을 가져올 방법은 없다. 따라서 등록된 알람을 취소하고자 한다면 등록할 때 만든 것과 동일한 pendingIntent를 만들어 하나하나 취소해야 한다.</span>

필자의 경우에는 등록한 alarmList를 가지고 있다가 취소하는 데 사용했다.

    fun cancelAllAlarm(context: Context) {
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        //필자는 해당 pendingIntent를 따로 변수에 저장해두었다 취소할 때 사용하였다.
        pendingIntentList.forEach {
            alarmManager.cancel(it)
        }
    }


👩🏻‍💻 알람 유형

  1. ELAPSED_REALTIME
    • 기기가 부팅된 후 경과한 시간에 대기 중인 인텐트 실행
    • 기기의 절전 모드 해제하지 않음
  2. ELAPSED_REALTIME_WAKEUP
    • ELAPSED_REALTIME과 동일
    • 기기의 절전 모드를 해제하고 대기 중인 인텐트 실행
  3. RTC
    • 지정된 시간에 대기 중인 인텐트 실행
    • 기기의 절전 모드 해제하지 않음
  4. RTC_WAKEUP
    • RTC와 동일
    • 기기의 절전 모드를 해제하고 대기 중인 인텐트 실행


👩🏻‍💻 broadcast receiver 사용 시, 주의할 점

주의할 점은 broadcast receiver를 통해 알람을 받고 UI 작업을 할 수 없다는 것이다. 따라서, dialog를 띄우거나 할 수 없다.. 하지만 pendingIntent를 활용해 activity를 다이얼로그처럼 띄울 수 있다. 이 방법은 추후 별도 게시글을 통해 정리해보겠다.

  • broadcast를 사용한다면 다음 게시글을 통해 해당 사용 권장사항을 읽어보는 것이 좋을 것 같다!

👩🏻‍💻 참고

댓글남기기