Nuke Olaf - Log Store

[Android] 안드로이드 - 서비스를 사용하는 방법에 대한 정리 본문

Android

[Android] 안드로이드 - 서비스를 사용하는 방법에 대한 정리

NukeOlaf 2019. 12. 3. 18:44

https://android-kr.tistory.com/9

서비스는 사용자 인터페이스 (UI) 가 없다. 즉, 사용자는 서비스와는 직접적으로 상호작용할 수 없다. 서비스는 백그라운드에서 시간이 오래 걸리는 작업들을 처리하는 컴포넌트이다. ( 안드로이드 앱의 구성요소를 컴포넌트라고 한다. 앱의 주요 구성요소를 4대컴포넌트라고 부르며, 액티비티, 브로드캐스트 리시버, 컨텐트 프로바이더, 서비스가 있다) 서비스는 다른 컴포넌트에서 실행할 수 있다. 사용자가 서비스가 시작된 앱에서 벗어나 다른 앱을 실행하더라도, 서비스는 백그라운드에서 실행하던 작업을 계속한다. 앱의 다른 컴포넌트들은 서비스와 상호작용할 수 있는데, 그러기 위해서는 bindService() 메소드를 호출하여 서비스를 바인드해야한다. 서비스를 이용해 프로세스간 통신(IPC)도 할 수 있다.

서비스를 이용해서 할 수 있는 일들에는

- 네트워크를 통한 데이터 전송 및 수신

- 음악 재생

- 파일 I/O

- 컨텐트 프로바이더와의 상호작용

등이 있다. 이러한 일들을 백그라운드에서 처리할 수 있다.

 

 < 서비스는 실행되는 방식에 따라 2가지 상태로 나뉘게 된다. >

1. Started : (액티비티와 같은) 앱 컴포넌트가 startService() 를 호출하면, 서비스는 started 상태가 된다. 서비스가 실행되면(started 되면) 그 서비스를 실행한 컴포넌트가 종료 즉, onDestroy() 되더라도 서비스가 할 일을 마치고 서비스 객체가 destroy() 될때까지 종료되지 않는다. 서비스는 다른 컴포넌트들과 독립적인 컴포넌트로서, 별도로 실행되는 컴포넌트이기 때문에 서비스를 실행한 컴포넌트에게 실행한 것에 대한 결과값을 리턴해주지 않는다. 서비스가 네트워크 상에서 파일을 다운로드 하거나 업로드 하는 경우, 작업이 끝나면 서비스는 스스로 종료되어야 한다.

2. Bound : 앱 컴포넌트가 bindService() 를 호출하면, 서비스는 bound 상태(bind 된 상태)가 된다. bound 된 서비스는 앱 컴포넌트들이 서비스와 상호작용( 서비스 객체에 접근하여 데이터를 가져오는 요청 및 응답, 프로세스간 통신(IPC))할 수 있도록 해주는 클라이언트-서버 인터페이스를 제공해 준다. 서비스는 서비스를 제외한 다른 앱 컴포넌트에 의해 바인드 된 경우에 bound 상태로 동작한다. 한번에 여러개의 컴포넌트가 서비스와 바인드될 수 있다. 바인드된 모든 컴포넌트가 unBind (bind 해제) 되어야 서비스도 종료된다.

서비스의 상태를 위와 같이 둘로 구분해서 설명하고 있기는 하지만, 서비스는 Start 상태이면서 Bound 상태가 될 수 있다. Started 상태에는 onStartCommand() 콜백 메서드가 호출되고, Bound 상태가 되는 경우 onBind() 콜백 메서드가 호출된다.

내 앱이 실행중인지 여부나, 서비스와 바인드 되어 있는지 여부와 상관없이 내 앱 및 다른 앱의 컴포넌트에서 인텐트를 사용하여 서비스를 실행할 수 있다. 이는 액티비티가 내 앱 및 다른 앱의 컴포넌트에서 인텐트를 통해 실행가능하다는 것과 비슷한 상황이다. 다른 앱에서 서비스를 실행/사용하지 못하게 매니페스트에서 선언할 수 있다.

서비스는 기본적으로 앱이 구동되는 프로세스의 메인쓰레드에서 실행된다. 즉, 별도의 프로세스나 쓰레드에서 실행되는 것이 아니다. 그래서 CPU 사용량이 많은 작업, mp3 재생이나 네트워킹같은 실행흐름을 막는 작업(blocking operation)을 수행해야할때는 서비스 내에서 별도의 쓰레드를 생성하여 서비스를 사용해야 한다. 그래야 앱의 메인 스레드가 사용자와 상호작용에 집중할 수 있다.

 

 < 일반적으로 서비스를 만들때 아래 2개의 클래스 중 하나를 상속받는다. >

1. Service : 가장 기본이 되는 추상클래스이다. 모든 서비스 클래스는 이 클래스를 상속받아야 한다. 서비스는 기본적으로 앱의 메인 쓰레드에서 실행되기 때문에 같은 프로세스에서 실행되는 액티비티의 퍼포먼스를 낮출 수 있다. 그래서 이 클래스를 상속받아 확장할때는, 쓰레드를 생성하여 서비스가 할일을 생성된 쓰레드 내에서 하도록 만드는 것이 중요하다.

2. IntentService : 이 클래스는 Service 클래스의 서브 클래스이다. 하나의 worker 쓰레드를 만들어서 요청들을 한번에 하나씩만 처리하도록 한다. 만약 여러개의 요청을 동시에 처리해야하는 상황이 아니라면, 이 클래스를 사용하는것이 권장된다. 이 클래스를 상속받아 확장할때는 onHandlerIntent() 만 구현하면 된다. 이 콜백 메서드는 worker 쓰레드에서 실행되기 때문에 매개변수로 인텐트를 받아서 그에 해당하는 요청을 처리하는 것만 구현해주면 된다. 

IntentService 는 아래와 같은 일을 한다.

1. worker 쓰레드를 만든 후, onStartCommand() 를 통해 전달받은 인텐트들을 (메인쓰레드가 아닌) worker 쓰레드에서 차근차근 실행한다.

2. 작업 큐를 만들어서 전달받은 인텐트들을 넣어놨다가 한번에 하나씩 onHandlerIntent() 에게 넘겨준다. 그래서 멀티쓰레드에 대한 고민을 하지 않아도 된다.

3. 모든 요청에 대한 처리가 끝나면 종료되도록 이미 구현되어 있다. 그래서 stopSelf() 를 호출할 필요가 없다.

4. onBind() 콜백 메서드는 기본적으로 null 을 리턴하도록 되어있다.

5. onStartCommand() 콜백 메서드는 기본적으로 전달받은 인텐트를 작업큐에 넣는 일을 한다.

 

 

Comments