Everyday Growing Engineer 2022. 8. 1. 12:09

Android Service란 쉽게 말해서 백그라운드에서 동작하는 기능을 말하는 겁니다. 대표적인 예로는 카카오톡 앱을 실행하지 않고도 누군가 메세지를 보내면 받고 알려주는 것이 있습니다. 

import android.app.Service
import android.content.Intent
import android.os.IBinder

class BasicService : Service() {

    override fun onCreate() {
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
    }
    
    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }
}

onDestroy() : 서비스를 더 이상 사용하지 않고 소멸할 때 호출

onCreate() : 서비스가 처음 생성되었을 때 호출

onStartCommand() : 다른 구성 요소가 서비스를 시작하도록 요청하는 경우 호출

onBind() : 다른 구성 요소가 해당 서비스에 바인딩되고자 하는 경우에 이 메서드를 호출, 바인딩을 허용하지 않으려면 null을 반환 출처: 

 

서비스 vs 스레드 (Service, IntentService)

서비스는 그저 백그라운드에서 실행될 수 있는 구성 요소일 뿐입니다. 서비스를 사용하는 경우 기본적으로 애플리케이션의 Main Therad에서 계속 실행되므로 서비스가 해야할 작업이 많거나 중간에 Blocking 작업이 들어간다면 서비스 내에 새 스레드를 생성을 해야 합니다.

여기서 우리는 두 가지 클래스를 통해 서비스를 구현할 수 있습니다.

 

Service

기본적인 서비스 클래스, 서비스는 기본적으로 Main Thread를 사용하기 때문에 성능을 저하시킬 수 있으므로 새 스레드를 생성해주어야 한다.

 

IntentService

Service의 하위 클래스, Work Thread를 사용하여 모든 시작 요청을 한번에 하나씩 처리합니다. 만약 서비스가 여러 개의 요청을 동시에 처리하지 않아도 되는 경우 사용합니다.

 

 

출처: https://ardor-dev.tistory.com/83 [Ardor IT's Devlog:티스토리]

 

쓰레드 서비스
백그라운드 프로세스를 수행할 수 있는 OS 수준의 기능 대부분 UI 없이 백그라운드에서 오래 실행되는 작업
자체 쓰레드에서 실행됨 메인 쓰레드에서 실행됨
쓰레드는 경량 프로세스고 안드로이드 컴포넌트가 아니다.
UI 쓰레드를 업데이트할 수 없고 이를 위한 핸들러가 필요함
서비스는 안드로이드 컴포넌트고, 액티비티지만 인터페이스가 없다
액티비티 생명주기에서 실행되며 액티비티가 파괴되면 종료 / 중지된다 서비스는 백그라운드에서 실행되며 액티비티 생명주기와 독립적인 자체 생명주기를 갖는다
따라서 액티비티가 파괴될 때 서비스가 명시적으로 중지되지 않는 한 서비스는 계속 실행된다

 

Service 생명주기

onStartCommand 와 onBind 로 나뉘게 된다.

onCreate()

  • 서비스가 생성될 때 최초로 호출됨, 초기 설정을 수행

onStartCommand()

  • startService() 로 Service가 시작될 때 호출됨. startService()를 통해 전달한 Intent를 onStartCommand() 에서 서비스가 수신하게 된다.
  • 서비스는 작업이 완료되면 stopSelf()를 호출하여 스스로 중단하거나 다른 컴포넌트가 stopService() 를 호출하여 중단시킬 수 있다. (콜백 없음)
    • onStartCommand()호출을 한 번이라도 받은 서비스는 lifecycle을 직접 관리 및 중단해야 한다. (이후 onBindCommand()가 호출 되었더라도)
      • 시스템이 서비스를 중단하거나 소멸시키지 않음

onBind()

  • bindService() 로 클라이언트가 Service에 binding될 때 호출됨.

onUnbind()

  • 모든 클라이언트들이 unbindService()를 호출해서 binding이 해지되었을 때 호출 됨.

onRebind()

  • unbindService()가 호출된 이후에, 클라이언트가 bindService()를 호출하여 Service에 binding될 때 호출됨.

5. onDestory()

  • Service가 해지될 때 호출 됨. 리소스 해지를 수행

 

 

 

onStartCommand의 경우

- 액티비티 같은 앱 컴포넌트가 startService()를 호출하면, 서비스는 실행되면(started), 그 서비스를 실행한 컴포넌트가 종료되도 할 일을 모두 마칠 때까지 서비스는 종료되지 않는다. 

 

- 따라서 서비스가 할일을 다하여 종료시키고 싶다면, 서비스 내에서 stopSelf()를 호출하여 스스로 종료되도록 하거나, 다른 컴포넌트에서 stopService()를 호출하여 종료시켜한다.

 

- 액티비티 등의 앱 컴포넌트는 startService()를 호출함으로써 서비스를 실행할 수 있고, 이때 어떤 서비스를 실행할지에 대한 정보와 그 외에 서비스에 전달해야할 데이터를 담고 있는 인텐트를 인자로 넘길 수 있습니다. 그리고 서비스의 onStartCommand() 콜백 메소드에서 매개변수로 그 인텐트를 받게 됩니다.

 

onBind의 경우

- startService() 메소드 대신 bindService() 메소드를 통해 시작되는 서비스를 서비스 바인딩 (Service Bind 혹은 Bound Service) 라 한다.

 

- 마치 클라이언트-서버 와 같이 동작을 하는데 서비스가 서버 역할을 한다. 

(액티비티는 서비스에게 어떠한 요청을 할 수 있고, 서비스로부터 요청에 대한 결과를 받을수 있음)

 

- 하나의 서비스에 다수의 액티비티 연결 가능하며, 서비스 바인딩은 연결된 액티비티가 사라지면 서비스도 소멸된다. (즉 백그라운드에서 무한히 실행되지는 않음)

 

- 클라이언트가 서비스와의 접속을 마치려면 unbindService() 를 호출한다.

 

결론: 서비스가 돌아가는 동안 지속적으로 액티비티와 커뮤니케이션 하기 위해 사용