Pages

September 26, 2013

[Android] 디바이스 시간 설정 변경 이벤트 캐치하기

디바이스의 시간 설정이 변경되었음을 나의 앱이 알아차리기 위해서는 시스템이 시간 관련 설정이 변경 되었을 때 Broadcast하는 Intent를 앱이 캐치하도록 하면된다.

여기서 시간 설정 변경이란 사용자가 디바이스의 시간을 수동으로 변경하는 경우나 시간 서버와 동기화로 인해 시간이 변경되는 경우를 의미하고 시간이 흐르는 이벤트는 별개의 것으로 다룬다.

사용자가 시간을 변경하는 경우


사용자가 설정 메뉴을 이용하여 수동으로 시간을 바꾸는 경우 발생하는 이벤트이다. 이 경우 관심을 가져야 하는 Intent는 ACTION_TIME_CHANGED,  ACTION_TIMEZONE_CHANGED로 다음과 같이 Broadcast Receive에 Intent filter를 적용하고 이벤트를 캐치하도록 한다.

  1. ACTION_TIME_CHANGED : 시간, 날짜 변경에 관계 없이 어느 하나라도 변경하는 경우 발생한다. 실제로 디바이스상에서 시간값을 변경하면 이 Intent가 2번 브로드캐스트 되는데 안드로이드 OS의 버그로 보인다. 시간 변경창을 띄우고 시간을 바꾸지 않더라도 뒤로가기 버튼을 누르면 창이 닫히면서 1번 브로드캐스트된다. 명백한 버그로 보인다.
  2. ACTION_TIMEZONE_CHANGED : 타임존 관련 세팅이 변경되면 발생한다. 차를 타고 시간 존이 변경되는 지역을 지나가면 이 이벤트가 발생하는지 안하는지는 테스트 해보지 않았으나 정상적으로 OS가 구현이 되었다면 발생해야 할 것 같지만 위에서 보듯이 안드로이드 OS도 버그가 많아서..어쩔지는 미지수이다. 


AndroidManifest.xml

    
        
        
        
        
    


DeviceEventReceiver.java
public class DeviceEventReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (Intent.ACTION_TIME_CHANGED.equals(action)
            || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
                // 시간이 변경된 경우 해야 될 작업을 한다.
         doSomething();
        }
    }
}


시간이 흐름에 따라 시간이 변경되는 경우

이 경우 캐치해야 하는 Intent는 ACTION_TIME_TICK 혹은 ACTION_DATE_CHANGED이다.

  1. ACTION_TIME_TICK : 매 분마다 이벤트가 발생한다. 이 이벤트는 AndroidManifest에 Intent filter를 적용하는 것으로 캐치할 수 없고 코드내에서 동적으로 등록을 해야한다. 아마도 실수로 이 이벤트에 대한 로직을 추가하여 디바이스 배터리 광탈을 막기위한 목적이 아닌가 한다.
  2. ACTION_DATE_CHANGED : 이 이벤트는 날짜가 변경 될 때 발생한다. 다시 설명하면 어느 날의 11:59  PM에서 자정으로 넘어가 날짜가 변경되는 경우 브로드캐스트 되는 Intent이다. 

각 경우의 예제 코드는 다음과 같다.

ACTION_TIME_TICK 이벤트

SomeActivity.java
private static BroadcastReceiver _tickReceiver;

@Override
public void onCreate() {
    super.onCreate();
    
 _tickReceiver = new BroadcastReceiver() {
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();

         if (action.equals(Intent.ACTION_TIME_TICK)) {
             doSomeTask();
         }
     }
    };

    IntentFilter _intentFilter = new IntentFilter();
 _intentFilter.addAction(Intent.ACTION_TIME_TICK);

    registerReceiver(tickReceiver, _intentFilter);
}

@Override
public void onStop() {
 super.onStop();
 
 //unregister broadcast receiver.
 if (_tickReceiver != null)
  unregisterReceiver(_tickReceiver);
}
ACTION_DATE_CHANGED 이벤트

AndroidManifest.xml

    
        
        
    


DeviceEventReceiver.java
public class DeviceEventReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (Intent.ACTION_DATE_CHANGED.equals(action)) {
                // 날짜가 변경된 경우 해야 될 작업을 한다.
         doSomething();
        }
    }
}


No comments:

Post a Comment