介绍
- [x] Binder由四部分组成:Binder客户端、Binder服务端、Binder驱动、服务登记查询模块。
- Binder客户端是想要使用服务的进程。
- Binder服务端是实际提供服务的进程。
- Binder驱动:
1.客户端先通过Binder拿到一个服务端进程中的一个对象的引用,
2.通过这个引用,直接调用对象的方法获取结果。
3.在这个引用对象执行方法时,它是先将客户端方法调用的请求传给Binder驱动;
4.然后Binder驱动再将客户端请求传给服务端进程;
5.服务端进程收到请求后,调用服务端“真正”的对象来执行所调用的方法;得出结果后,将结果发给Binder驱动;
6.Binder驱动再将结果发给我们的客户端;
7.最终,我们在客户端进程的调用就有了返回值。
8.Binder驱动,相当于一个中转者的角色。通过这个中转者的帮忙,我们就可以调用其它进程中的对象。
- Service Manager(服务登记查询模块)
1.我们调用其它进程里面的对象时,首先要获取这个对象。这个对象其实代表了另外一个进程能给我们提供什么样的服务(再直接一点,就是:对象中有哪些方法可以让客户端进程调用)。
2.首先服务端进程要在某个地方注册登记一下,告诉系统我有个对象可以公开给其它进程来提供服务。当客户端进程需要这个服务时,就去这个登记的地方通过查询来找到这个对象
Binder工作流程
- 假设:客户端的程序Client运行在进程A中,服务端的程序Server运行在进程B中。
- 由于进程的隔离性,Client不能读写Server中的内容,但内核可以,而Binder驱动就是运行在内核态,因此Binder驱动帮我们进行请求的中转。
- 有了Binder驱动,Client和Server之间就可以打交道了,但是为了实现功能的单一性,我们为Client和Server分别设置一个代理:Client的代理Proxy和Server的代理Stub。这样,由进程A中的Proxy和进程B中的Stub通过Binder驱动进行数据交流,Server和Client直接调用Stub和Proxy的接口返回数据即可。
- 此时,Client直接调用Proxy这个聚合了Binder的类,我们可以使用一系列的Manager来屏蔽掉Binder的实现细节,Client直接调用Manager中的方法获取数据,这样做的好处是Client不需要知道Binder具体怎么工作。
- Client想要获得的服务多种多样,那么它是怎么获取Proxy或Manager的呢?答案是通过Service Manager进程来获取的。Service Manager总是第一个启动的服务,其他服务端进程启动后,可以在Service Manager中注册,这样Client就可以通过Service Manager来获取服务器的服务列表,进而选择具体调用的服务器进程方法。
AIDL通信实例
<activity
android:name=".ServerActivity"
android:process=":remote" />
<activity android:name=".ClientActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
/**
* @Author yangtianfu
* @Data 2021/4/1 18:01
* @Des ②创建aidl文件和用于客户端与服务端通信的方法
*/
interface IMyAidlInterface {
void setName(String name);
String getName();
}
- ③AIDL文件声明完,activity等文件并不能调用到IInfManager接口,需要在app的build.gradle文件中的android{}中添加
sourceSets{
main{
java.srcDirs = ['src/main/java', 'src/main/aidl']
}
}
- ④Service中创建Binder对象,onBind方法中返回这个对象,Binder对象中具体实现了IMyAidlInterface接口中的方法。Service记得在AndroidManifest.xml中注册
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
package com.example.binderapp
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.os.RemoteException
/**
* @Author yangtianfu
* @Data 2021/4/1 18:09
* @Des ④Service中创建Binder对象,
* 在onBind方法中返回这个对象,Binder对象中具体实现了IMyAidlInterface接口中的方法。Service记得在AndroidManifest.xml中注册
*/
class MyService : Service() {
private var name: String? = ""
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
name = intent?.getStringExtra("name")
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent): IBinder {
return binder
}
private val binder: Binder = object : IMyAidlInterface.Stub() {
@Throws(RemoteException::class)
override fun setName(mName: String) {
name = mName
}
@Throws(RemoteException::class)
override fun getName(): String {
return name?:""
}
}
}
package com.example.binderapp
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
class ServerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_server)
val intent = Intent(this@ServerActivity,MyService::class.java)
intent.putExtra("name","BlissYang")
startService(intent)
}
fun jumpClient(view: View) {
startActivity(Intent(this@ServerActivity, ClientActivity::class.java))
}
}
package com.example.binderapp
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class ClientActivity : AppCompatActivity() {
private var iMyAidlInterface: IMyAidlInterface? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this@ClientActivity,MyService::class.java)
bindService(intent,connection, Context.BIND_AUTO_CREATE)
// Thread.sleep(3_000L)
// iMyAidlInterface?.name = "客户端消息"
}
private val connection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service)
try {
Log.i("ClientActivity", "服务端数据:" + iMyAidlInterface?.name)
iMyAidlInterface?.name = "YangTianfu"
Log.i("ClientActivity", "next:" + iMyAidlInterface?.name)
} catch (e: RemoteException) {
}
}
override fun onServiceDisconnected(name: ComponentName) {
}
}
override fun onDestroy() {
super.onDestroy()
unbindService(connection)
}
}