Android使用Google Cloud Messaging(已廢棄)

2018-08-02 17:43 更新

編寫(xiě):jdneo - 原文:http://developer.android.com/training/cloudsync/gcm.html

谷歌云消息(GCM)是一個(gè)用來(lái)給Android設(shè)備發(fā)送消息的免費(fèi)服務(wù),它可以極大地提升用戶體驗(yàn)。利用GCM消息,你的應(yīng)用可以一直保持更新的狀態(tài),同時(shí)不會(huì)使你的設(shè)備在服務(wù)器端沒(méi)有可用更新時(shí),喚醒無(wú)線電并對(duì)服務(wù)器發(fā)起輪詢(這會(huì)消耗大量的電量)。同時(shí),GCM可以讓你最多一次性將一條消息發(fā)送給1,000個(gè)人,使得你可以在恰當(dāng)?shù)貢r(shí)機(jī)很輕松地聯(lián)系大量的用戶,同時(shí)大量地減輕你的服務(wù)器負(fù)擔(dān)。

這節(jié)課將包含一些把GCM集成到應(yīng)用中的最佳實(shí)踐方法,前提是假定你已經(jīng)對(duì)該服務(wù)的基本實(shí)現(xiàn)有了一個(gè)了解。如果不是這樣的話,你可以先閱讀一下:GCM demo app tutorial。

高效地發(fā)送多播消息

一個(gè)GCM最有用的特性之一是單條消息最多可以發(fā)送給1,000個(gè)接收者。這個(gè)功能可以更加簡(jiǎn)單地將重要消息發(fā)送給你的所有用戶群體。例如,比方說(shuō)你有一條消息需要發(fā)送給1,000,000個(gè)人,而你的服務(wù)器每秒能發(fā)送500條消息。如果你的每條消息只能發(fā)送給一個(gè)接收者,那么整個(gè)消息發(fā)送過(guò)程將會(huì)耗時(shí)1,000,000/500=2,000秒,大約半小時(shí)。然而,如果一條消息可以一次性地發(fā)送給1,000個(gè)人的話,那么耗時(shí)將會(huì)是(1,000,000/1,000)/500=2秒。這不僅僅體現(xiàn)出了GCM的實(shí)用性,同時(shí)對(duì)于一些實(shí)時(shí)消息而言,其重要性也是不言而喻的。就比如災(zāi)難預(yù)警或者體育比分播報(bào),如果延遲了30分鐘,消息的價(jià)值就大打折扣了。

想要利用這一功能非常簡(jiǎn)單。如果你使用的是Java語(yǔ)言版本的GCM helper library,只需要向send或者sendNoRetry方法提供一個(gè)注冊(cè)ID的List就行了(不要只給單個(gè)的注冊(cè)ID):

// This method name is completely fabricated, but you get the idea.
List regIds = whoShouldISendThisTo(message);

// If you want the SDK to automatically retry a certain number of times, use the
// standard send method.
MulticastResult result = sender.send(message, regIds, 5);

// Otherwise, use sendNoRetry.
MulticastResult result = sender.sendNoRetry(message, regIds);

如果想用除了Java之外的語(yǔ)言實(shí)現(xiàn)GCM支持,可以構(gòu)建一個(gè)帶有下列頭部信息的HTTP POST請(qǐng)求:

Authorization: key=YOUR_API_KEY
Content-type: application/json

之后將你想要使用的參數(shù)編碼成一個(gè)JSON對(duì)象,列出所有在registration_ids這個(gè)Key下的注冊(cè)ID。下面的代碼片段是一個(gè)例子。除了registration_ids之外的所有參數(shù)都是可選的,在data內(nèi)的項(xiàng)目代表了用戶定義的載荷數(shù)據(jù),而非GCM定義的參數(shù)。這個(gè)HTTP POST消息將會(huì)發(fā)送到:https://android.googleapis.com/gcm/send

{ "collapse_key": "score_update",
   "time_to_live": 108,
   "delay_while_idle": true,
   "data": {
       "score": "4 x 8",
       "time": "15:16.2342"
   },
   "registration_ids":["4", "8", "15", "16", "23", "42"]
}

