현재 회사에서 진행하고 있는 프로젝트에서 안드로이드 어플리케이션은 특정 디바이스와 계속해서 블루투스 연결을 유지해야 한다. 그러다보니 Service와 Broadcast 같은 것들에 대해 알아보게 되었는데, Service 부분이 헷갈리는게 있어서 정리하려고 한다.



안드로이드의 서비스는 life cycle에 따라 종류가 두 가지로 나누어진다.




1. Started Service


startService 메소드를 사용하면 서비스가 생성되며, stopService 또는 stopSelf를 호출하지 않는 이상 서비스는 종료되지 않고 계속 작동한다.


이러한 형태는 백그라운드에서 계속 돌아가야 하는 음악 재생 어플리케이션 등에서 사용된다.


그리고 서비스의 life cycle에 따라 콜백 메소드들이 존재한다.


하나의 서비스가 생성될 때 onCreate가 단 한번만 호출된다.


예전에는 onStart를 사용하였지만 요즘은 onStartCommand 사용을 권장하고 있다. 서비스가 시작될 때 호출되는데, 만약 이미 startService를 했는데 추가로 startService를 하려고 하면 이 onStartCommand가 호출된다. bindService를 사용할 때는 호출되지 않는다.


그리고 이 메소드는 int형의 반환값을 가지는데, 리소스 부족 등의 이유로 시스템이 서비스를 강제종료 했을 떄, 어떻게 처리할지를 정하는 플래그이다. 


- START_STICKY : client에서 startService 사용 시 intent로 서비스를 전달하며, onStartCommand에서 intent를 인자로 받을 수 있다. 단, 기존의 전달되었던 intent 값은 넘어오지 않는다.


- START_NOT_STICKY : 시스템이 서비스를 죽여도 다시 살아나지 않는다.


- START_REDELIVER_INTENT : 기본적으로 START_STICKY 플래그와 비슷하며, 대신 기존에 전달했던 intent 값을 돌려준다.


서비스 생성 : startService(Intent service)

서비스 종료 : stopService() 또는 stopSelf()



2. Bound Service


bindService 메소드를 사용하면 서비스가 생성되며, unbindService를 사용하거나 기존에 bound 된 액티비티들이 모두 unbind 하면 종료된다.


명시적으로 메소드를 사용해야 종료되는 Started Service와는 달리, 생성한 서비스에 bound 된 액티비티가 존재하지 않는다면 서비스는 종료된다.


콜백 메소드로는 onBind, onRebind, onUnbind가 있다. onRebind 같은 경우, 이미 unbind 되었던 액티비티가 다시 서비스에 연결했을 때 호출된다. 내 프로젝트를 예로 들자면 사용자가 앱 화면을 벗어나 다른 작업을 할 때 unbind가 되는데, 현재 디바이스가 연결되어 있다는 것을 notification bar로 보여준다. 그리고 다시 화면으로 돌아와 rebind 되면 notification을 내린다.


Bound Service 또한 마찬가지로 서비스에 플래그를 전달할 수 있는데, bindService 메소드의 인자로 값을 설정한다. 흔히 사용하는 플래그로는 0과 BIND_AUTO_CREATE가 있다.


0을 플래그로 설정하면 startService로 서비스를 생성하기 이전까지는 서비스가 생성되지 않는다. 만약 기존에 서비스가 생성되어 있다면 정상적으로 bind 된다.


BIND_AUTO_CREATE는 시스템에 의해 강제로 종료되더라도 리소스가 충분해지면 리소스에서 다시 실행하도록 하며, onBind에서 이전에 전달받았던 Intent 값을 받을 수 있다. 즉 바인딩된 액티비티가 존재하는 한 서비스를 생성한다. 대신 onStartCommand는 startService를 사용할 때에만 호출된다.


서비스 생성 : bindService(Intent service, ServiceConnection conn, int flags)

서비스 종료 : unbindService() 또는 모든 액티비티 unbound



3. start와 bind 동시 사용


startService와 bindService를 동시에 사용하는 것 또한 가능하다. 


이 때 서비스의 life cycle은 Started Service를 따른다. 즉, 명시적으로 stopService 또는 stopSelf 메소드를 사용하지 않는 이상 서비스는 종료되지 않는다.(시스템이 종료하는 것은 제외하고...)


이에 대해서는 구글에 좋은 예제가 있다.



참고


[Android] 서비스(Service)의 기초


19. Service에 대해서 - Service의 생존(2)


[컴][안드로이드] service에 bind하기 - local service


android service startService() and bindService()


Use 0 or BIND_AUTO_CREATE for bindService's flag


Google Android developers Context#BIND_AUTO_CREATE

블로그 이미지

NCookie

,