23 March 2012
這篇是舊版的,已經被deprecated,新版為GCM,新版的實作請看
新版的Server篇





最後一篇進入到了Android C2DM的coding了!!
哈! 這篇存在草稿也三個月了..........
今天終於有一點點時間來修改!


第一篇在講參數說明
第二篇在講流程說明
這篇專注於server端的實作
下一篇才會專注於android端的實作




OK,
在coding之前,請先去Google官網註冊你的app
比較要注意的是下面兩項
  1. Package name of your Android app *
  2. Role (sender) account email *
第1項,是指你的Android app的package name,這裡一定要填對,不然C2DM Server不知道送到哪個app去。
第2項,是指用來傳遞訊息的帳號,也就是開發者的帳號,這裡的建議是不要用個人帳號,建議新申請另一個帳號來使用。

完成上面註冊動作以後,就可以開始coding了!
網路上的code教學都是拿Google官網上面放的範例(JumpNote)
我覺得這樣不太native,畢竟這是別人寫的app!
所以我直接講最基本的流程!


接下來的code大概會分成下面幾種:

  1. 實作Server端:使用Google Client Login API取得Auth token,並且存起來。
  2. 實作Server端:Sending Message to C2DM Server。
  3. Android端:基本的設定。
  4. Android端:向C2DM 註冊,並且取得registration id。
  5. Android端:傳送 Registration Id 到我們的Server

因為其實有點多,所以就分成兩篇來打,
一篇為Sever篇,就是此篇!
另一篇為Android篇,就是下篇!

【1.  使用Google Client Login API取得Auth token 】

因為得把token傳至C2DM Server,
C2DM Sever才知道你有登入,且是合格的。

至於Google Client Login API的流程在這就不贅述,
就直接實做! 但大家可以去Google Client Login API官網看!!!

這裡我是架在Google App Engine上,把GAE當作我們的Sever。
由於auth token可以重複使用,
所以我們可能可以每段時間去執行ClientLogin,
並取得auth token!
這時候就可以用GAE的cron,可能設定每天去登入一次以取得token。

而Client Login的code如下:
String strClientLoginUrl = "https://www.google.com/accounts/ClientLogin"; // client login的url
String strAccountType = "accountType=HOSTED_OR_GOOGLE&";// 你要登入的帳號型態,這裡就輸入HOSTED_OR_GOOGLE
String strEmail = "Email=test@gmail.com&"; // 你的email!!
String strPasswd= "Passwd=123456&"; // 你的密碼
String strService= "service=ac2dm&"; // 你登入以後,要拿這token存取Google哪個Service,這裡是ac2dm
String strSource= "source=KenYang-AndroidC2DM-1.0";// 這個只是用來identify你的application,格式要companyName-applicationName-versionID


HttpURLConnection conn = (HttpURLConnection) new URL(strClientLoginUrl).openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST"); // 設定request Method為POST
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");


// 送出資料
OutputStream out = conn.getOutputStream();
String strPostData = strAccountType+strEmail+strPasswd+strService+strSource;
out.write(strPostData.getBytes());
out.close();

// 取得response code,成功的話就是200
resp.getWriter().println(conn.getResponseCode()+ "</br>");

// 把資料讀進來並且印出來
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
String strLine = "";
while((strLine=reader.readLine())!=null){
resp.getWriter().println(strLine+"</br>");
}




正常來說,如果你帳號沒有問題,
或者密碼沒有輸入錯誤,
或者的確有這帳號存在!
那麼response code會是200!
就代表登入成功!
此時就要取得auth token。

印出來的資料如下:
SID=DQAAAGgA...7Zg8CTN
LSID=DQAAAGsA...lk8BBbG
Auth=DQAAAGgA...dk3fA5N

這時候,只要取得最後那一行資料即可!
就是Auth那一行!!!
然後把Auth存起來!
這裡我是先存在GAE的datastore!
以利待會使用!




【2.  傳送資料至C2DM Server 】

至於傳送甚麼資料,可以來這官網看詳細參數說明!
這邊就簡單地說明幾種"必需"的參數!

  1. registration_id :android 裝置的id,一定要傳這資料給C2DM Server,C2DM才知道訊息要傳給誰,至於這個值,是來自android device的!
  2. collapse_key :這個value可以是隨意的值,這個參數的用意是怕android device的狀態是離線狀態,一旦狀態恢復為連線,避免使用者突然收到大量訊息!(這個參數可以每次都不一樣,也可以每次都一樣)
  3. data.<key> :這個參數就是你要傳給android device的訊息了! 型態為key-value。如data.keyName=value
  4. GoogleLogin auth :這個不是要post的參數,而是要送出的header值! 而值就是上面存在datastore裡面的Auth!



實際的code如下:
String strSendUrl = "https://android.apis.google.com/c2dm/send";  // c2dm的url
String strRegistrationId = "registration_id="+req.getParameter("device_token")+"&"; // 接收來自android傳來的參數
String strCollapse= "collapse_key=1&"; // 這個參數上面說明了
String strAuth = "xxxxxx"; // 從datastore撈出來的值,這裡就不寫有關datastore的操作了
String strData = "data.keyHello=fromKen"; // 你要送的訊息

String strPostData = strRegistrationId+strCollapse+strData;

HttpURLConnection conn = (HttpURLConnection) new URL(strSendUrl).openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Authorization", "GoogleLogin auth=" + strAuth); // 設定header
conn.setRequestProperty("Content-Length", Integer.toString(strPostData.getBytes().length)); // 告訴c2dm要傳送的資料長度

// 送出資料
OutputStream out = conn.getOutputStream();
out.write(strPostData.getBytes());
out.close();

// 看response code, 200為OK
resp.getWriter().println(conn.getResponseCode()+ "</br></br>");





完成上面的步驟,server端就完成了!
但還要完成android端,才能真正收到訊息!
下一篇會專注於android端的實作








blog comments powered by Disqus