进程间通信时,服务端一次调用,客户端多次通知服务端
要做一个解锁的服务,然后其他进程去调用这个服务来解锁,解锁之后把解锁结果返回给其他进程,涉及到进程间通信。如果是简单的函数调用,那个就简单,binder,aidl,Messenger都可以胜任。
但是遇到的问题是,binder,aidl(其实里面是binder),Messenger (其实里面是aidl)它们都采用的其实是binder机制,binder机制在客户端调用远程服务时,如果使用返回值来获取调用结果,客户端是处于阻塞状态的,而解锁服务是一个耗时服务(500ms)左右,并且是在子线程中使用的,所以简单的binder调用并不能完美的解决问题。
解决方式
实际上就是客户端再开一个服务,由服务端的解锁服务去调用,把解锁结果等消息传给客户端。
1. 在客户端使用Activity去启用远程的服务端的解锁服务时,同时自己端开启一个接收消息的服务,这个服务因为跟此Activity是在同一个进程中,所以给这个接收消息的服务设置一个Handler。
2. 客户端调用解锁服务
3. 解锁服务在解锁过程中,把消息通过binder调用客户端的接收消息的服务,把解锁结果,解锁进度通知客户端的接收消息的服务。
4. 客户端的接收消息的服务,使用Handler来通知Activity更新结果。
遇到的一些问题
1.调用远程服务最开始用aidl,后来感觉binder本身用着也不错,所以就用binder实现了。其实上面的解决方式,用aidl或者Messenger都是一样的步骤,不过既然骨子里都是binder,还不如用最原始的。
2.后来尝试使用Messenger去通信,但是发现MsgfromClient.replyTo在使用过一次以后,后面就变成空的了,所以只能回复一次。这个倒是能支持多线程返回结果,如果只需要回复解锁结果的话,其实是可以用这个的。
再后来往里面看,发现用的aidl实现的,这么一想,还是binder万能。
下面是当时多次调用回复的日志
05-15 10:03:49.257 2016-2016/ming.com.faceunlock I/FaceUnlockService: start->>>mMsgfromClient:{ when=-1ms what=272 target=ming.com.faceunlock.FaceUnlockService$1 } mMsgfromClient.replyTo:android.os.Messenger@a0a27f8
05-15 10:03:50.702 2016-12111/ming.com.faceunlock I/FaceUnlockService: unlockResult->>>mMsgfromClient:{ when=-31d4h17m1s578ms barrier=0 } mMsgfromClient.replyTo:null
05-15 10:03:50.900 2016-12111/ming.com.faceunlock I/FaceUnlockService: complete->>>mMsgfromClient:{ when=-31d4h17m1s775ms barrier=0 } mMsgfromClient.replyTo:null