Android_app

[Android app] bindService() 분석

하니_즐거운하루 2023. 4. 3. 12:23

서비스는 안드로이드의 핵심 4대 구성요소중 하나로 호출하는 방법은
    startService() 또는 bindService()를 사용합니다.

   이번 노트에서는 이중 bindService() 를 분석해 봤습니다.

 

 bindService() 함수 인자 구성

   : 파라미터에 따라 몇개의 함수가 존재하고 저는 아래함수를 사용해 봤습니다.

   (service , conn , flags )

service 변수는 Intent 타입이고 Service를 상속받아 만든 class 를  인자로넣어주면 됩니다.

conn 변수는 ServiceConnection 타입이고 ServiceConnection interface를 상속한  객체를 만들고 이를 넣어줍니다. 

flags 는 Context 아래의 적당한 타입을   넣어 줍니다.

 

▶  service 변수 적용하기

   : sevice 변수는 타입이 Intent 이므로 다음처럼 생성을 해 줍니다.

 

val intent = Intent(this@MainActivity,???)
  --> ??? 에는  Service 클래스를 상속한 클래스를 넣어줍니다.

 

  →  아래처럼 MyService를  만들고

   :  New > Service > Service 선택후

    Class Name 변경후 Finish 버튼 클릭

 

   별 내용은 없이 Service() 상속한 MyService 클래스가 생성이 되네요.

class MyService : Service() {

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

 

   Intent  인자에 들어갈 서비스를 만들었으니 아래처럼 넣어줍니다.

val intent = Intent(this@MainActivity,MyService::class.java)

 

▶  conn 변수 적용하기

    : conn 변수는  ServiceConnection 타입의 인터페이스 이고 object 키워드를 사용해 객체를 생성

     하고 내부에  override 함수를 정의해 줍니다.

    val serviceConnection:ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            TODO("Not yet implemented")
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
            TODO("Not yet implemented")
        }
    }

 

 

▶  flags 변수 적용하기

   : Context 클래스의 변수중 BIND_AUTO_CREATE 적용하기

bindService(intent , serviceConnection, Context.BIND_AUTO_CREATE)

 

▶ onBind() 코드 만들기

   :  bindService() 안에 들어가는 인자처리가 끝났으니 다음은 MyService.kt 소스안에 onBind() 함수를 재정의 해줍니다.

     >>  bindService() 호출시 MyService 의 onBind() 가 호출이 됩니다.

      리턴에 null 을 넣으니 에러가 나오네요. 

 

 IBinder 를 리턴해야 하고 이는 ServiceConnection> onServiceConnected() 의 p1 인자와 연결이 됩니다.

 →  IBinder를 implement 한 Binder 클래스를 상속하는  inner 클래스 LocalBinder 를  만들어 주고

      추가로 MyService 클래스의 메소드를  외부에서  사용하기 위해 getService() 함수도 추가해 줍니다.

 

 →  LocalBinder 클래스 객체변수 mBinder 를 만들어주고 onBind() 의 return 에 넣어줍니다.

      소스 코드 참고하세요.

class MyService : Service() {
    ~~ 중략 ~~
    // 1> IBinder 상속한 LocalBinder 클래스 만들기
    inner class LocalBinder : Binder() {
        fun getService():MyService {
            return this@MyService
        }
    }
    
    // 2> LocalBinder 변수 생성
    val mBinder = LocalBinder()
    
    
    // 3> onBind() 함수에 넣기
    override fun onBind(intent: Intent): IBinder {
        Log.d(TAG,"onBind()")
        return mBinder
    }

 

  >  bindService() 호출시 아래처럼 onBind 코드가 호출되면 OK 입니다.

 

 

▶  ServiceConnnection 클래스  onServiceConnected() 함수를 작성하라는 에러가 보이네요.

    → 인자로 넘어오는 p1 값의 타입이 IBinder 인데 이게 MyService 안의 LocalBinder 클래스가 되고

        getService() 메소드를 통해 MyService 클래스 객체를  myService 변수에 대입합니다.

        >  val myService: MyService =(p1 as MyService.LocalBinder).getService()

    val serviceConnection:ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            TODO("Not yet implemented")
        }
        override fun onServiceDisconnected(p0: ComponentName?) {
            TODO("Not yet implemented")
        }
    }
    
    ==> 
    
    // 1> myService 변수 선언
    var myService : MyService? = null
    
    // 2> myService 변수에 IBinder 변수를 이용해 값을 할당합니다.
    val serviceConnection:ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            Log.d(TAG,"onServiceConnected()")
            myService =(p1 as MyService.LocalBinder).getService()
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
	        Log.d(TAG,"onServiceDisconnected()")
            myService = null
        }
    }

 

 

▶ Service 에 함수 작성후  호출 여부 테스트

// 1> MyService 안에 메서드 한개 만들기
class MyService : Service() {
    ~~ 중략 ~~
    fun test() {
        Log.d(TAG,"test()")
    }
}


// 2> MainActicity 안의 myService 변수를 통한 메서드 호출
class MainActivity : ComponentActivity() {
    var myService : MyService? = null      <---- 요기
    ~~ 중략 ~~
    val serviceConnection:ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            myService =(p1 as MyService.LocalBinder).getService()     <---- 요기
        }
        ~~ 중략 ~~
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ~~ 중략 ~~
        Column(
            modifier = Modifier.fillMaxSize(),
        ) {
             Button(
                onClick = {
                    myService?.test()    <---- 요기
                },
                modifier = Modifier.align(alignment = Alignment.CenterHorizontally),
            ){
                Text("myService.test()")
            }
        }
    }

}

  

 

<기타 >

bindService() 호출시 내부 동작

           MainActivity                                      <----->                          MyService

           bindService()                                     ----->

                                                                     <-----                           onBind()

    ServiceConnection.onServiceConnected

 

 

bindService() 호출코드를 분석해 보았습니다.

참고하세요.

 

반응형