2013년 2월 13일 수요일

[Android] Automatic Running a Service after booting up

어떠한 background service가 사용자에 의해서 실행이 된 후에 폰이 재 부팅이 되는 일이 발생한다면, 사용자는 한번 실행 시켜둔 서비스가 부팅 후에도 자동으로 실행이 될 것으로 기대할 수 있다. 이런 경우, 폰의 부팅이 완료되고 난 시점에 사용자의 설정상태(폰 종료 전 서비스를 실행시켰었는지)를 확인하여 만약 그 상태가 on 이었다면 자동으로 서비스를 실행 시켜줘야 한다.

이를 위해선 크게 두가지를 해야한다.
1. 폰이 부팅이 된 시점을 알고, 그때에 일련의 작업을 처리할 수 있어야 한다.
2. 사용자의 서비스 실행 여부를 알 수 있어야 한다.

첫째로, android 시스템은 폰 부팅이 완료되고 나면 android.intent.action.BOOT_COMPLETED intent를 broadcast 한다. 이 intent를 받을려면 manifest 파일에 receiver를 등록하고 해당 intent를 추가해야 한다. App 내에서 code로 broadcast receiver/intent를 등록할 수 없는 이유는 app이 실행되기 전에 해당 intent를 받을 수 있어야 하기 때문이다. (코드로 등록한다는 것은 사용자가 앱을 실행해서 해당 루틴이 수행이 되어야 한다는 것을 전재로 한다.)

BOOT_COMPLETED intent를 받는 receiver code는 아래와 같다. onReceiver 루틴에서 부팅이 끝난 후 필요한 일을 처리하면 된다.
public class BootStartupReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){
   // After booting up, this routine is called
   // If s service was on before turned off, let's start here again
   ...
  }
 }
}
BOOT_COMPLETED intent를 받기 위해 AndroidManifest.xml 파일에 아래와 같이 permission과 receiver를 등록한다.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

...


    
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    


이제 부팅이 끝나고 난 시점에 무언가를 처리할 수 있는 준비가 되었다. 그럼 두번째로 폰 종료 전 사용자의 서비스 실행여부에 대한 상태를 알 수 있어야 한다. 폰 재부팅 후에도 값을 유지하기 위해선 정보가 non-volatile 메모리, 즉 flash에 저장이 되어야 한다. Android에서는 이를 위해 크게 세가지 정도의 방법을 제공한다.
1. Preference
2. File System
3. SQLite DB
하지만, 여기서 저장해야 할 값은 boolean type의 간략한 정보이므로 preference를 이용하는게 적절하겠다.

사용자가 서비스를 on 할때, 아래와 같이 shared preference에 상태값을 저장한다.
public static final String PREF_FILE_NAME = "PrefFile";

// Read saved value
SharedPreferences preferences = getSharedPreferences(PREF_FILE_NAME, MODE_PRIVATE);
boolean serviceOn = preferences.getBoolean("serviceOn", false);
if(serviceOn){
 // Do something
}
폰 부팅 후, 저장된 상태값을 다시 읽어올 때는 아래와 같은 루틴을 사용하면 되겠다.
// Save setting
SharedPreferences preferences = getSharedPreferences(PREF_FILE_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("serviceOn", isChecked);
editor.commit();

요약하면, 사용자가 background service를 실행할 때 그 상태를 preference로 저장하고, 폰이 재 부팅후 부팅 완료가 되는 시점에 preference에 저장해 두었던 값을 다시 읽어와서 그 상태가 on이면 자동으로 background service를 실행한다.

추가로, 화면이 켜져 있는 동안 혹은 사용자가 lock 화면을 해제한 동안만 서비스가 동작하게 하고싶다면, 아래의 intent를 받아서 적절히 처리하면 되겠다.
1. Intent.ACTION_SCREEN_ON
2. Intent.ACTION_SCREEN_OFF
3. Intent.ACTION_USER_PRESENT : 사용자가 lock 화면 해제시 발생
SCREEN ON/OFF의 경우는 AndroidManifest.xml파일에 등록하는 방법은 없다. 코드상에서 등록을 해야지만 수신할 수 있다. 3번의 경우는 코드와 manifest에 등록하는 방법 두가지가 모두 존재하지만 1, 2, 3번 의 경우 모두 필요할 때 코드상에서 추가하도록 하는게 적절해 보인다.
(3번의 경우, manifest로 등록하기 위해선 android.intent.action.USER_PRESENT 사용해야 한다.)

댓글 없음:

댓글 쓰기