안드로이드 Service

: ) YOUNG·2022년 10월 16일
1

안드로이드

목록 보기
1/17
post-thumbnail


BindService

  • startService()와 달리 하나 이상의 클라이언트 컴포넌트 간의 통신을 구현 가능

  • 서비스를 실행시켜 두고 필요할 때 마다 서비스의 메소드를 접근하여 통신할 수 있는 구조

  • Service가 Background에서 실행되고 있을 때, Activity에서 Service의 메소드를 호출/결과를 받아서 보여주는 Interaction을 해야할 경우 등에 사용된다.

  • Binder는 기본적으로 Process간 통신을 제공한다.


bindService 생명주기

  • bindService() 함수로 시작 하면 onCreate() -> onBind() 함수가 호출되면서 Running 상태가된다.

  • bindService() 함수로 실행된 서비스는 unbindService()로 종료

  • 종료될 때 onUnbind() -> onDestroy() 함수가 호출된다.


Local에서 구현

  • bindService와 client가 동일 어플리케이션에 대해 로컬(동일 프로세스에서 실행)이면서 private(다른 애플리케이션에서 사용 불가)인 경우 라면 Binder 클래스의 서브 클래스 생성하여 구현 가능

Local이 아닌 경우(다른 프로세스)

  • Messenger와 Handler를 사용한다.

  • AIDL(Android Interface Definition Language)를 이용하여 서비스 구현


IPC/Binder

IPC(Inter Process Communication)

  • 프로세스 통신, 리눅스 커널에서 Binder를 이용하여 프로세스간 메시지를 주고 받도록 구현되어 있다.

  • 안드로이드 리눅스 커널을 기반으로 만들어져 있으므로, process는 kernel 내부의 일정 공간을 공유하여 함수를 호출하며 이를 Binder Driver가 수행

Parcel / Parcelable

  • Binder는 데이터를 parcel 형태로 전달하기 때문에 안드로이드에서는 parcelable 클래스를 활용

  • 안드로이드에서는 Serializable 보다는 Parcelable을 권장



local service

  • Binder를 통해 Activity와 Service가 통신하는 프로세스

Activity생성 -> Service Connection -> Service -> Binder -> Service Connection -> (서비스가 다시 시작되면 처음부터) -> Activity


class BoundService : Service() {
    private val mBinder: IBinder = MyLocalBinder()

    override fun onCreate() {
        super.onCreate()

    }

    override fun onBind(intent: Intent?): IBinder {
        return mBinder
    } 

    inner class MyLocalBinder : Binder() {
        // getService가 호출되면서 myService가 실행된다.
        fun getService(): BoundService {

            // getService를 호출하면 this를 통해서 자신인, BoundService가 return 된다.
            return this@BoundService
        }
    } // End of MyLocalBinder inner class

} // End of BoundService class


MainActivity


    private val connection =
        object : ServiceConnection {

            // MyLocalBinder가 IBinder 이므로 타입캐스팅이 가능하다.
            // 연결될 때 service가 IBInder가 onBind이다.
            // IBinder가 MyLocalBinder 이기 때문에 (MyLocalBinder가 IBinder 타입임)
            // service가 MyLocalBinder로 타입 캐스팅할 수 있다.
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                val binder = service as BoundService.MyLocalBinder
                myService = BoundService()
                myService = binder.getService()
                isBound = true
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                isBound = false
            }
        }
        
        
        
	override fun onStart() {
        super.onStart()
        val intent = Intent(this, BoundService::class.java)
        bindService(intent, connection, BIND_AUTO_CREATE)
    }


  • onBind 함수에서는 BoundService의 IBinder 객체를 반환함

  • 현재 시간을 반환하는 getCurrentTime() 함수 구현. 클라이언트가 이 method를 호출하기 위해서 bind함

  • Inner class로 Binder의 서브클래스인 MyLocalBinder를 정의하고 이 클래스는 getService 함수에서 서비스 인터페이스를 반환해주는 역할을 한다.

  • private val mBinder : IBinder = MyLocalBinder()를 통해서 new로 MyLocalBinder를 생성함 타입은 IBinder타입으로 지정

  • MyLocalBinder는 Binder를 상속 받았고, Binder가 IBinder를 상속받았기 때문에 MyLocalBinder는 IBinder 타입을 받을 수 있다. 즉, onBind에서 return type이 IBinder 타입을 return 한다는 것은 onBind가 myBinder를 return해도 된다는 얘기가 된다.

Binder의 구현체를 보면, IBinder를 implements함.

IBinder -> Binder 임, MyLocalBinder가 Binder를 상속받는다는 것은 MyLocaBinder가 IBinder 타입이 될 수 있다는 것을 얘기함.
(구조가 조금 복잡하다...)

  • onStart에서 bindService를 실행한다.

  • 이렇게 해서 BoundService에서 구현된 함수를 getService를 통해서 호출 할 수 있다.

  • 복잡한 로직, 또는 시간이 걸리는 작업의 경우를 Service내부에서 구현하고 작업하여 줄 수 있다.

0개의 댓글