關(guān)于更多GCM多播消息的格式,可以閱讀:Sending Messages。

對(duì)可替換的消息執(zhí)行折疊

GCM經(jīng)常被用作為一個(gè)觸發(fā)器,它告訴移動(dòng)應(yīng)用向服務(wù)器發(fā)起鏈接并更新數(shù)據(jù)。在GCM中,可以(也推薦)在新消息要替代舊消息時(shí),使用可折疊的消息(Collapsible Messages)。我們用體育比賽作為例子,如果你向所有用戶發(fā)送了一條包含了當(dāng)前比賽比分的消息,15分鐘之后,又發(fā)送了一條消息更新比分,那么第一條消息就沒(méi)有意義了。對(duì)于那些還沒(méi)有收到第一條消息的用戶,就沒(méi)有必要將這兩條消息全部接收下來(lái),何況如果要接收兩條消息,那么設(shè)備不得不進(jìn)行兩次響應(yīng)(比如對(duì)用戶發(fā)出通知或警告),但實(shí)際上兩條消息中只有一條是重要的。

當(dāng)你定義了一個(gè)折疊Key,此時(shí)如果有多個(gè)消息在GCM服務(wù)器中,以隊(duì)列的形式等待發(fā)送給同一個(gè)用戶,那么只有最后的那一條消息會(huì)被發(fā)出。對(duì)于之前所說(shuō)的體育比分的例子,這樣做能讓設(shè)備免于處理不必要的任務(wù),也不會(huì)讓設(shè)備對(duì)用戶造成太多打擾。對(duì)于其他的一些場(chǎng)景比如與服務(wù)器同步數(shù)據(jù)(檢查郵件接收),這樣做的話可以減少設(shè)備需要執(zhí)行同步的次數(shù)。例如,如果有10封郵件在服務(wù)器中等待被接收,并且有10條GCM消息發(fā)送到設(shè)備提醒它有新的郵件,那么實(shí)際上只需要一個(gè)GCM就夠了,因?yàn)樵O(shè)備可以一次性把10封郵件都同步了。

為了使用這一特性,只需要在你要發(fā)出的消息中添加一個(gè)消息折疊Key。如果你在使用GCM helper library,那么就使用Message類的collapseKey(String key)方法。

Message message = new Message.Builder(regId)
    .collapseKey("game4_scores") // The key for game 4.
    .ttl(600) // Time in seconds to keep message queued if device offline.
    .delayWhileIdle(true) // Wait for device to become active before sending.
    .addPayload("key1", "value1")
    .addPayload("key2", "value2")
    .build();

如果你沒(méi)有使用GCM helper library,那么就直接在你要構(gòu)建的POST頭部中添加一個(gè)字段。將collapse_key作為字段名,并將Key的名稱作為該字段的值。

在GCM消息中嵌入數(shù)據(jù)

通常, GCM消息被用作為一個(gè)觸發(fā)器,或者用來(lái)告訴設(shè)備,在服務(wù)器或者別的地方有一些待更新的數(shù)據(jù)。然而,一條GCM消息的大小最大可以有4kb,因此,有時(shí)候可以在GCM消息中放置一些簡(jiǎn)單的數(shù)據(jù),這樣的話設(shè)備就不需要再去和服務(wù)器發(fā)起連接了。在下列條件都滿足的情況下,我們可以將數(shù)據(jù)放置在GCM消息中:

  • 數(shù)據(jù)的總大小在4kb以內(nèi)。
  • 每一條消息都很重要,且需要保留。
  • 這些消息不適用于消息折疊的使用情形。

例如,短消息或者回合制網(wǎng)游中玩家的移動(dòng)數(shù)據(jù)等都是將數(shù)據(jù)直接嵌入在GCM消息中的例子。而電子郵件就是反面例子了,因?yàn)殡娮余]件的數(shù)據(jù)量一般都大于4kb,而且用戶一般不需要對(duì)每一封新郵件都收到一個(gè)GCM提醒的消息。

