bindservice:「Binder机制」实例篇,超详细

 2021-07-17 9:08    77  

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

这篇先来看实例bindservice,第二篇分析源码

bindservice:「Binder机制」实例篇,超详细

一、创建工程bindservice,并且创建两个端

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

如图bindservice,在此工程中创建了两个module

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

black_client

bindservice:「Binder机制」实例篇,超详细

black_server

bindservice:「Binder机制」实例篇,超详细

二、在 black_server 端我们先创建 Aidl 文件

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

创建即可

bindservice:「Binder机制」实例篇,超详细

然后在创建出来的 aidl 文件中定义我们想要给 server 端设置的方法

bindservice:「Binder机制」实例篇,超详细

第三步、定义 aidl 拥有的功能

bindservice:「Binder机制」实例篇,超详细

本例想让 server 端拥有 添加学生、获得学生列表 的方法。

bindservice:「Binder机制」实例篇,超详细

① 那么首先我们需要先定义一个学生类

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

注意,因为我们需要在aidl 中使用此类,所以此类必须要实现 Parcelable 接口,这样才能跨进程使用此类。

bindservice:「Binder机制」实例篇,超详细

② 有了上述中的学生类后,我们就可以定义 aidl 拥有的功能了

bindservice:「Binder机制」实例篇,超详细

首先,在创建 aidl 文件生成的目录中,我们需要再创建一个与学生类对应的 aidl 文件,如下图

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

这样定义后,IMyAidlInterface.aidl 文件才能关联上学生类,并且能够 make成功。

bindservice:「Binder机制」实例篇,超详细

然后我们再定义 aidl 拥有的功能,如下图

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

需要说明的是 addStudent(in Student student)方法的定义,in 表示是输入的参数,必须指定。

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

此外,还要手动 import Student 的包,否则在 make 的时候会无法找到Student 类。

bindservice:「Binder机制」实例篇,超详细

这样我们就定义完了 aidl 文件拥有的功能了。

bindservice:「Binder机制」实例篇,超详细

③ make project

bindservice:「Binder机制」实例篇,超详细

bindservice:「Binder机制」实例篇,超详细

make成功后,就生成了能让客户端远程访问的桥梁。

桥梁搭好了,但是具体 aidl 的功能的实现还没有做,下一步就要让服务端完成这些功能的实现。

Stub 抽象类即是我们 server 端要实现的类,即具体的 aidl 的功能需要 server 端实现 aidl 中的 Stub 抽象类才能具体化。

第四步、我们继续完成服务端的逻辑

在服务端创建 ServerService 文件

然后创建内部类,实现 aidl 中的 Stub抽象类

实现这两个方法,下图具体实现:

最后,清单文件中注册此 Service。

注意:一定要将

android:exported="true"加上,这样才能被其他进程调用。

这样,我们就把服务端的逻辑处理完了

第五步、配置客户端

① 将服务端的 Person 类复制过来,注意包名需要与服务端完全相同

② 给客户端添加两个按钮,一个按钮触发 bindService 事件,一个按钮用来操作服务端进程的逻辑。

自定义了两个方法 bindService 和 handle 方法。

我们先把绑定服务的代码完善下:

bindService 写完后,别忘了在 Activity 销毁的时候,调用 unBindService 方法

当 service 连接成功后,需要通过 service 获取到 服务端的代理,进而再访问到服务端实际逻辑。

所以此时,我们需要把服务端的 aidl 的代码完全复制过来(包名一致),然后再 make project,才能够使用 aidl 。

③ 复制 aidl 文件夹,并且 make project

复制完后,make

④ 客户端 make 完后,就可以继续完善上面的两个方法了

//通过此方法,我们会拿到服务端的代理IMyAidlInterface.Stub.asInterface(service) //通过代理调用服务端的方法,具体内部的实现是服务端实现iMyAidlInterface.addStudent()iMyAidlInterface.getStudents()第六步、运行

先跑服务端,再跑客服端,否则客户端会因为找不到对应的 service 而报错。

先点击 “绑定服务端”,再点击几次 “操作远程 service 的逻辑”

打印结果为

说明我们已经从客户端通过 aidl 访问到了 服务端提供的逻辑。

此时我们杀死服务端程序,这个时候,客户端与服务端的连接会断开

此时,再次点击 “绑定服务端”

发现,仍然是可以绑定的。

再次点击 “操作远程 service 的逻辑”

仍然可以操作。

说明客户端想要远程访问服务端,只需要服务端在手机上存在即可,不需要提前开启服务端。

至此,我们的例子就介绍完了。

最后,我们来从客户端正向理一下 aidl 的调用过程。

//获得 AIDL 的代理 ProxyIMyAidlInterface.Stub.asInterface(service);

//调用 Proxy 的 addStudent 方法iMyAidlInterface.addStudent();

这里有两个 Parcel 文件,一个 _data 一个 _reply,data 表示的是调用服务端传入的数据,而 reply 表示的是服务端返回给客户端的数据。

//Proxy 内部调用 Binder 的 transact 方法mRomote.transact(Stub.TRANSACTION_addStudent,_data,_reply,0)

进而调用 Binder 的 onTransact()方法

//而 AIDL 文件中的 Stub 是 Binder 的子类,它实现了 Binder 的 onTransact() 方法。Stub.onTransact()

最终会来到

this.addStudent()

这个 addStudent() 只有服务端的 Service 内部类实现了

所以最终会调用到服务端的处理逻辑。

画个时序图,大概是这样的

今天就到这,下篇一起看下 binder 机制源码吧

本文标签:实例机制

原文链接:https://www.xgfox.com/alpx/1034.html

本文版权:如无特别标注,本站文章均为原创。