GCM:入門
此文描述了如何使用GCM提供的輔助庫(客戶端和服務器)來編寫一個Android應用程序和服務器端的邏輯。
創建一個谷歌API項目
要創建一個谷歌API項目:
- 打開谷歌API的控制台頁面。
- 如果你還沒有創建一個API項目,這個頁面會提示你這樣做:
注:如果您已經有項目,你看到的第一頁將是儀表板頁面。從那里你可以通過打開項目的下拉菜單(左上角),並選擇Other>Create一個新的項目。
- 點擊創建項目。你的瀏覽器URL將會改成這樣的:
https://code.google.com/apis/console/#project:4815162342
-
注意#project:后面的值:(示例中的4815162342)。這是你的項目ID,並且后面會用作GCM發件人的ID。
啟用GCM服務
為了啟用GCM服務:
- 在谷歌API的控制頁面的主頁中,選擇服務。
- 切換Google Cloud Messaging按鈕的狀態為ON。
- 在服務條款頁面中接受這些條款。
獲取一個API密鑰
為了獲取一個API密鑰:
- 在谷歌API控制台主頁面中,選擇API Access。你將會看到一個類似於以下內容的頁面:

2. 點擊Create new Server key。會出現以下頁面:

3. 點擊 Create:

請注意在這個示例中API key 的值(YourKeyWillBeShownHere
),它稍后會被用到。
注:如果你想換掉這個密鑰,請點擊Generate new key。一個新的密鑰就會創建,而之前的密鑰在未來24內仍然有效。如果你想讓之前的密鑰立即失效(例如:你認為它已經被破解了),請點擊Delete key。
安裝輔助庫
在執行下面章節描述的步驟之前,請確保已經安裝好輔助庫(參考:客戶端和服務器)。打開Android SDK Manager,安裝Extras > Google Cloud Messaging for Android Library。這會在YOUR_SDK_ROOT/extras/google/目錄下創建一個gcm文件夾,gcm文件夾下包含:
gcm-client
,gcm-demo-appengine
, gcm-demo-client
, gcm-demo-server
, and gcm-server子目錄。
注:SDK Manager版本要求r20以上,之前的版本發現不了GCM庫。所以先打開eclipse升級ADT。
開始編寫Android程序
此章節描述了用GCM編寫Android程序的步驟。
步驟 1:拷貝gcm.jar到程序的classpath目錄下
在編寫程序之前,請先拷貝SDK目錄下gcm-client/dist目錄下的gcm.jar文件到程序的classpath。
步驟 2:按照以下步驟更改項目的AndroidManifest.xml文件
1. GCM需要Android2.2或更高版本,所以如果你的程序不依賴GCM就無法正常工作,那么請在AndroidManifest文件中添加以下內容,“xx”處替換為最新的目標SDK版本號:
<uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="xx"/>
2. 聲明並使用一個自定義的權限以此來確保只有這個程序可以接收你的GCM消息:
<permissionandroid:name="my_app_package.permission.C2D_MESSAGE"android:protectionLevel="signature"/><uses-permissionandroid:name="my_app_package.permission.C2D_MESSAGE"/>
這個權限必須稱作:my_app_package.permission.C2D_MESSAG(程序包名.permission.C2D_MESSAG,程序包名就是在manifest文件中定義包名),不然將不能正常運行。
注:如果你的程序針對的是4.1或更高版本的系統(即,minSdkVersion 16),那么就不需要這個權限。
3. 添加權限接收GCM消息:
<uses-permissionandroid:name="com.google.android.c2dm.permission.RECEIVE"/>
4. 添加以下廣播接收器:
<receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <action android:name="com.google.android.c2dm.intent.REGISTRATION"/> <category android:name="my_app_package"/> </intent-filter> </receiver>
這個Broadcast receiver負責處理2個從GCM發來的Intent(com.google.android.c2dm.intent.RECEIVE和com.google.android.c2dm.intent.REGISTRATION),並且要在manifest文件中定義(而非通過編碼實現)。因此,這些Intent甚至可以在程序未運行的情況下被接收到。通過設置com.google.android.c2dm.permission.SEND權限,可以確保這些Intent只能通過GCM系統框架發送到這個receiver(普通程序是沒有權限發出這些Intent的)。
注意在category標簽里的android:name必須替換成你程序的包名(如果程序是針對16或更高的minSdkVersion的平台那么就不需要有category這個標簽了)。
5. 添加以下Intent服務:
<service android:name=".GCMIntentService"/>
在下一步中,這個Intent服務會被GCMBroadcastReceiver(由GCM庫提供)調用。它必須稱作my_app_package.GCMIntentService,除非你用重寫了GCMBroadcastRecevier方法的子類來作為此服務的名字。
步驟 3:實現my_app_package.GCMIntentService類
下面來實現my_app_package.GCMIntentService類,重寫下面的幾個回調方法(這些方法會被GCMBroadcastReceiver調用):
onRegistered(Context context, String regId)
: 收到注冊Intent后此方法會被調用,GCM分配的注冊ID會做為參數傳遞到設備/應用程序對。通常,你應該發送regid到你的服務器,這樣服務器就可以根據這個regid發消息到設備上。onUnregistered(Context context, String regId)
: 當設備從GCM注銷時會被調用。通常你應該發送regid到服務器,這樣就可以注銷這個設備了。onMessage(Context context, Intent intent)
: 當你的服務器發送了一個消息到GCM后會被調用,並且GCM會把這個消息傳送到相應的設備。如果這個消息包含有效負載數據,它們的內容會作為Intent的extras被傳送。onError(Context context, String errorId)
: 當設備試圖注冊或注銷時,但是GCM返回錯誤時此方法會被調用。通常此方法就是分析錯誤並修復問題而不會做別的事情。onRecoverableError(Context context, String errorId)
: 當設備試圖注冊或注銷時,但是GCM服務器無效時。GCM庫會使用應急方案重試操作,除非這個方式被重寫並返回false。這個方法是可選的並且只有當你想顯示信息給用戶或想取消重試操作的時候才會被重寫。
注: 上面的方法運行在Intent服務的線程里,因此可以自由訪問網絡而不會阻塞UI線程。
步驟 4:實現你程序的主Activity
在你程序的主activity里添加下面的導入語句:
import com.google.android.gcm.GCMRegistrar;
在onCreate()方法里添加下面的代碼:
GCMRegistrar.checkDevice(this); GCMRegistrar.checkManifest(this); final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("")) { GCMRegistrar.register(this, SENDER_ID); } else { Log.v(TAG, "Already registered"); }
checkDevice()方法用來驗證設備是否支持GCM,如果不支持會拋出異常(例如,模擬器就不包含Google APIs)。相似地,checkManifest()方法來驗證程序的manifest包含了在開始編寫Android程序中所有符合要求的描述(這個方法只有你在開發程序的時候需要;一旦這個程序准備發布的時候,你就可以把它移除掉)。
一旦這些健康檢查做完了,就可以調用GCMRegsistrar.register()通過傳送注冊GCM時得到的SENDER_ID來注冊設備了。但是由於GCMRegistrar單例保持跟蹤所有收到的注冊Intent的注冊ID,所以可以先調用GCMRegistrar.getRegistrationId()方法檢查此設備是否已經注冊。
注:可能設備已經成功注冊到GCM,但是沒有成功發送注冊ID到你的服務器,這種情況你應當重試。請查看高級主題來了解處理這種情況的更多詳情。
編寫服務端程序
編寫服務器程序請做如下准備:
- 拷貝SDK的gcm-server/dist目錄下的gcm-server.jar到你服務器的classpath。
- 創建一個servlet(或其它服務器端機制),被Android程序用來發送從GCM收到的注冊ID。Android程序可能也要發送一些其它的信息,例如用戶的email地址或用戶名,這樣服務器就可以對注冊ID和用戶設備進行關聯。
- 相似地,創建一個servlet用來注銷注冊ID。
- 當服務器需要發送一條消息到設備時,可以使用GCM庫中的com.google.android.gcm.server.Sender輔助類。例如:
import com.google.android.gcm.server.*; Sender sender = new Sender(myApiKey); Message message = new Message.Builder().build(); MulticastResult result = sender.send(message, devices, 5);
上面的代碼段實現了如下工作:
- 用你項目的API key創建一個Sender對象。
- 用獲得的注冊ID來創建一個消息(消息的構建者也要有方法來設置全部的消息參數,例如collapse key和有效負載數據)。
- 發送這個消息(如果GCM服務器無效的話,有5次重發機會),並保存響應給result。
現在就需要解析響應結果並對如下情況采取適當的措施:
- 如果消息被創建了,但是結果返回了一個被認可的注冊ID,那么需要用這個認可的ID替換當前的注冊ID。
- 如果返回的錯誤是NotRegistered,那么需要移除這個注冊ID,因為那個設備沒有安裝此程序。
這有一個代碼段來處理這兩種情況:
if (result.getMessageId() != null) { String canonicalRegId = result.getCanonicalRegistrationId(); if (canonicalRegId != null) { // same device has more than on registration ID: update database } } else { String error = result.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from device - unregister database } }