[Android app] bindService() 분석
: 서비스는 안드로이드의 핵심 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() 호출코드를 분석해 보았습니다.
참고하세요.