도래울

[Android] AlarmManger - 알람매니저 : Receiver, Notification - 리시버, 알림, 노티피케이션 본문

개발/Android

[Android] AlarmManger - 알람매니저 : Receiver, Notification - 리시버, 알림, 노티피케이션

도래울 2016. 2. 5. 13:17



AlarmManager(알람매니저)를 사용하면 정해진 시간에 내가 원하는 어떤 동작을 수행하도록 할 수 있습니다.

기본적으로 알람매니저에서 Action을 취하는 방식은 2가지가 있습니다.
1. service 호출
2. broadcast receiver 호출

호출이라는 표현을 쓰기는 했지만, 어떤 action을 취함으로써 서비스나 리시버가 action 을 캐치해 내가 원하는 명령들을 실행하도록 하는 것이죠.




AlarmManager를 사용하기 위해 아래의 4가지를 알아보도록 하겠습니다.
1. Alarm의 생명주기
2. Alarm의 생성
3. Alarm의 반복
4. Alarm의 해제





 1. Alarm의 생명주기


Alarm은 어플리케이션과 별개의 생명주기를 가지기 때문에 어플리케이션이 죽어있는 상태이더라도 System에 등록해 놓으므로, Alarm은 죽지않습니다.
 
Alarm의 주기는 사용자가 지정할 수 있습니다.
 
기본적인 Alarm은 한번의 실행되고 나면 더 이상 존재하지 않지만,(set()메소드 사용)
반복기능(setRepeat()메소드)을 사용하면 어플리케이션 생명주기와 관계없이 존재할 수 있습니다.


이를 확인하기 위해 어플스토커, Advanced Task killer 등의 killer 어플 여러개를 사용해 어플리케이션을 종료시켜보았습니다.

위의 캡춰와 같이 어플리케이션이 종료되면 어플리케이션의 PID(프로세스 아이디)는 바뀌지만, 
지정된 시간(제가 지정한 시간은 1분)마다 Alarm이 작동을 합니다.

Alarm은 어플리케이션과 생명주기를 같이 하는 것이 아닌 OS와 생명주기를 같이 합니다.




 2. Alarm의 생성


알람의
 타입은 4가지가 있습니다.(AlarmManager static 변수 : int)

 

Don’t wake up Device

Wake up Device

RTC

RTC

RTC_WAKEUP

ELAPSED

ELAPSED_REALTIME

ELAPSED_REALTIME_WAKEUP

 


RTC : UTC표준시간을 기준으로 하는 명시적인 시간에 intent를 발생
 
RTC_WAKEUP : UTC 표준시간을 기준으로 하는 명시적인 시간에 intent를 발생, 장치를 깨움
 
ELAPSED_REALTIME : 부팅 후 시간을 기준으로 지정된 시간에 intent를 발생
 
ELAPSED_REALTIME_WAKEUP : 부팅 후 시간을 기준으로 지정된 시간에 intent를 발생, 장치를 깨움


아래는 receiver를 동작하게 하는 intent action을 발생시키는 코드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 알람을 등록한다.
 
 * @param context 컨텍스트
 */
public static void registerAlarm(Context context)
{
    Log.e(TAG, "registerAlarm");
      
    Intent intent = new Intent(context, NotificationReceiver.class);
    intent.setAction(NotificationReceiver.INNER_PUSH);
    PendingIntent sender 
          = PendingIntent.getBroadcast(context, mCrouteCode, intent, 0);
          
    AlarmManager manager 
          = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 
          
    long triggerTime = SystemClock.elapsedRealtime() + 1000*60;
    manager.set(AlarmManager.ELAPSED_REALTIME, triggerTime, sender);
}



위 코드는 receiver를 동작하게 하기 위해 PendingIntent의 인스턴스를 생성할 때, getBroadcast 라는 메소드를 사용하였습니다.

만약 service를 동작하게 하기 위한 PendingIntent의 인스턴스를 생성할 경우에는, getService 라는 메소드를 사용합니다.
마찬가지로 Intent의 인스턴스를 생성할때에 파라미터로 넘기는 클래스에도 Service를 상속받아 만들어둔 클래스를 넘기면 됩니다.

PendingIntent sender = PendingIntent.getBroadcast(context, mCrouteCode, intent, 0);
PendingIntent sender = PendingIntent.getService(context, mCrouteCode, intent, 0); 


위의 두 경우 모두 같은 파라미터들을 넘겨줍니다. 
순서대로 Context, int requestCode, Intent, int flag 를 넘겨줍니다.
이때 넘겨주는 파라미터 중 requestCode는 나중에 Alarm을 해제 할때 어떤 Alarm을 해제할지를 식별하는 코드가 됩니다.

