[Android] Service 정리

성승모·2026년 2월 22일

Android

목록 보기
9/10

크게 세 가지 유형

  • 포그라운드: 알림으로 알려야 하는 작업. kill될 확률이 적음
  • 백그라운드: 앱이 포그라운드에 있을 때만 제한적으로 가능. 알림이 없고 킬될 확률 높음
  • 바인드: activity 같은 컴포넌트에 종속되어 생명주기를 같이 함.

주의 사항

  • Service는 Main Thread에서 실행되니, 새로운 쓰레드 풀 또는 코루틴 스코프를 주어야한다.
  • maniest에서 exported = false로 해놓으면, 다른 앱 컴포넌트가 접근하는 걸 막을 수 있다.
  • 해당 앱이 포그라운드에 있지 않은 한, 백그라운드 서비스는 제한된다.
  • stopSelf는 startId 값을 받아 안전하게 종료되도록 할 수 있다. 예를 들어, stopSelf(1)을 호출했지만 현재 startId = 2인 경우 이를 무시한다.

서비스 상속 시

  • onStartCommand: startService 호출 시, 불리는 함수로 실행되어 백그라운드에서 작동하게 된다.
  • onBind: bindService 실행 시 호출되는 함수로, 서비스와 통신할 수 있도록 돕는 인터페이스인 IBinder를 반환한다. 만약, bind를 허락하고 싶지 않다면 null을 반환하도록 하면 된다.
  • onCraete: onStartCommand, onBind보다 먼저 실행되어 생성을 알리는 함수
  • onDestory: 서비스가 파괴될 때 호출되는 함수로, 리소스를 반환해줘야 한다.

startService vs bindService

: startService는 독립적인 서비스를 실행시키는 함수로, 이를 호출한 컴포넌트에 독립적으로 작동하며 stopSelf 또는 stopService로 종료시켜줘야 한다.
: 반면 bindService는 해당 컴포넌트에 묶여, 작동하므로 activity가 종료되면 같이 destory된다.

시스템이 킬하는 배경 및 이유 등

  • 기본적으로 리소스가 없다고 판단되면 킬할 수 있다.
  • 하지만, bind된 activity가 포그라운드, 즉 유저 포커스를 가지고 있다면 거의 킬 되지 않음 (단, 서비스가 포그라운드로 실행되어야 함.)
  • but, 시간이 지날수록 후순위로 밀리기 때문에 킬될 확률이 오른다. 추후에 리소스가 여유로워 진다면 onStartCommand에서 무엇을 반환했는지에 따라 restart 정책이 정해진다.
  • 따라서, restart 될 경우를 생각하여 Service 코드를 작성해야 한다.

onStartCommand 반환값 정리

  • START_STICKY: 프로세스에 의해 kill된 이후 재시작을 보장하는 상수 값. 만약, kill된 상황에서 다른 컴포넌트가 다시 서비스를 실행시키거나 시키지 않을 수 있다. 시키지 않은 경우, kill 상황에서 intent를 따로 보존하지 않기 때문에 null intent를 넣어 startServiec를 하기 때문에 if (intent == null)과 같은 방어 코드가 필요하다. 반면, 새롭게 다시 실행시키면 해당 intent를 사용하고, 작업 큐에 있던 re-start 서비스 작업은 없앤다.

  • START_STICKY_COMPATIBILITY: 위와 동일하게 작동하지만, 재시작을 보장하지 않는다.

  • START_NOT_STICKY: 명시적으로 intent가 있을 경우, 즉 startService, bindService 등을 호출한 경우에만 서비스를 실행시킬 수 있음. 즉, restart 자체는 되지 않고, 명시적으로 다시 start 또는 bind 시켜야 작동

  • START_REDELIVER_INTENT: START_STICKY와 같지만 restart 시 동일한 intent가 전달되어 재시작됨.

IBinder 이용하기

  • 먼저 clinet가 ServiceConnection 객체를 만들고, 이를 bindservice에 넘겨주면 IBinder를 사용할 수 있다.
  • bindService에 플래그도 넘겨줄 수 있음
    • BIND_AUTO_CREATE: 실행 중인 서비스가 없으면 생성 후 binder 제공
    • 0(플래그 없음): 서비스를 생성하지 않고 있을 경우만 binder 제공. 없다면 false

그 밖....(AI로 정리)
1. 프로세스 우선순위 제어

  • BIND_NOT_FOREGROUND: 클라이언트가 포그라운드에 있더라도, Service 프로세스를 포그라운드 수준으로 승격시키지 않습니다.
  • BIND_ABOVE_CLIENT: 시스템에게 "이 Service 프로세스가 나(클라이언트)보다 더 중요하다"고 명시적으로 알립니다.
  • BIND_WAIVE_PRIORITY: 클라이언트의 존재가 Service 프로세스의 우선순위에 어떠한 영향도 미치지 않게 합니다.
  1. 디버깅 목적
  • BIND_DEBUG_UNBIND: 클라이언트가 unbindService()를 호출하지 않고 종료될 경우, 시스템 로그캣에 바인딩 당시의 Call Stack Trace를 강제로 출력합니다.
  • 커스텀 binder 클래스 만들기
class LocalService : Service() {
    // Binder given to clients.
    private val binder = LocalBinder()

    // Random number generator.
    private val mGenerator = Random()

    /** Method for clients.  */
    val randomNumber: Int
        get() = mGenerator.nextInt(100)

    inner class LocalBinder : Binder() {
        // Return this instance of LocalService so clients can call public methods.
        fun getService(): LocalService = this@LocalService
    }

    override fun onBind(intent: Intent): IBinder {
        return binder
    }
}
profile
안녕하세요!

0개의 댓글