3122小游戏,在线h漫,2411小游戏
最近有个项目刚好使用了service,特别是aidl远程服务,经过这次项目对service有了更好的理解,在这里作个总结。
startservice / bindservice 混合使用
如果startservice / bindservice 混合使用 那service的生命同期会怎样呢,其实只要记住以上的思路,这种问题很好理解。首先 startservice 与 stopservice 对应 ,没有stopservice 之前不会 destroy service , bindservice 与 unbindservice对应 ,没有 unbindservice 前也不会destroy service。
为服务添加权限
相信大家做的服务都是公共的,即所有应用都可以调用。但是如果我想我的服务只给特定的应用调用,应该如何设置呢?我们可以给服务添加权限。关于权限,android系统给权限为了四个类别:
<uses-permission android:name="android.permission.custom.xxx"/>
如果我们想让自己开发的service只能被特定的client调用,那就可以添加自定义的权限。比如危险级,我们可以在androidmanifest.xml中声明对应的权限,只有应用也设置了这个权限,才能正常启动服务。
关于aidl远程服务
所谓的aidl远程服务 就是运行在另一个进程的服务,平时我们调用的服务都运行在主线程。要使用aidl服务就必须写aidl接口,向外暴露接口就可以与远程服务进行交互了。对于aidl有如下几个值得注意的地方:
aidl的接口如何升级?
在做一个比较大型的项目,那项目会不断迭代,那就有可能增加、修改aidl接口,那如何保证aidl接口和老的接口不会混乱呢,根据我的经验有如下总结:
service管理多个客户端
如果service有多个客户端,如何安全地与它们通信呢?如何给各个客户端回调结果呢? 在这里我要说说我在最近项目出现的一个问题,我在项目中要做一个公共的服务,类似于指纹解锁,其它应用通过调用我的服务来获取结果,我设计了start(callback), stop()两个接口,一开始我就用单回调的方式,即在代码中定义一个callback的属性,谁调用了start就把callback设置成谁,只有最后一个调用start的client能够获得回调,代码如下 :
private callbak mcallback; public void start(callback callback) { this.mcallback = callback; } public void stop() { this.mcallback = null; }
这种方式,在单个应用时是很有效的,在多个应用时,只要应用能按顺序执行start、stop 那这个接口的设计也没什么问题。但是事情没想象中那么简单,如果client1调用了start,跟着client2也调用了start,这时client1 要stop,那会怎样,那整个服务都stop了。这个就是我设计的服务中出现的大问题,之后我想着为我的服务接口作一些改变,以适应这种多应用的不按顺序的调用 。我第一个想法就是用register、unregister的方式,用一个list收集所有的callback ,回调时可以轮循,stop时也可以通过判断list的个数,如果是小于等于1,那就执行stop :
private list<callbak> mcallbacks; public void start(callback callback) { mcallbacks.add(callback); } public void stop(callback callback) { mcallbacks.remove(callback); if(list.size() >= 1) return; }
考虑到接口的升级,这个改动是最小的,只给stop添加了一个参数。但是这个方式也有毛病,我们服务对callback的引用是强引用,如果client异常退出了,那引用还在并且会越积越多,在回调的时候,也可能出现deadobjectexception的错误。通过网络查找资料,我找到了remotecallbacklist,remotecallbacklist也是一个列表,保存的是回调接口,使用link-to-death回调 (在sevice中接受到这个binder对象,并且使用 binder.linktodeath(),注册一个deathrecipient回调;实现deathrecipient。当client意外退出的时候,deathrecipient.binderdied()将被回调,我们可以在这里释放相关的资源。)。最终代码如下:
private remotecallbacklist<callback> mcallbacks = new remotecallbacklist<>(); public void start(callback callback) { mcallbacks.register(callback); } public void stop(callback callback) { mcallbacks.unregister(callback); if(mcallbacks.getbroadcastitem() >= 1) return; } private void notifyresult(string result) { final int len = mcallbacks.beginbroadcast(); for (int i = 0; i < len; i++) { try { mcallbacks.getbroadcastitem(i).onresult(result); } catch (remoteexception e) { e.printstacktrace(); } } mcallbacks.finishbroadcast(); }
使用messenger 实现 servie与client端通信
messenger是基于handler的,通过为messenger添加handler来传递处理数据,之后service与client的通信都是通过传递的handler来进行。用这种方式可以不需要定义aidl接口,也就不出现因为修改aidl接口所造成的接口版本不对应的麻烦。
messenger的使用就是通过 handler传递消息, 客户端send方法发送的是一个message,这个message.replyto指向的是一个messenger,messenger又持有客户端的一个binder对象(messengerimpl),服务端正是利用这个binder对象做的与客户端的通信。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Android apk 项目一键打包并上传到蒲公英的实现方法
Android 自定义LineLayout实现满屏任意拖动功能的示例代码
android 限制某个操作每天只能操作指定的次数(示例代码详解)
Android 集成 google 登录并获取性别等隐私信息的实现代码
网友评论