進(jìn)程間通信時(shí),服務(wù)端一次調(diào)用,客戶端多次通知服務(wù)端
要做一個(gè)解鎖的服務(wù),然后其他進(jìn)程去調(diào)用這個(gè)服務(wù)來解鎖,解鎖之后把解鎖結(jié)果返回給其他進(jìn)程,涉及到進(jìn)程間通信。如果是簡單的函數(shù)調(diào)用,那個(gè)就簡單,binder,aidl,Messenger都可以勝任。
但是遇到的問題是,binder,aidl(其實(shí)里面是binder),Messenger (其實(shí)里面是aidl)它們都采用的其實(shí)是binder機(jī)制,binder機(jī)制在客戶端調(diào)用遠(yuǎn)程服務(wù)時(shí),如果使用返回值來獲取調(diào)用結(jié)果,客戶端是處于阻塞狀態(tài)的,而解鎖服務(wù)是一個(gè)耗時(shí)服務(wù)(500ms)左右,并且是在子線程中使用的,所以簡單的binder調(diào)用并不能完美的解決問題。
解決方式
實(shí)際上就是客戶端再開一個(gè)服務(wù),由服務(wù)端的解鎖服務(wù)去調(diào)用,把解鎖結(jié)果等消息傳給客戶端。
1. 在客戶端使用Activity去啟用遠(yuǎn)程的服務(wù)端的解鎖服務(wù)時(shí),同時(shí)自己端開啟一個(gè)接收消息的服務(wù),這個(gè)服務(wù)因?yàn)楦薃ctivity是在同一個(gè)進(jìn)程中,所以給這個(gè)接收消息的服務(wù)設(shè)置一個(gè)Handler。
2. 客戶端調(diào)用解鎖服務(wù)
3. 解鎖服務(wù)在解鎖過程中,把消息通過binder調(diào)用客戶端的接收消息的服務(wù),把解鎖結(jié)果,解鎖進(jìn)度通知客戶端的接收消息的服務(wù)。
4. 客戶端的接收消息的服務(wù),使用Handler來通知Activity更新結(jié)果。
遇到的一些問題
1.調(diào)用遠(yuǎn)程服務(wù)最開始用aidl,后來感覺binder本身用著也不錯(cuò),所以就用binder實(shí)現(xiàn)了。其實(shí)上面的解決方式,用aidl或者M(jìn)essenger都是一樣的步驟,不過既然骨子里都是binder,還不如用最原始的。
2.后來嘗試使用Messenger去通信,但是發(fā)現(xiàn)MsgfromClient.replyTo在使用過一次以后,后面就變成空的了,所以只能回復(fù)一次。這個(gè)倒是能支持多線程返回結(jié)果,如果只需要回復(fù)解鎖結(jié)果的話,其實(shí)是可以用這個(gè)的。
再后來往里面看,發(fā)現(xiàn)用的aidl實(shí)現(xiàn)的,這么一想,還是binder萬能。
下面是當(dāng)時(shí)多次調(diào)用回復(fù)的日志
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