set 메소드를 사용해 단발성 Alarm을 생성할 경우에는, 아래의 세가지를 파라미터로 넘겨주어야 합니다.

int Type, long triggerTime, long interval, PendingIntent operation
Alarm의 Type은 위의 2. Alarm의 생성의 표에서 확인할 수 있습니다.
long triggerTime은 알람의 발생시간(실행될 시간)을 의미합니다.
PendingIntent operation은 이 Alarm을 발생시켜서 무엇을 할지에 대한 부분을 정의하는 것입니다.

무엇을 할지(service를 호출할지, broadcast를 호출할지, 어떤 intent action을 취할지)에 대해서는,
프로그래머의 의도에 따라서, Intent와 PendingIntent를 생성할 때 정의할 수 있습니다.


 3. Alarm의 반복

위(2. Alarm의 생성)에서 보았듯이 알람을 생성하는 것은 생각보다 간단합니다.
일단 생성한 알람은 OS가 재부팅 되지 않는 한, 한번 실행되고 종료되도록 만들어진 Alarm이 아닌한은 어플리케이션의 생명주기와 상관없이 존재할 수 있습니다.

이번에는 일정시간(프로그래머가 설정해둔 일정시간)마다 반복되는 Alarm에 대해서 알아보도록 하겠습니다.

위에서도 잠시 언급했었지만, AlarmManager 인스턴스에서 set 메소드를 실행시키는 것은 단발성 Alarm을 생성하는 것이고, setRepeating 메소드를  실행시키는 것은 반복성 Alarm을 생성하는 것이라는걸 알 수 있습니다.


기본적인 코드는 2의 알람의 생성과 같고 

manager.set() 메소드가 manager.setRepeating() 메소드로 바뀐 것만 다릅니다.
또 이렇게 메소드를 바꾼 경우에는 기존보다 하나의 파라미터를 더 넘겨주어야 합니다.

1
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, time, 1000*60, sender);


setRepeating 메소드를 사용해 반복성 Alarm을 생성할 경우에는, 아래의 네가지를 파라미터로 넘겨주어야 합니다.

int Type, long triggerTime, long interval, PendingIntent operation
Alarm의 Type은 위의 2. Alarm의 생성의 표에서 확인할 수 있습니다.
long triggerTime은 알람의 최초 발생시간을 의미합니다.
long interval은 알람이 최초 발생한 후 얼마마다 알람을 반복해서 발생시킬지를 정의하는 시간입니다.
PendingIntent operation은 이 Alarm을 발생시켜서 무엇을 할지에 대한 부분을 정의하는 것입니다.

추가된 하나의 파라미터 long interval 만 잘 조절한다면 원하는 시간마다 알람을 발생시킬 수 있습니다.




 4. Alarm의 해제

사실상 Alarm의 해제를 보자면, 직접적으로 알람을 해제시킨다기 보다는,
OS에 등록된 Alarm에 의해서 동작할 Operation을 해제시킨다고 생각해도 될것 같습니다.
실제 알람을 해제시키는 코드를 보자면,

PendingIntent(여기서는 operation이라고 생각합니다.)를 만들때, 위의 알람 생성시에 넣었던 requestCode를 똑같이 넣어주고, manager.cancel() 메소드를 실행해 operation을 cancel 시켜 버립니다.

Intent의 인스턴스를 생성할 때, 위의 2. Alarm의 생성과 같이 클래스 지정이나 setAction에 대한 부분은 다시한번 확인해 봐야 하지만, 기본적으로는 requestCode를 통해 Alarm을 해제시킬수 있다고 보아집니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 알람을 해제한다. 
 
 * @param context 컨텍스트
 */
public static void unregisterAlarm(Context context)
{
    Log.e(TAG, "unregisterAlarm");
      
    Intent intent = new Intent();
    PendingIntent sender 
        = PendingIntent.getBroadcast(context, mCrouteCode, intent, 0); 
  
    AlarmManager manager = 
        (AlarmManager)context
            .getSystemService(Context.ALARM_SERVICE);
  
    manager.cancel(sender);
}








알람매니저가 유용한 이유는, Alarm이 한번 등록되면 어플리케이션의 생명주기와 관계없이 어플리케이션이 종료되어있는
경우에도 지정해놓은 operation에 대해 어김없이 실행할 수 있다는 것입니다.

이를 이용해 receiver, service와 결합해서 사용한다면, background에서  실행되어야 하는 작업들을 수월하게 처리할 수 있습니다.


Comments