Message 메소드
obtain()
: 메시지를 풀에서 가져오거나 새로운 메시지를 생성합니다.sendToTarget()
: 메시지를 해당 메시지가 속한 Handler의 대상으로 보냅니다.setData()
,setDataInt()
,setDataLong()
: 메시지에 데이터를 추가합니다.- arg1, arg2, obj : 메시지에 대한 추가적인 정보를 설정하거나 가져옵니다.
클라이언트 앱에서 서비스에 명령을 보내거나
, 백그라운드 서비스에서 메인 액티비티로 데이터를 전송
하는 데 사용될 수 있다.🚗 메신저 객체를 생성하는 두 가지 경우
1. 액티비티에서 IBinder를 넘겨주는 경우
- 이 경우, 액티비티가 서비스와 바인딩되고 서비스로부터 IBinder를 받아와 Messenger를 생성
- 이렇게 생성된 Messenger는 서비스에게 메시지를 보낼 때 사용됩니다. 액티비티에서 생성된 Messenger를 통해 메시지를 보내면, 해당 메시지는 서비스의 Handler에 도달하게 된다.
2. 서비스에서 핸들러를 넘겨주는 경우- 이 경우, 서비스의 Handler를 사용하여 받은 메시지를 처리
- 클라이언트 앱에서 생성된 Messenger가 서비스의 핸들러를 통해 메시지를 전달합니다. 이 핸들러는 서비스에서 메시지를 수신하고 처리하는 역할을 한다.
send(Message)
, getBinder()
등이 있다.1) MyService.kt
class MyService : Service() {
// 난 메신저를 쓸거다
private lateinit var messenger: Messenger
override fun onCreate() {
super.onCreate()
// 메신저를 만들때엔 메신저 객체에 핸들러를 매개변수로 넘겨줘야한다.
messenger = Messenger(IncomingHandler())
}
override fun onBind(intent: Intent): IBinder {
// onBind에서 메신저의 바인더를 리턴해줌
return messenger.binder
}
private inner class IncomingHandler: Handler(){
// 핸들러는 말그대로,, 어떻게 핸들할 것이다를 담고 있다
// 메세지 객체는 핸들러를 통해 메시지 큐에 전달된다.
override fun handleMessage(msg: Message) {
when (msg.what){
MSG_HELLO -> {
// 처리할 내용
showToast("hello from client~")
}
else -> super.handleMessage(msg)
}
}
}
companion object {
const val MSG_HELLO = 1
}
// 토스트 메시지를 띄우는 함수
private fun showToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
2) MainActivity.kt
bindService
로 서비스를 연결해준 후, 만들어진 Messenger
(onServiceConnected
)에 메세지를 send해주는 것이 핵심class MainActivity : AppCompatActivity() {
private var messenger : Messenger? = null
private var bound = false
// 서비스컴포넌트 쓸 것이니 서비스 커넥션 생성
private val serviceConnection = object: ServiceConnection{
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
// 서비스와 바인딩되는 메신저 객체 생성
// 서비스 컴포넌트의 onBind에서 반환한 messenger.bind를 IBinder형태로 받아와서 넣어줌
messenger = Messenger(p1)
bound = true
}
override fun onServiceDisconnected(p0: ComponentName?) {
messenger = null
bound = false
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this, MyService::class.java)
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
val btnSend = findViewById<Button>(R.id.btnSend)
btnSend.setOnClickListener {
sendMessageToService()
}
}
override fun onDestroy() {
super.onDestroy()
if (bound){
unbindService(serviceConnection)
bound = false
}
}
private fun sendMessageToService(){
if (!bound) return
// 메시지를 얻기 위해 사용. 메세지풀에서 가져옴
val message = Message.obtain(null, MyService.MSG_HELLO, 0,0)
try{
// 메신저 클래스의 기본 메소드. 메세지 객체를 넣어서 보내면 메신저의 handleMessage로 넘어감
messenger?.send(message)
}catch(e:RemoteException){
e.printStackTrace()
}
}
}
// IMyAidlInterface.aidl
package com.example.ch15_aidl;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
void showToastMessage(String message);
}
onBind()
에서 binder를 리턴해주면 되는데, 그 binder는 IMyAidlInterface.Stub()
를 하면 해당 AIDL 인터페이스의 Binder 객체가 반환된다. 이 Binder 객체를 클라이언트와 서비스 간의 통신을 위한 인터페이스로 사용할 수 있는 것.class MyService : Service() {
override fun onBind(intent: Intent): IBinder {
return binder
}
// binder 객체 생성
private val binder = object : IMyAidlInterface.Stub(){
override fun showToastMessage(message : String){
// Display a toast message
message?.let {
Toast.makeText(applicationContext, it, Toast.LENGTH_SHORT).show()
}
}
}
}
bindService()
로 서비스와 바인딩한다. ServiceConnection
에서 IMyAidlInterface.Stub.asInterface(service)
로 바인딩해준다. class MainActivity : AppCompatActivity() {
private var service: IMyAidlInterface? = null
private var bound = false
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
this@MainActivity.service = IMyAidlInterface.Stub.asInterface(service)
bound = true
}
override fun onServiceDisconnected(name: ComponentName?) {
service = null
bound = false
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this, MyService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
val btnSend = findViewById<Button>(R.id.btnSend)
btnSend.setOnClickListener {
sendMessageToService()
}
}
override fun onDestroy() {
super.onDestroy()
if (bound) {
unbindService(connection)
bound = false
}
}
// Method to send message to the service and display toast
private fun sendMessageToService() {
val message = "AIDL service to Client!"
service?.showToastMessage(message)
}
}