티스토리 뷰

반응형

앞서 설명한 Local Service 를 구현하는 방법중에 하나인 startService를 통해 구현하는 방법에 대해 설명하겠다.

 

특징

1. 특정 서비스를 백그라운드로 동작시키는 것에 목적을 둔 형태.

2. 발생시킨 곳에서는 중단시키는 것 이외에는 어떤 제어도 불가능하다.

3. 발생시키는 곳과 서비스는 독립적이여서 Activity가 종료되어도 동작한다.

 

 

 


Start Service의 생명주기

Start/Bound 인지에 따라서 생명주기에 차이가 있다.

 

Service가 실행되면 onCreate - onStartCommand 생명주기 함수가 호출되고, 종료될 땐 onDestroy 생명주기 함수가 호출된다.

 

결국 서비스가 동작중일땐 onStartCommand의 코드가 계속해서 동작하는 것이다.

 

 


구현

1. Service 클래스를 상속받은 Java 클래스를 만든다. 

    ( 당연히 AndroidManifest.xml에 Service 태그 등록해야한다. )

2. onBind, onCreate, onStartCommand, onDestroy Method들을 Overring한다.

3. Service의 동작과정은 onStartCommand에 작성한다. onBind는 bind Service에서 사용한다.

4. intent에 Service의 클래스 정보를 담은뒤에 startService(intent) / stopService(intent)

 

public class CountService extends Service {
	public void onCreate() {
    	super.onCreate();
    }
    public int onStartCommand(Intent intent, int flags, int startId) {
    	super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }
    public void onDestroy() {
    	super.onDestroy();
    }
    // onBind 함수는 Bound Service에서 사용하는 함수지만 여기서도 Overriding은 해줘야한다.
    public IBinder onBind(Intent arg0) {
    	return null;
    }
}

 

Service는 Component이기 때문에 반드시 AndroidManifest.xml에 Service에 대한 정보를 기록해야 한다.

<service android:name=".CountService">
	<intent-filter>
    	<action android:name="ch4njun_count">
    </intent-filter>
</service>

 

그렇다면 이렇게 생성한 Start Service는 어떻게 실행시키고 종료시키는지 살펴보자.

public void onClick(View v) {
	switch(v.getId()) {
    	case R.id.start_count_btn:
        	Intent serviceIntent = new Intent("ch4njun_count");
            startService(serviceIntent);
            break;
        case R.id.stop_count_btn:
        	Intent serviceIntent = new Intent("ch4njun_count");
            stopService(serviceIntent);
            break;
    }
}

 

이미 Service가 실행중일 때 startService가 다시한번 호출될 경우 onCreate는 생략되고 onStartCommnad 생명주기 함수가 한번 더 호출되게 된다.

 

 


onStartCommand의 반환값

Service가 실행되는 도중 시스템이 자원이 부족해서 강제로 Service를 종료시킬 수도 있다.

이 때 onStartCommand의 반환값이 START_STICKY 이면 자원이 확보되는대로 다시 Service를 동작시킨다.

그러나 START_NOT_STICKY를 반환한다면 사용자가 다시 Service를 실행시키지 않는한 실행되지 않는다.

 

여기서 LMK의 우선순위에 대해서 설명하는데 꼭 순서를 기억하자 (시험에 나온대요..ㅠㅠ)

 


Service의 종료

우리는 Service를 생성한 컴포넌트에서 stopService 함수를 호출해 해당 Service를 강제로 종료시킬 수 있다.

 

stopService를 사용하지 않고 Service를 종료시키는 방법도 당연히 존재한다. Service가 자기할일을 마치고 스스로 종료하게 하는 방법은 다음 함수를 사용하면 된다. ( stopSelf, stopSelfResult )

 

이렇게 스스로 종료될 수 있는 여지가 있기 때문에 Service의 생명을 영원히 보장할 수 없다.
메모리 부족시 시스템은 강제로 Service를 종료시킬 수 있다.

이러한 작업을 LMK(Low Memory Killer)가 담당한다.

 

 

두 가지 방법의 동작방식은 동일하지만 왠만하면 stopSelf Method를 사용하는 것을 권장한다.

참고로 둘다 적용되어있지 않으면, Service는 절대 onDestroy를 호출하지 않는다.

 

 

 

 


이미 해당 Service가 동작하면 추가 동작 막기

( 굉장히 유용하게 사용할 수 있을 것 같다. )

  → 동기화 문제의 역이용..? 같은 느낌이다.

 

private ExecutorService exec = Executors.newSingleThreadExecutor();
private boolean isRunning = false;

public int onStartCommand(Intent intent, int flags, int startId) {
	if(isRunning) {
    	return START_NOT_STICKY;
    }
    
    isRunning = true;
    exec.submit(new Runnable() {
    	// ....
        stopSelf();
    });
    return START_STICKY;
}

public void onDestroy() {
	isRunning = false;
}

 

간단하게 설명을 덧붙이자면 isRunning 변수가 true라면 해당 Service가 동작하는 것이고,

false라면 Service가 동작중이지 않은 것이다. ( 코드는 굉장히 단순한듯 ! )

 

 


(매우중요★★★)

다시한번 주의해야할 점은 Service도 Main Thread에 속해서 동작한다는 점이다.

그래서 반드시 ANR에 걸릴만한 작업은 Sub Thread를 통해서 동작시켜야 한다.

( Thread로 종료시킬 때, Service가 종료된다면 반드시 Thread도 interrupt() 로 종료해주고

null로 초기화 해줘야한다. 당연히 이러한 작업을 하는 위치는 onDestroy method이다. )

 

ANR에 걸리는 시간은 20초이다. (액티비티는 5초, 리시버는 10/60초)

 

위에서 말했던 방법으로 onDestory를 구성하는 코드를 살펴보자.

private Thread mCountThread = null;

public int onStartCommand(Intent intent, int flags, int startId) {
	super.onStartCommand(intent, flags, startId);
    
    if(mCountThread == null) {
    	mCountThread = new Thread("Count ThreaD") {
        	public void run() {
            	while(true) { ... }
            }
        }.start();
    }
    return START_STICKY;
}

public void onDestroy() {
	if(mCountThread != null) {
    	mCountThread.interrupt();
        mCountThread = null;
        mCurNum = 0;
    }
    
    super.onDestroy();
}

 

 

 

그리고 startService에는 같은 Service에대해

여러번 startService가 실행되면 동기화문제가 발생한다.

동기화문제에 대한 자세한 설명은 생략하겠다. 너가 생각하는 그거 맞음ㅇㅇ;

 

동기화 문제를 해결할 수 있는 방법에 대한 정보는 못찾았고...

대체할 만한 놈으로 다음 포스팅에서 등장할 IntentService가 있다!!

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함