Android 即時通信開發小結(一)

《Android 即時通信開發小結》基於IM Andriod 開發的各類常見問題,結合網易雲信即時通信技術的實踐,對IM 開發作一個全面的總結。安全

 

相關推薦閱讀:、服務器

Android 即時通信開發小結(二)微信

移動IM開發指南1:如何進行技術選型網絡

移動IM開發指南2:心跳指令詳解架構

移動IM開發指南3:如何優化登陸模塊框架

 

客戶端架構ide

做爲一個 IM 軟件,最重要的一個特性就是保證消息的達到率和實時性。達到率受服務器性能和設計協議影響,後面再談。而實時性則主要取決於客戶端進程是否長期存活,鏈接是否一致保持。性能

進程切分優化

在 Android 系統中,App 對於本身應用的生命週期是基本沒有控制力,系統能在任意時候將你的進程殺死,且不會發出任何通知,也會在它認爲合適的時候把你叫起來。進程先後臺切換也一樣不會給出任何通知。不過進程的生死控制也仍是有一些規矩的,大致上來講就是進程佔的資源越多(內存,CPU 時間等等),對於用戶越不重要(前臺進程->可視進程->服務進程->後臺進程->空進程),越容易被幹掉。所以,進程應當儘可能小巧,且具備高的優先級。ui

若是一個應用自己就很小巧的話,一個進程就徹底足夠了,主線程負責 UI,另起一個後臺線程跑一個服務。而若是應用比較龐大的話,將推送服務獨立出來則是一個更好的選擇。主進程負責用戶交互和主要的業務邏輯,佔用龐大的資源,當退到後臺後,隨時被殺死都無所謂。推送進程則僅僅負責與服務器交互,保持最小限度的業務邏輯處理。

網絡鏈接和登陸狀態是綁在一塊兒的,登陸以後,同步數據也是必須的操做。所以,登陸和同步數據都須要在推送進程中完成,除此以外,其餘的業務都交給 UI 進程處理。推送進程收到本身不屬於本身的協議時,就將數據扔給 UI 進程處理。

兩個進程之間通訊方式沒有別的選擇,只有 AIDL,難點在於接口的設計。IM 業務邏輯複雜,咱們不可能爲每個調用實現一個 AIDL 接口,所以確定會把接口調用打包成控制命令傳遞。而標識控制命令比較容易想到的方式,是採用相似於 Message 的 what,由咱們爲每個控制命令分配一個命令號(或者再加一個子命令號),並指定對應的命令數據格式,接收端根據命令號再將數據反解出來處理。這種方式比較麻煩,且可維護性不好。更優雅的方式是使用遠程過程調用,發送端申明業務的調用接口,並在遠端實現這些接口,當發送端調用這些接口時,遠端直接調用對應接口的實現。除了使用各類第三方框架外,Java 自身的 Proxy 也能實現這個功能。而從推送進程到 UI 進程還有一點不一樣,UI 進程隨時可能會被幹掉,AIDL 調用可能會返回失敗,此種狀況可選擇 Intent 方式傳遞數據,併兼具喚起 UI 進程的功能。

 

 

保活分爲三個方面,一是系統API提供了接口,應用本身就能作的,這是」合法「的,二是利用系統的缺陷,躲開系統的審查,這算是」非法「的,或者是」灰色「的,三就是多個 App 結盟,互相喚醒,這是耍流氓,誰的陣營龐大誰就贏。

第一種主要有系統鬧鐘,各類事件的 BroadcastReceiver,任務被移除的回調通知等。

第二種已知的就是在 4.4 及之前版本上,使用 native 進程,並將該進程從 davilk 父進程中脫離,掛接到 init 進程上,以此避開系統的查殺。而後在這個 native 進程中,定時喚起應用。爲了讓這個 native 進程更輕巧,可使用 exec 的方式啓動一個可執行文件,以除掉直接 fork 帶入的 Zygote 進程環境。另外,這種方式也被用在監聽本身應用被卸載時彈出調查窗口。

第三種方式如今各大互聯網公司都在使用,方式很簡單,互相調用指定的 Service,或髮指定得廣播便可。只要你起一個阿里系的 App,其餘阿里系的 App 都會被跟着喚起。你啓動一個裝了友盟 SDK 的 App, 其餘裝了友盟 SDK 的 App,以及阿里系的 App 都會被跟着喚醒。

一般,第一種是必備,第二種和第三種則會結伴出現,流氓到底。

 

通訊協議選擇

消息的實時性的另外一個保證是長鏈接。固然,你也能夠用短鏈接輪詢,但這個通常只在網頁端短時聊天使用,在 Android 後臺無限時輪詢沒有人能受的了。長鏈接類型能夠選傳統的 TCP,也可使用 比較新的 WebSocket。 使用後一種的好處主要是服務器的,他們一套鏈接就能夠服務好 App 端和 Web 端。

IM 的通訊協議選擇性不少,開源的有 XMPP,MQTT等,使用開源協議的優點在於上手快,資料多。而大部分主流 IM 則通常會設計私有的通訊協議。使用私有協議,能夠針對本身的業務邏輯,設計出更省流量,效率更高的協議,同時,還能有效保護本身的生態圈,就像 Android 手機裝不了蘋果系統,易信用戶不能給微信用戶發消息同樣。

私有協議的協議內容和開源協議差很少,能夠包含通用的協議頭,而後加上負載包體。打包時,爲了追求可讀性,可使用文本協議,爲了追求省流量,則通常使用二進制協議。

在設計私有協議時,消息必達是一個須要側重考量的地方。因爲移動網絡的複雜性,消息在客戶端和服務器之間傳遞是有很大可能被傳丟的。當客戶端發送消息給服務器時,客戶端並不能確保消息必定就會被服務器收到,須要服務器在收到消息後給客戶端一個回饋,若是客戶端沒有收到回饋,就須要在必定超時後從新發送。這裏存在一個問題就是有可能服務器已經收到了,但回饋的包被丟掉了,這時就會形成消息重複,爲了去重,咱們須要爲相同的消息分配相同的 uuid,供接收方去重。一樣,當服務器將消息轉發給接收端時,服務器也不能保證接收端就必定能收到,須要接收端給服務器一個回執,告訴服務器這條消息我已經收到了,你就不要再給我發了。

 

Android 即時通信開發小結(二)將會從「創建安全鏈接」、「心跳」、「斷線重連」、「多媒體數據管理」、「圖片」、「語音」等問題出發,結合網易雲信即時通信技術的實踐, 進行詳細的介紹和總結。

相關文章
相關標籤/搜索