※ GCM 註冊流程請參考上篇 push notification - android client 以 GCM 實現 (一)
Client 流程
1. 打開 Android SDK 下載 Google Play Services
2. 將下面檔案複製到 workspace 中,然後 import 至 eclipse,並設定為 library
C:\android-sdk目錄\extras\google\google_play_services\libproject\google-play-services_lib
3. 新建專案並引入上述的 library
4. 在 AndroidManifest.xml 中加入下列權限
<!-- 使用GCM -->
<permission
//com.example.gcmtest 為 package name
android:name="com.example.gcmtest.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcmtest.permission.C2D_MESSAGE" />
<!-- 存取 internet -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
5. 跟 Google GCM Server 註冊,取得 regId
GoogleCloudMessaging gcm = GoogleCloudMessaging
.getInstance(context);
String registerid = "";
Log.i(ConfigUtil.TAG, "registerGCM package id:" + ConfigUtil.SENDER_ID);
try {
registerid = gcm.register(ConfigUtil.SENDER_ID);
} catch (IOException e) {
e.printStackTrace();
}
Log.i(ConfigUtil.TAG, "registerGCM regId:" + registerid); //取得的 regId
if(!registerid.equals("")){
registerGCM(registerid);
}
※ GCM Server 回傳 RegID
6. 將 RegID 傳給自己的 server 儲存
7. Server 發送訊息到 Google GCM Server ( 實作部分稍後解說 )
8. 在 AndroidManifest.xml 中註冊接收 GCM Broadcast
7. Server 發送訊息到 Google GCM Server ( 實作部分稍後解說 )
8. 在 AndroidManifest.xml 中註冊接收 GCM Broadcast
<!-- 接收 GCM 的 receiver -->
<receiver
android:name="com.example.gcmtest.receiver.GcmBroadcastReceiver" //接收的 class 路徑
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcmtest" /> //package name
</intent-filter>
</receiver>
9. Google GCM Service 發送訊息到 Android Device,Android 以 Broadcast 接收
public class GcmBroadcastReceiver extends BroadcastReceiver {
Context ctx;
@Override
public void onReceive(Context context, Intent intent) {
Log.i(ConfigUtil.TAG, "action=" + intent.getAction());
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Log.i(ConfigUtil.TAG, "Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Log.i(ConfigUtil.TAG, "Deleted messages on server: "
+ intent.getExtras().toString());
} else {
//action = com.google.android.c2dm.intent.REGISTRATION
sendNotification(intent); //正常收到訊息
}
setResultCode(Activity.RESULT_OK);
}
}
※ client 接收到 GCM Broadcas
server 流程
- 管理 client RegID ( 儲存、刪除 )
- 發訊息到 Google GCM Server
(1) header 設定 JSON 格式,並加入 project number ( 請參考 push notification - android client 以 GCM 實現 (一) )
(2) content:設定接收端的 regId 與要傳送的訊息內容,並轉成 JSON 格式Content-Type:application/json Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA //project number
※ registrationids,data 為固定 key ( 一定要有 ),請照此規格包裝您要傳送的訊息{ "registrationids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."], //regId "data" : { "key" : "value" ... }, }
範例 ( 這裡以 java 實現 ):
List registrationIds = new ArrayList();
registrationIds.add(registerid); //client regId
MsgObj msgObj = new MsgObj();
msgObj.setMsg(et_msg.getText().toString()); //要發送的訊息
Gcmlite gcmlite = new Gcmlite();
gcmlite.setRegistration_ids(registrationIds);
gcmlite.setData(msgObj);
String paramvalue = GsonUtil.gson.toJson(gcmlite); //轉成 JSON String
Log.i(ConfigUtil.TAG, "snend:"+paramvalue);
String responseStr = "";
try {
responseStr = HttpUtil.sendMsgToGcmServer(paramvalue);
} catch (HttpHostConnectException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i(ConfigUtil.TAG, "responseStr:"+responseStr);
Error
GCM response status
- 200:success
- 400:JSON passing error or contained invalid fields
- 401:API key is not valid
- 5xx:GCM server is temporarily unavailable(timeouts..). honoring any Retry-After header included in the response.Sender must retry later
GCM success response body
- multicast_id:Broadcast uuid
- success:成功數量
- failure:失敗數量
- canonical_ids
- results
- message_id:message uuid? I'm not sure.
- registration_id:訊息已成功發送,不過 client 的 registration ID 已經更換,server 需要 replace id,不更換的話之後 client 可能無法收到 Broadcast
※ 如果 GCM 要改變 registration ID,GCM 會在發送個通知給 Android Application,client 會自動處理 - error
- Unavailable:GCM servers 忙碌中,稍後可嘗試重新 send msg
- NotRegistered:client 已經移除 app,或 app 不接收 "com.google.android.c2dm.intent.RECEIVE" intents 的 broadcast,所以您必須將 registration ID 從 DB 中移除
- 其他 error response
※ 如果 failure 與 canonical_ids 都是 0,則不需要再查看其他 response
References
範例下載 ( 測試時請記得將 ConfigUtil 中 SERVER_URL, SENDER_ID, API_KEY 換掉 )
沒有留言:
張貼留言