Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions 4_Service_Component/eunchang/Service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

## Service

백그라운드에서 작업을 수행하는 애플리케이션 구성 요소이며, 다른 앱에 있더라도 계속하여 유지가 가능하다.
주로 백그라운드 상태에서 데이터를 요청하고 응답받거나, 앱의 상태를 관찰하거나, 음악 재생, 주기적으로 위치와같은 정보를 전송하는 것과 같이 백그라운드에서 오래 실행되는 작업을 수행하기 위해 사용된다.
Service는 ForegroundService, BackgroundService, BindService 3가지 유형으로 나뉜다.

ForegroundService는 사용자가 앱이 백그라운드에 있더라도 Service에 의해 작업이 실행되고 있음을 인지할 수 있다.
예를 들어 뮤직 플레이어 같은 앱이 있으며, 음악이 재생되는 동안 사용자는 뮤직 플레이어가 실행되고 있음을 상태바와 노티피케이션으로 알 수 있다.
Service로 실행된 노티피케이션은 서비스가 중지되기 전엔 사용자가 임의로 제거할 수 없다.

BackgroundService는 사용자에게 보이지 않은 작업을 수행하며, 해당 작업이 Service에 실행되고 있는지를 사용자는 알 수 없다.
Service는 백그라운드 작업을 실행하는 도중에 기기의 리소스를 사용할 수 있기 때문에 동시에 많은 Service 사용은 기기에 부담이 될 수 있고 사용자 경험에 부정적인 영향을 준다.
따라서 sdk 26버전 이상을 타겟팅하는 앱에서는 브로드캐스트 수신을 제한하거나 서비스를 중지시키는 등 BackgroundService 실행을 제한하고 있다.
ForegroundService가 아니고, IME, 배경화면 서비스, 알림 리스너, 음성 또는 텍스트 서비스가 아닌 앱은 BackgroundService로 간주하고 이를 제한한다.

BindService는 Activity 혹은 Fragment 등을 서비스에 바인딩하여 요청을 보내고 응답을 받을 수 있다.
제한을 하고 있긴 하지만 서비스는 기본적으로 종료하기 전까지는 백그라운드에서 무한정 실행시킬 수 있지만,
Service Bind는 바인드한 구성요소가 종료될때까지만 유지된고, 바인딩 되지 않은 서비와 약간 다른 생명주기를 가진다.

## Service 구현

서비스는 Activity와 마찬가지로 매니페스트에 선언을 해줘야 하고, 서비스를 시작하는데 필요한 권한 등을 매니페스트에서 정의해 줄 수 있으며 android:exported 속성으로 다른 앱에서 서비스를 사용하는 것을 제어할 수 있다.
서비스를 실행하기 위해서는 구현하고자하는 작업에 맞게 몇가지 콜백 함수들을 구현해줘야한다. Service를 구현할 때 주의사항이나 참고할 사항을 콜백 함수 중심으로 살펴보자면...

- onStartCommand()는 startService()를 호출하여 서비스를 시작하도록 요청할 때 호출받는데 해당 함수를 구현하면 서비스를 중단하는 것은 개발자의 몫이며, 바인딩을 제공할 경우 해당 함수는 구현하지 않아도 된다.
- onBind() 함수는 서비스를 바인딩 하여 사용할 때 구현해야하며 다른 구성요소와 데이터를 주고받을 때 사용된다. 바인딩을 제공하지 않으면 null을 반환한다.
- onCreate()는 서비스가 처음 생성되었을 때의 최초의 작업을 수행한다. 이미 서비스가 실행중일 때는 호출되지 않는다.
- onDestroy()는 서비스가 소멸될 때 호출되며 리소스를 정리하는 작업을 수행할 수 있다. 서비스의 종료는 stopSelf() 와 stopService() 함수를 호출시켜 종료시킬 수 있다.
- onBind() 함수만 구현된 서비스에서는 해당 서비스를 호출한 구성요소가 종료되면 바인딩이 해제되면서 서비스가 소멸되지만, onBind()와 onStartCommand()가 함께 구현되어 startService()로 시작된 서비스는 자동으로 종료되지 않는다. 서비스에서 stopSelf() 함수를 호출하거나 Activity 등에서 stopService()를 호출해주어야 한다.
- onTaskRemoved()는 Task에서 앱이 지워질 때 호출받으며, 앱을 종료될 때 서비스를 종료시키는 등의 작업을 수행할 수 있다. (앱의 종료 로직에 따라 해당 함수가 아닌 다른 부분에서 별도로 종료시켜줘야 할 수 있다.)
- sdk 26버전을 타겟팅하고 있다면, ForegroundService를 시작할때 Service를 시작하고 5초 이내에 startForeground() 함수를 호출하여야 한다.

# startForeground
현재 클럽라이브 앱에서 가장 많은 크래시 보고를 받고 있는 부분이 Service 관련된 부분이며, 이는 대부분 RemoteServiceException으로

>Context.startForegroundService() did not then call Service.startForeground()

라는 메세지를 주는 중.
당연히 코드로만 보면 startForeground()를 정상적을 호출중이다.
해당 크래시를 살펴볼 초창기엔 소켓에서 주는 데이터가 null이면 startForeground() 정상적으로 호출하지 않을 수도 있었지만,
이를 수정하여, onCreate()에서 아무런 조건없이 startForeground()를 호출하게끔 해봤지만 여전히 크래시는 계속 일어난다.
[서칭](https://issuetracker.google.com/issues/76112072) 해봤을 때 해당 내용을 안드로이드 버그라고 주장하는 사람도 있지만 확실하지는 않은 것 같고...
정상적으로 방송방에 입장하고 종료하는 것이 아닌 여러 경우를 두고 이것저것 좀 더 하드한 테스트가 필요할 것 같다