同時(shí)在發(fā)送多播消息時(shí),也可以考慮這一方法,這樣的話就不會(huì)導(dǎo)致大量用戶在接收到GCM的更新提醒后,同時(shí)向你的服務(wù)器發(fā)起連接。

這一策略不適用于發(fā)送大量的數(shù)據(jù),有這么一些原因:

  • 為了防止惡意軟件發(fā)送垃圾消息,GCM有發(fā)送頻率的限制。
  • 無(wú)法保證消息按照既定的發(fā)送順序到達(dá)。
  • 無(wú)法保證消息可以在你發(fā)送后立即到達(dá)。假設(shè)設(shè)備每一秒都接收一條消息,消息的大小限制在1K,那么傳輸速率為8kbps,或者說(shuō)是1990年代的家庭撥號(hào)上網(wǎng)的速度。那么如此大量的消息,一定會(huì)讓你的應(yīng)用在Google Play上的評(píng)分非常尷尬。

如果恰當(dāng)?shù)厥褂?,直接將?shù)據(jù)嵌入到GCM消息中,可以加速你的應(yīng)用的“感知速度”,因?yàn)檫@樣一來(lái)它就不必再去服務(wù)器獲取數(shù)據(jù)了。

智能地響應(yīng)GCM消息

你的應(yīng)用不應(yīng)該僅僅對(duì)收到的GCM消息進(jìn)行響應(yīng)就夠了,還應(yīng)該響應(yīng)地更智能一些。至于如何響應(yīng)需要結(jié)合具體情況而定。

不要太過(guò)激進(jìn)

當(dāng)提醒用戶去更新數(shù)據(jù)時(shí),很容易不小心從“有用的消息”變成“干擾消息”。如果你的應(yīng)用使用狀態(tài)欄通知,那么應(yīng)該更新現(xiàn)有的通知,而不是創(chuàng)建第二個(gè)。如果你通過(guò)鈴聲或者震動(dòng)的方式提醒用戶,一定要設(shè)置一個(gè)計(jì)時(shí)器。不要讓?xiě)?yīng)用每分鐘的提醒頻率超過(guò)1次,不然的話用戶很可能會(huì)不堪其擾而卸載你的應(yīng)用,關(guān)機(jī),甚至把手機(jī)扔到河里。

用聰明的辦法同步數(shù)據(jù),別用笨辦法

當(dāng)使用GCM告知設(shè)備有數(shù)據(jù)需要從服務(wù)器下載時(shí),記住你有4kb大小的數(shù)據(jù)可以和消息一起發(fā)出,這可以幫助你的應(yīng)用做出更智能的響應(yīng)。例如,如果你有一個(gè)支持訂閱的閱讀應(yīng)用,而你的用戶訂閱了100個(gè)源,那么這就可以幫助你的應(yīng)用更智能地決定應(yīng)該去服務(wù)器下載什么數(shù)據(jù)。下面的例子說(shuō)明了在GCM載荷中可以發(fā)送什么樣的數(shù)據(jù),以及設(shè)備可以做出什么樣的反應(yīng):

  • refresh - 你的應(yīng)用被告知向每一個(gè)源請(qǐng)求數(shù)據(jù)。此時(shí)你的應(yīng)用可以向100個(gè)不同的服務(wù)器發(fā)起獲取訂閱內(nèi)容的請(qǐng)求,或者如果你在服務(wù)器上有一個(gè)聚合服務(wù),那么可以只發(fā)送一個(gè)請(qǐng)求,將100個(gè)源的數(shù)據(jù)進(jìn)行打包并讓設(shè)備獲取,這樣一次性就完成更新。
  • refresh, freshID - 一種更好的解決方案,你的應(yīng)用可以有針對(duì)性的完成更新。
  • refresh, freshID, timestamp - 三種方案中最好的,如果正好用戶在收到GCM消息之前手動(dòng)做了更新,那么應(yīng)用可以利用時(shí)間戳和當(dāng)前的更新時(shí)間進(jìn)行對(duì)比,并決定是否有必要執(zhí)行下一步的行動(dòng)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)