(안드로이드) 스타트서비스와 바운드서비스 개요

*안드로이드 서비스 클래스는 애플리케이션이 백그라운드 작업을 시작시켜 수행할 수 있게 특별히 설계되었다. 작업을 빨리 수행하고 종료하는 브로드캐스트 수신자와 다르게, 서비스는 실행 시간이 길면서 사용자 인터페이스를 필요로하지 않는 작업을 수행하도록 설계되었다.


<스타트 서비스>

스타트 서비스는 다른 애플리케이션 컴포넌트(예를들어, 액티비티나 브로드캐스트 수신자)에 의해 론칭된다.
그리고 서비스가 중단되거나 리소스 해제를 위해 안드로이드 런타임 시스템에 의해 소멸될 때까지 백그라운드로 무한정 실행된다.
이 서비스는 자신을 시작시킨 애플리케이션이 더 이상 포그라운드에 있지 않아도 계속 실행된다. 심지어는 실제로 서비스를 시작시킨 컴포넌트가 소멸될 경우에도 계속 실행된다.

기본적으로 이 서비스는 자신이 론칭되었던 애플리케이션 프로세스와 동일한 메인 스레드에서 실행된다. 이것을 로컬서비스라고 한다.
따라서 CPU를 많이 사용하는 작업들은 그 서비스의 새로운 스레드에서 수행되도록 하는 것이 중요하다. 그리고 별도의 프로세스에서 서비스가 실행되는 것을 원격서비스라고하며,
이때는 매니페스트 파일에 구성 변경을 해야 한다.

매니페스트 파일의 설정으로 서비스가 특별히 private(론칭된 프로세스 전용)으로 구성되지 않는다면 그 서비스는 같은 안드로이드 장치의 다른 컴포넌트에 의해 시작될 수 있다.
이때는 한 액티비티가 다른 액티비티를 론칭하는 방법과 똑같이 인텐트 매커니즘을 사용하면 된다.

스타트 서비스는 startService()메소드를 호출하여 론칭하며, 시작되는 서비스를 식별하는 인텐트 객체를 인자로 전달한다. 스타트 서비스는 작업을 완료한 후 stopSelf()를 호출하여 자신을 중단시켜야 한다. 또한, stopService()메소드를 호출하면 실행 중인 서비스를 다른 컴포넌트에서 중단시킬 수 있다. 이때는 중단될 서비스아 일치하는 인텐트를 인자로 전달한다.


<인텐트 서비스>

IntentService클래스는 Service클래스의 서브 클래스이자 편의(convenience)클래스이다.
이 클래스는 백그라운드 작업을 처리하는 작업 스레드를 설정하고 비동기 방식으로 각 요청을 처리한다. 이 서비스는 큐에 담긴 모든요청을 처리하고 중단된다. 
IntentService클래스를 사용할 떄는 각 요청을 실행하는 onHandleIntent()메서드만 구현하면 된다.

각 요청을 동기식으로 처리할 필요가 없는 서비스라면 인텐트 서비스가 바람직하다.
그러나 동기화가 필요한 서비스는 Service클래스의 서브 클래스가 되어야 하며, CPU를 많이 사용하는 작업을 효율적으로 처리하기 위해 스레드를 우리가 직접 구현하고 관리해야 한다.

<바운드 서비스>

바운드서비스는 스타트 서비스와 유사하다. 단, 바운드서비스는 결과를 반환하며 자신을 론칭한 컴포넌트와의 상호작용도 허용한다는 것이 스타트서비스와 다르다.

예를들어, 오디오 재생을 하기 위해 액티비티에서 서비스를 시작시킬 수 있다. 그리고 그 액티비티는 재생 일시 중지나 다음 트랙으로 건너뛰기 등의 목적으로 사용자에게 제어를 제공하는 사용자 인터페이스를 포함할 가능성이 크다.
이와 유사하게, 오디오 재생 서비스에서는 현재 오디오 트랙이 끝났음을 나타내고 방금 재생을 시작한 다음 트랙의 상세정보를 제공하기 위해 호출 액티비티에게 정보를 전달해야 한다.

한 컴포넌트(여기서는 클라이언트)가 시작되어 bindService()메소드르 호출하면 바운드 서비스에 바인딩(binding,결속)된다. 그러면 동시에 여러 컴포넌트가 서비스에 바인딩할 수 있다. 클라이언트에서  바인딩된 서비스를 더 이상 필요로 하지 않을 때는 unbindService()메소드를 호출해야 한다. 마지막으로, 남은 바인딩 클라이언트가 서비스에서 바인딩을 해제하면 그 서비스는 안드로이드 런타임에 의해 종료된다. 바운드 서비스는 또한 startService()의 호출로 시작될 수도 있다는 것을 알아두자. 이 겨우 일단 서비스가 시작되면 컴포넌트들은 bindService()호출로 그 서비스에 바인딩할 수 있다. 이처럼 바운드 서비스가 startService()호출로 론칭되는 경우는 마지막 남은 클라이언트가 바인딩을 해제하더라도 서비스는 여전히 계속 실행된다.

바운드서비스는 onBind()메소드의 구현을 포함해야 한다. 서비스가 최초 생성될 때와 그 이후에 다른 클라이언트들이 그 서비스에 바인딩할 때 모두 onBind()메소드가 자동 호출된다.
이 메소드의 목적은 바인딩한 클라이언트들에게 IBinder타입으 객체를 반환하는 것이다.
이 객체는 서비스와 통시하기 위해 클라이언트가 필요로하는 정보를 포함한다.

클라이언트와 바운드 서비스 간의 통신은 구성형태에 따라 구현기법이 달라진다. 즉, 클라이언트와 서비스가 같은 프로세스에 있는지 아니면 다른 프로세스에 있는지, 그리고 서비스가 특정 클라이언트에게만 가능한지, 아니면 그렇지 않은지에 따라 달라진다.
로컬통신(같은 프로스세내의 통신)은 Binder클래스로부터 서브 클래스를 생성하고 onBind()메소드에서 그 서브 클래스의 인스턴스를 반환함으로써 서비스가 구현될 수 있다.
이와는 달리 서로다른 프로세스간의 통신은 Messenger아 Handler를 구현해야 한다.



*매니페스트 파일에 서비스 선언하기

서비스를 사용하려면 매니페스트에 서비스를 선언해야 한다. <service>요소를 기존의 <application>항목에 추가해야 한다.

예)
<application~
  />

 <service andorid:name=".MyService">
 </service>

</application>


-->기본적으로 서비스는 public으로 선언된다. 즉, 서비스가 있는 애플리케이션 패키지 외부의 컴포넌트들이 액세스할 수 있다는 의미다. 서비스를 private으로 만들려면 <service>요소 내부의 android:exported속성을 false로 선언해야 한다.

예)
<service android:name=".MyService"
  android:exported="false">
</service>


*기본적으로 서비스는 호출한 컴포넌트와 동일한 프로세스에서 실행된다. 따라서 서비스를 독립된 프로세스에서 실행하게 하려면 <service>요소에 android:process속성을 추가하면된다. 이때 프로세스 이름앞에 콜론(:)을 붙인다.

예)
<service android:name=".MyService"
  android:exported="false"
  android:process=":myprocess">
</service>

---->앞에 붙인 콜론은 새로운 프로세스가 로컬 애플리케이션 전용(private)이라는 것을 나타낸다. 만일 프로세스 이름이 콜론 대신 영문 소문자로 시작하면 그 프로세스는 자신이 속한 애플리케이션 외의 다른 컴포넌트에서 사용할 수 있다.



댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기