[android] Service

이아름·2022년 10월 11일
0

안드로이드

목록 보기
7/13
post-thumbnail

Service

  • StartService()는 서비스를 호출만 합니다.
  • BindService()는 서비스를 호출해서 값을 주고 받을 수 있습니다.

BindService

  • bindService는 startService와는 달리 하나 이상의 클라이언트 컴포넌트 간의 통신을 구현할 수 있습니다.
  • 서비스를 실행시켜두고 필요할때마다 서비스의 메서드에 접근하여 통신할 수 있습니다.
  • Service(background)가 실행되고 있을때 화면(activity)에서 Service의 메서드를 호출하고 결과를 받아서 보여주는 등 상호작용할 경우 사용합니다.

BindService의 생명주기

Service 생명주기

  • onCreate -> onBind를 통해 생성되고 onUnbind -> onDestroy를 통해 삭제됩니다.

  • bindService() 함수로 실행된 서비스는 unbindService() 함수로 종료해야합니다.
    -> 보통 각각을 onStart() onStop()에서 실행합니다.


⁂ 서비스를 계속 실행하면서 바인딩도 제공해야하는 경우
-> startService를 통해 서비스를 실행시키고 클라이언트가 bindService()를 사용해 binding 할 수있다.
=> 이 경우에는 반드시 stopSelf() 또는 stopService()를 호출해야한다.
why? 바인딩을 모두 해제해도 서비스가 소멸되지 않음
=> onStartCommand()와 onBind() 둘 다를 구현해야함


BindService 구현하기

  • Local로 구현
    -> 서비스와 클라이언트가 동일 프로세스에서 실행되면서 private(다른 애플리케이션에서 사용 불가)인 경우라면 Binder 클래스의 서브 클래스를 생성하여 구현 가능
  • Local이 아닌 경우 (다른 프로세스에서 실행)
    -> Messenger와 Handler를 사용
    -> AIDL(Android Interface Definition Language) 사용

  • Service를 local로 구현하는 것은 thread를 사용하는 것과 동작이 비슷합니다.
  • 통신을 하는 모든 Thread는 queue를 가지고 있습니다.
    -> ThreadHandler가 queue의 값을 처리하고
    -> Looper가 Handler에게 queue의 값을 전달합니다.
    -> 모든 thread는 handler를 가질 수도 가지지 않을 수도 있습니다.

AIDL(Android Interface Definition Language)

  • AIDL은 android 에서 사용하는 IDL입니다.
  • IDL : 같은 언어를 사용하지 않는 소프트웨어 컴포넌트 사이의 통신을 가능하게 합니다.
    -> ex) c++과 java간의 통신을 구현할 때
    => 통신의 최하단 부분은 IDL이 구현해주고 개발자는 interface만 구현하도록 하는 것입니다.

Binder

  • Binder는 기본적으로 Process간 통신을 제공합니다.
  • IPC/ Binder
    -> IPC(Inter Process Communication) : 프로세스들 사이에 서로 데이터를 주고받는 행위 또는 그에 대한 방법이나 경로
    => 프로세스 통신, 리눅스 커널에서 Binder를 이용하여 프로세스간 메시지를 주고 받도록 구현되어 있습니다.
    => process는 kernel의 내부의 일정 공간을 공유하여 함수를 호출, 이를 Binder Driver가 수행합니다.

⁂ 이때 Binder는 android framework중 linux kernel에 있는 Binder입니다.

  • Parcel / Parcelable
    -> Binder는 데이터를 Parcel 형태로 전달하므로 안드로이드에서는 Parcelable 클래스를 활용합니다.
    => 안드로이드에서 직접 메모리 공간에 object를 읽고 쓰는 클래스를 Parcelable 클래스라고 합니다.
    ⁂ Serializable을 사용해도 무관합니다.

Local Service 생성하기

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

  • Activity가 ServiceConnection을 생성합니다.
  • Intent를 통해 bindService() 매개변수로 Service Connection 인스턴스를 넣고 bindService를 시작합니다. -> Service가 만들어집니다.
  • onBind를 통해 Binder를 생성합니다.
  • Service Connection의 내부 메서드인 onServiceConnected의 인자로 Binder가 주어집니다.

이제 하나하나 코드를 살펴 보겠습니다.

  • Activity가 ServiceConnection을 생성합니다.
//MainActivity
connection = object : ServiceConnection{
    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
         val binder = service as BoundService.MyLocalBinder
         myService = binder.getService()
   }

    override fun onServiceDisconnected(name: ComponentName?) {
    }
}
  • Intent를 통해 bindService() 매개변수로 Service Connection 인스턴스를 넣고 bindService를 시작합니다. -> Service가 만들어집니다.
//MainActivity
var intent = Intent(this, BoundService::class.java)
bindService(intent,connection, BIND_AUTO_CREATE)

-> bindService의 매개변수는 각각 intent, 성공하면 callback받을 곳, FLAG(binding option)의 인자를 받습니다.

  • onBind를 통해 Binder를 생성합니다.
//Service
private val mBinder : IBinder = MyLocalBinder()
override fun onBind(intent: Intent?): IBinder {
    return mBinder
}

inner class MyLocalBinder : Binder(){
    fun getService(): BoundService{
       return this@BoundService
    }
}
  • Service Connection의 내부 메서드인 onServiceConnected의 인자로 Binder가 주어집니다.
    -> 앞에서 만든 connection의 service: IBinder? 에 Service에서 만든 mBinder가 들어갑니다.

Remote Service 생성하기

local이 아닐 경우

  • 다른 프로세스에서도 Service를 사용해야 한다면 Messenger Handler를 이용해서 구현하는 방법이 있습니다.
    -> Message에 data를 담아서 다른 프로세스에 전해주는 것입니다.
    -> Android 11부터는 package visibility가 강화되어 외부의 Service를 호출한다면 AndroidMenifest.xml 파일에 queries를 선언해야 합니다.
    => 선언함으로 인해 어떤 Service를 호출하는지 명확하게 알 수 있습니다.

  • Handler로 처리하면 순차적으로 Task를 처리하여 동시에 Task를 처리할 수 없습니다.


AIDL을 통한 서비스 구현

  • AIDL를 통해서도 별도의 프로세스에서 서비스를 사용할 수 있습니다.
  • AIDL을 사용하면 여러 요청을 동시에 요청하고 처리할 수 있습니다.

AIDL 생성하기

  1. aidl 파일 생성 (textfile)
  2. 인터페이스 구현
    • Android SDK는 Java 언어로 인터페이스를 생성함
    • 해당 Interface는 Binder를 상속하고 AIDL 인터페이스 메서드를 구현해주는 Stub라는 내부 추상 클래스가 있음
  3. Activity에서 서비스 바인딩
    • Service를 구현한고 onBind()를 오버라이딩하여 Stub 추상클래스를 상속받은 클래스의 객체를 생성하여 반환함
    • Activity에서 구현한 서비스를 바인딩함
profile
반갑습니다

0개의 댓글