제임스딘딘의
Tech & Life

개발자의 기록 노트/Android

[Android] 죽지않는 서비스 만들기

제임스-딘딘 2011. 6. 22. 17:07

안드로이드에서 죽지않는 서비스 만들기

안드로이드는 시스템의 메모리 상황에 따라 각 Process별로 OOM Score (Out Of Memory Score)를 부여하고, 이 값을 기준으로 메모리가 부족해지면 OOM Score가 높은 Process부터 선택적으로 동작중인 서비스를 죽이기도 한다. 또한 나중에 다시 살리기도 한다.

만약 앱 개발을 하면서 죽지않고 항상 떠서 동작하는 서비스를 구현해야 하는 요구사항이 있다면, 이런 일이 발생하는 것에 당황할 수 있다. 이러한 상황에 부딪히면 자신이 개발중인 서비스를 죽지 않도록 만들고자 방법을 찾아볼 텐데, 이런 경우를 위한 방법이 있다. 바로 알람서비스를 이용하여 서비스가 죽으면 다시 살리는 방법이다. 많은 경우 이런 방식을 이용하는 것으로 보인다.


예제 소스 코드

PersistentService가 죽지 않아야 할 서비스 이름이다. 

아래 예제를 보면 onCreate 메서드에서 기존 알람이 있으면 제거하고 onDestroy메서드에서 알람을 등록한다. 

알람은 일정시간이 지나면 PendingIntent를 날리는 알람이고, 이 인텐트를 받을 수 있는 BroadcastReceiver가 존재한다.

이 예제에서는 RestartService receiver가 해당 인텐트를 받아서, 이 때 종료된 PersistentService를 재시작 시키는 역할을 한다.


PersistentService.java
class PersistentService extends Service {

	onCreate(..) {
		unregisterRestartAlram(); //이미 등록된 알람이 있으면 제거
	}

	onDestroy(..) {
		registerRestartAlram(); // 서비스가 죽을때 알람을 등록
	}

	// support persistent of Service 
	void registerRestartAlarm() {
		Log.d(TAG, "registerRestartAlarm");
		Intent intent = new Intent(PersistentService.this, RestartService.class);
		intent.setAction(RestartService. ACTION_RESTART_PERSISTENTSERVICE);
		PendingIntent sender = PendingIntent.getBroadcast(PersistentService.this, 0, intent, 0);
		long firstTime = SystemClock.elapsedRealtime();
		firstTime += 10*1000; // 10초 후에 알람이벤트 발생
		AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
		am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 10*1000, sender);
	}

	void unregisterRestartAlarm() {
		Log.d(TAG, "unregisterRestartAlarm");
		Intent intent = new Intent(PersistentService.this, RestartService.class);
		intent.setAction(RestartService.ACTION_RESTART_PERSISTENTSERVICE);
		PendingIntent sender = PendingIntent.getBroadcast(PersistentService.this, 0, intent, 0);
		AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
		am.cancel(sender);
	}
}

RestartService.java
public class RestartService extends BroadcastReceiver {
	public static final String ACTION_RESTART_PERSISTENTSERVICE = "ACTION.Restart. PersistentService";

	@Override
	public void onReceive(Context context, Intent intent) {
		Log.d("RestartService", "RestartService called!@!@@@@@#$@$@#$@#$@#");
		if(intent.getAction().equals(ACTION_RESTART_PERSISTENTSERVICE)) {
			Intent i = new Intent(ctx, PushService.class);
			context.startService(i);
		}
	}
}

manifest.xml

<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name="RestartService" android:process=":remote"/>