绑定服务

来源:互联网 发布:sshd 知乎 编辑:程序博客网 时间:2024/05/22 02:15

绑定服务分为本地服务和远程服务。

本地服务:调用者和服务在同一个应用程序里面。

远程服务:调用者和服务不在同一个应用程序里面。

绑定本地服务

服务里面的方法要想被调用者所调用

第一步:服务里面需要定义一个public类型的内部类(中间人如:MiddlePerson)继承Binder类,在内部类中定义一个public类型的方法,在该方法中调用服务里面的方法

第二步:在服务里面的onBind方法中返回这个内部类的一个对象


第三步:调用者在自定义的bind方法中通过bindService(Intent service, ServiceConnection conn, int flags);方法绑定服务

其中,service是意图,由于在同一个应用程序中,可以定义成显示意图。

ServiceConnection是接口,需要把这个接口的实现类创建出来,实现接口里面未实现的两个方法

1.第四步:当服务被连接的时候调用的方法(服务被成功绑定的时候调用):

onServiceConnected(ComponentName name, IBinder service)

参数service就是服务里面的onBind方法返回的对象声明出来一个中间人(服务内部类的引用),并把service(需要进行强制类型转换)赋值给这个中间人。

第五步:调用者通过这个中间人就可以调用服务里面的方法了


2.当服务失去连接的时候调用的方法(一般进程挂了,或者服务被异常杀死的时候调用):

onServiceDisconnected(ComponentName name)

flags是绑定额外的标识,一般为BIND_AUTO_CREATE。


调用者在自定义的unbind方法中通过调用unbindService(conn)方法解除绑定。解除绑定后,服务被回收了,但是服务里面的内部类的引用(中间人)没有被释放,若不将中间人回收,尽管服务已经停止,但是服务里面的方法仍然是可以被调用的,所以,解除绑定的同时,我们也要把中间人设为null


由于中间人是服务中public类型的内部类,所以,中间人的所有方法都可以被调用者所调用,但是中间人不希望自己所有的方法都能被调用者调用,把public类型改为private的话,调用者又不能调用中间人中的任何方法了。

通常想私有类里面的某个方法给暴露出来,我们可以通过接口的方式把它给暴露出来:

定义一个接口(中间人接口如:IMiddlePerson),在接口中定义public类型的private类要暴露的方法,然后这个私有类再实现这个中间人接口。

此时,调用者要定义服务里面的方法就不能通过中间人调用了,而是要通过接口。


远程服务

远程服务的服务在定义的时候,由于需要被其他应用程序所调用,所以服务需要在清单文件中添加意图过滤器,并添加action节点的name属性值

远程服务的调用者在绑定服务的时候,由于调用者跟服务不在同一个应用程序,所以要用隐式意图。隐式意图的setAction要与服务的清单文件中action的name属性值相同。


每一个应用程序都是运行在自己独立的进程里面的。进程是操作系统分配内存空间的一个单位。进程的数据都是独立的。默认情况下,不可以相互访问。有各自独立的内存空间。

要想让多个进程共享数据,就必须要按照一定的规范进行操作。进程间通讯:信号量、消息邮箱、消息队列、管道。。。

aidl:android interface definition language安卓接口定义语言

把服务里面定义的中间人接口文件改为aidl文件的方法:

中间人接口所在的包的属性==》复制Location==》cmd中粘贴按enter进入中间人接口所在文件夹==》把后缀改为.aidl==》F5刷新远程服务

由于接口文件只可能是公有的,所以aidl文件是没有访问权限修饰符的。故要把中间人接口里面的public都删除。保存时系统会在gen目录的包名下自动生成一个跟aidl同名的java文件。该文件中自动生成了一个继承Binder实现aidl的接口类型的抽象内部类Stub该类就是进程间通讯的实现类。以后在两个进程之间想要传递IBinder对象,只需要在服务中定义中间人时继承aidl文件名.Stub(如:IMiddlePerson.Stub)即可

IPC:inter process communication 进程间通讯。


调用者要想调用服务里面的方法,必须要保证aidl文件同远程服务里面的一样(包名也要和远程服务中aidl所在的包名相同)。


调用者调用onServiceConnected(ComponentName name, IBinder service)方法时

aidl文件名.Stub.asInterface(service);

如:private IMiddlePerson imp;

imp = IMiddlePerson.Stub.asInterface(service);


此时调用者就可以通过imp调用远程服务里面的方法了。

调用远程服务时除了上面与调用本地服务的不同外,其他都还是相同的。


绑定服务的应用场景:

绑定系统低层的一些服务,调用服务里面的方法。

0 0
原创粉丝点击