-
https://developer.android.com/guide/components/services?hl=ko
Service
스타트 서비스, 인텐트 서비스, 바운드 서비스, 백그라운드 서비스, 포어그라운드 서비스, 바인드 서비스
각 서비스는 목적에 따라 크게 다릅니다.
예를 들어,
스타트 서비스는 애플리케이션이 시작될 때 실행되고,
백그라운드 서비스는 사용자가 애플리케이션을 종료한 후에도 계속해서 실행됩니다.
포어그라운드 서비스는 사용자에게 직접적으로 보이는 작업을 수행하는 서비스이며,
인텐트 서비스는 다른 애플리케이션과 데이터를 주고받는데 사용됩니다.바운드 서비스와 바인드 서비스는 비슷해 보일 수 있지만,
바운드 서비스는 다른 애플리케이션과 상호작용하기 위해 사용되는 서비스이고,
바인드 서비스는 클라이언트와 서비스 간에 인터페이스를 제공하여 통신하는데 사용됩니다.- 포그라운드
- 사용자에게 보이는 작업을 수행하는 서비스입니다. 예를 들어, 음악 앱에서 음악을 재생하는 작업이 포그라운드 서비스로 실행됩니다. 포그라운드 서비스는 알림(Notification)을 표시하여 사용자에게 서비스 실행 상태를 보여줍니다.
- 포그라운드 서비스는 사용자에게 잘 보이는 몇몇 작업을 수행합니다. 포그라운드 서비스는 사용자가 앱과 상호작용하지 않을 때도 계속 실행됩니다.
- 백그라운드
- 사용자에게 직접 보이지 않는 작업을 수행하는 서비스입니다. 예를 들어, 어떤 앱에서 파일을 다운로드하는 작업이 백그라운드 서비스로 실행됩니다. 백그라운드 서비스는 시스템 제한에 따라 실행 제한이 있을 수 있습니다.
- 백그라운드 서비스는 사용자에게 직접 보이지 않는 작업을 수행합니다. 예컨대 어느 앱이 저장소를 압축하는 데 서비스를 사용했다면 이것은 대개 백그라운드 서비스입니다.
참고: 앱이 API 레벨 26 이상을 대상으로 한다면 앱이 포그라운드에 있지 않을 때 시스템에서 백그라운드 서비스 실행에 대한 제한을 적용합니다. 이와 같은 경우에서는 대부분 앱이 예약된 작업을 사용해야 합니다.
- 바인드
- 다른 구성 요소에서 bindService() 메서드를 사용하여 호출하며, 클라이언트-서버 인터페이스를 제공하여 구성 요소가 서비스와 상호작용합니다. 클라이언트가 연결되어 있는 한, 서비스가 실행됩니다.
- 애플리케이션 구성 요소가 bindService()를 호출하여 해당 서비스에 바인딩되면 서비스가 바인딩됩니다. 바인딩된 서비스는 클라이언트-서버 인터페이스를 제공하여 구성 요소가 서비스와 상호작용하게 하며, 결과를 받을 수도 있고 심지어 이와 같은 작업을 여러 프로세스에 걸쳐 프로세스 간 통신(IPC)으로 수행할 수도 있습니다. 바인딩된 서비스는 또 다른 애플리케이션 구성 요소가 이에 바인딩되어 있는 경우에만 실행됩니다. 여러 개의 구성 요소가 서비스에 한꺼번에 바인딩될 수 있지만, 이 모든 것에서 바인딩이 해제되면 해당 서비스는 소멸됩니다.
- 스타트 서비스 : startService() 메서드를 사용하여 호출하며, 한번 실행되면 서비스가 백그라운드에서 계속 실행됩니다. 다른 구성 요소에서 startService()를 호출하여 시작하고, stopService()를 호출하여 종료할 수 있습니다.
- 액티비티나 브로드캐스트 수신자에 의해서 시작된다.
- 서비스가 중단되거나 리소스 해제를 위해서 시스템에 의해 소멸될 때 까지 백그라운드로 무한정 실행된다.
- 자신을 시작시킨 앱이 더 이상 포그라운드에 있지 않아도 계속 실행된다 - 서비스를 시작시킨 컴포넌트가 소멸될 경우에도 계속 실행된다.
- 로컬 서비스 : 메인 스레드 에서 실행 - CPU를 많이 사용하는 작업
- 원격 서비스 : 별도의 프로세스에서 서비스가 실행 -> 메니페스트에 구성변경을 해야함
- 서비스가 private 으로 구성되지 않는다면 해당 서비스는 다른 안드로이드 장치의 다른 컴포넌트에 의해 시작될 수 있다.
- startService() 함수 호출로 시작되며 이때 인텐트 객체를 인자로 전달한다.
작업 완료 후에는 stopself()로 중단해야하고 stopService()를 호출하면 실행중인 서비스를 다른 컴포넌트에서 중단 시킬수 있다.
인텐트 서비스: startService() 메서드와 함께 인텐트(Intent) 객체를 전달하여 호출하며, 인텐트 객체는 서비스에 실행할 작업을 명시합니다. 한번 실행되면 서비스가 백그라운드에서 계속 실행됩니다. 다른 구성 요소에서 startService()를 호출하여 시작하고, stopService()를 호출하여 종료할 수 있습니다.- CPU를 많이 사용하는 작업은 서비스로 실행할 때에 새로운 스레드에서 수행되어야 한다. 이러한 서비스를
JobIntentService 클래스로 구현할 수 있다. - JobIntentService는 Service 클래스의 서브 클래스로, 백그라운드 작업을 처리하는 스레드를 설정하고 비동기 방식으로 이를 처리한다. 큐에 담긴 모든 서비스를 처리후 둥단된다.
사용시 onHandleWork()를 구현하여 각 요청을 실행한다. - 각 요청을 동기화 하여 처리할 필요가 없다면 사용하기에 적합하다.
- CPU를 많이 사용하는 작업은 서비스로 실행할 때에 새로운 스레드에서 수행되어야 한다. 이러한 서비스를
JobIntentService' is deprecated. Deprecated in Java -> WorkManager로 대체한다!!!
Android 12부터는 앱이 foreground에서 실행 중일 때만 앱이 background 작업을 실행할 수 있도록 변경되었습니다. 이전에는 JobIntentService를 사용하여 background에서 작업을 실행할 수 있었지만, 이제는 foreground에서 실행 중이지 않으면 제한됩니다. 이로 인해, Google은 WorkManager나 JobScheduler와 같은 더욱 최신의 API를 권장하고 있습니다.
따라서, JobIntentService를 대체하기 위해 WorkManager나 JobScheduler API를 사용하는 것이 좋습니다. 이들 API는 foreground에서 실행 중이지 않아도 background 작업을 실행할 수 있도록 하며, 시스템의 최적화와 관련하여 자원 사용을 최적화합니다.
- 바운드 서비스 : bindService() 메서드를 사용하여 호출하며, 다른 구성 요소에서 바인딩하여 서비스와 상호작용합니다. 클라이언트-서버 인터페이스를 제공하여 구성 요소가 서비스와 상호작용할 수 있습니다. 바인딩된 서비스는 라이프사이클이 더욱 복잡합니다. 클라이언트가 연결되어 있는 한, 서비스가 실행됩니다.
- 스타트 서비스와 비슷하나 결과를 반환하며, 프로세스간 통신을 구현하고 이를 통해서 부모 컴포넌트와 상호작용을 할수있다.
- 컴포넌트가 시작되어 bindService()를 호출하면 바운드 서비스에 컴포넌트가 바인딩 된다. 그리고 서비스를 더 이상 필요로 하지 않을때는 unbindService()로 바인딩을 해제하면 해당 서비스는 시스템에 의해 종료된다.
- onBind()의 구현이 필수적이며 이 함수는 서비스가 최초 생성될 때 그리고 이후에 다른 컴포넌트가 해당 서비스에 바인딩 할때 자동으로 호출된다.
Binder 타입의 객체를 반환하는데 해당 객체는 통신을 위한 정보를 포함한다. - 구성형태에 따라서 구현 방법이 달라진다.
로컬 통신의 경우 Binder로 부터 서브 클래스를 생성하고 onBind() 에서 해당 클래스의 인스턴스를 반환하여 서비스를 구현한다.
서로 다른 프로세스간의 통신의 경우 Messenger와 Handler를 통해 구현한다.
- 서비스 생명주기
- onCreate() : 서비스가 생성될때 호출된다. 제일 먼저 호출되며 이후에 onStartCommand()나 onBind()가 호출된다.
- onStarCommand() : startService() 함수가 호출되어 서비스를 시작할때 , 바운드 서비스의 경우 이 함수를 구현할 필요가 없다.
- onBind() : 컴포넌트가 bindService() 함수를 호출하여 서비스에 바인딩할 때 호출된다.
Binder 객체를 반환하며 해당 객체를 서비스와 클라이언트간의 통신에서 사용된다.
스타트 서비스의 경우 null을 반환한다.
- onUnbind() : 클라이언트가 서비스와의 연결을 해제할 때 호출되는 콜백 메서드입니다. 즉, 클라이언트가 unbindService() 메서드를 호출하면 이 메서드가 호출됩니다. 만약 모든 클라이언트와의 바인딩이 해제되면 이 메서드는 반환값으로 true를 반환해야 합니다. 만약 이 메서드가 true를 반환하면 시스템은 이후에 이 서비스의 onRebind() 메서드를 호출할 수 있습니다.
- onRebind() : 이전에 바인딩된 클라이언트가 다시 서비스와 바인딩할 때 호출되는 콜백 메서드입니다. 즉, bindService() 메서드를 호출하면 이전에 이미 바인딩되어 있었던 서비스와 다시 바인딩할 때 이 메서드가 호출됩니다.
- onDestroy() : 서비스가 소멸될때 호출된다.
- onHandleWork() : JobIntentService의 서브 클래스에만 적용되며 메인 스레드와 다른 별도의 스레드에서 실행된다.
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override fun onCreate() { // The service is being created } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return mStartMode } override fun onBind(intent: Intent): IBinder? { // A client is binding to the service with bindService() return mBinder } override fun onUnbind(intent: Intent): Boolean { // All clients have unbound with unbindService() return mAllowRebind } override fun onRebind(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override fun onDestroy() { // The service is no longer used and is being destroyed } }
- 서비스 재시작 옵션 : onStartCommand()에서는 정수값을 반환하는데, 각 값들은 서비스의 소멸시 이를 어떻게 처리하는지를 정희한다.
- START_NOT_STICKY : 처리 대기중인 인텐트가 없다면 서비스가 소멸될때 다시 시작시키지 않는다
- START_STICKY : 서비스 소멸이후에 다시 시작되도록 한다. 처리 대기중인 인텐트가 없다면 null 인텐트를 받는 onStartCommand()가 호출된다.
- START_REDELIVER_INTENT : 서비스 소멸 이후에 다시 현재의 인텐트를 onStartCommand()에 전송하여 다시 시작되어야 함을 알리고, 그 다음 처리 인텐트를 전달시킨다.
- 서비스 선언
<manifest ... > ... <application ... > //기본적으로 public으로 선언된다. 외부 컴포넌트가 액세스 가능! <service android:name=".ExampleService1" /> //private 하게 만드려면 exported를 false로 선언한다. <service android:name=".ExampleService2" android:exported="false"/> // JobIntentService를 사용하기 위해서는 BIND_JOB_SERVICE 권한을 요청한다. <service android:name=".ExampleService3" android:permission ="android.permission.BIND_JOB_SERVICE" /> //서비스를 독립된 프로세스에서 실행되게 하려면 process 속성을 준다. <service android:name=".ExampleService4" android:process=":myprocess" /> ... </application> </manifest>
'Android' 카테고리의 다른 글
StartActivityForResult (0) 2023.07.04 coroutine - 하나의 scope 안에서 collect를 하지 않는 이유 (0) 2023.03.30 Coroutine (0) 2023.03.24 context (0) 2023.03.24 Intent + broadcast (0) 2023.03.24 - 포그라운드