以下圖片畫面僅供參考,畫面會隨Google改版而有所變更。

 

1. 申請Key和ProjectID的網址

https://console.developers.google.com


 

2. 取得 金鑰

   專案 -> 憑證 

   新增憑證 -> API 金鑰 -> 伺服器金鑰

   推播需建立伺服器憑證

   此金鑰是推播訊息發送端使用的。

 

151013001  

 


 

3. 取得專案編號 ProjectID 

    專案 -> 首頁 -> 右手邊區塊的ID後面的數字編號

    也就是下圖紅框內的數字(不同的專案,會有不同的ID)

    此ID是推播訊息接收端使用的,也就是要打入Android程式碼中的編號

    151013002  

 


 

4. Android 程式

   AndroidManifest.xml

<!-- 開網路 -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- 接收 GCM 用 -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- 用來連接到 Google Services -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 需要使用 Google 帳戶資訊(4.0.4以下版本需要使用者帳戶) -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- 收到訊息時保持 CPU 休眠 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- 紅色部份,請換成 package name -->
<permission android:name="com.app.name.permission.C2D_MESSAGE" android:protectionLevel="signature" /><uses-permission android:name="com.app.name.permission.C2D_MESSAGE" />

 

<application>

<activity android:name="..............................">

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>

<!-- 允許 GCMBroadcastReceiver 接收處理來自 GCM 所 SEND 出來的 RECEIVE 跟 REGISTRATION 這兩個 Intent -->
<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" />
<!-- 紅色部份,請換成 package name -->
<category android:name="com.app.name" />
</intent-filter>
</receiver>

<!-- 繼承自 GCMBaseIntentService 的類別, 若由 GCMBroadcastReceiver 呼叫則不能改類別名 -->
<service android:name=".GCMIntentService" />

</application>


 

5. Android程式 手機訊息設定

建立 GCMIntentService.java

package com.app.name;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.app.name.R;
import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

public GCMIntentService() {

super( ProjectID );

}

@SuppressWarnings("deprecation") //沒加會有警告訊息
private static void generateNotification(Context context, String message) {
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

 

//這裡可以設定推播通知的icon
Notification notification = new Notification(R.drawable.appicon, message, when);

//這裡可以設定推播通知的標題
String title = Title; 

//這裡可以設定當點選推播通知的時候要開起哪支程式
Intent notificationIntent = new Intent(context, MainActivity.class);


notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}

protected void onError(Context arg0, String arg1) { }

protected void onMessage(Context arg0, Intent arg1) {
Log.d("GCM", "RECIEVED A MESSAGE");
generateNotification(arg0, arg1.getStringExtra("message"));
}

protected void onRegistered(Context arg0, String arg1) { }

protected void onUnregistered(Context arg0, String arg1) { }
}

 


 

6. Android程式 手機註冊

    手機註冊取回Google Token,並登錄 ProjectID

    (1)需搭配Thread使用

    (2)不會100%成功,所以需搭配迴圈或遞迴來重覆執行

//取得Google token

private String Token = "";

private void getRun()
{
Message msg2 = new Message ( ) ;
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
if (GCMRegistrar.isRegistered(this)) {
  Log.d("info", GCMRegistrar.getRegistrationId(this));
}

try
{
  //目前失敗最高七次,取回空白
  Token = GCMRegistrar.getRegistrationId(this);

 
//Thread 使用註記
  msg2.what = GUI_OK2;
  MainActivity.this.myMessageHandler.sendMessage ( msg2 ) ; 

}
catch(Exception e)
{
  Toast.makeText(MainActivity.this, "Ex."+ e.getMessage(), Toast.LENGTH_LONG).show();
}

if (Token.equals("")) {
  //將步驟3取得的ProjectID,放進來
  GCMRegistrar.register(this, ProjectID ); 
  Log.d("info", GCMRegistrar.getRegistrationId(this));
} else {
  Log.d("info", "already registered as" + Token);
}
//這裡的regId就是前面server端所需的裝置ID
}


 

7.  把取到的Token記錄,想辦法存到資料庫,並且和使用者帳號有關連。


 

8.  編寫伺服器端的發送程式

using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;

namespace PUSH
{
public static class AndroidGSM
{

private static string BrowserAPIKey = "AIzaSyCviYfVwvXXXXXXXXXXXXXXXXXXXXXXXE"; // Server App key
private static string tickerText = "ProjectTestGCM"; //registration_ids http ticker
private static string contentTitle = "ProjectTestGCM"; //registration_ids http title
//private static string sSource_sms = "APP_ProjectTest";

/// <summary>
/// Android 推播程式
/// </summary>
/// <param name="token"></param>
/// <param name="msg"></param>
public static void SendAndroid(string token, string msg)
{
RunSend(token, msg);
}

/// <summary>
/// Android 推播解析
/// </summary>
/// <param name="id">這裡請填入要傳送的裝置ID</param>
private static void RunSend(string id, string message)
{
/*
* { "registration_ids": [ "{0}" ], "data": {"tickerText":"{1}", "contentTitle":"{2}", "message": "{3}"}}
*/

string response = "";
string postData =
"{ \"registration_ids\": [ \""
+ id + "\" ], \"data\": {\"tickerText\":\""
+ tickerText + "\", \"contentTitle\":\""
+ contentTitle + "\", \"message\": \""
+ message + "\"}}";

//十次機會,如果十次都錯,那就放棄發送吧!
for (int i = 0; i < 10; i++)
{
  response = "";
  string err = "";

  response = SendGCMNotification(BrowserAPIKey, postData, out err);
  if (err.Length == 0)
  {
    break;
  }
  else
  {
    Thread.Sleep(500); //回傳錯誤,暫停0.5秒
    Console.Write(" ...");
  }
}

Console.WriteLine(response);
}

/// <summary>
/// Android GCM功能
/// </summary>
/// <param name="apiKey"></param>
/// <param name="postData"></param>
/// <param name="ermsg"></param>
/// <param name="postDataContentType"></param>
/// <returns></returns>
private static string SendGCMNotification(string apiKey, string postData, out string ermsg, string postDataContentType = "application/json")
{
ermsg = "";
ServicePointManager.ServerCertificateValidationCallback
+= new RemoteCertificateValidationCallback(ValidateServerCertificate);

// MESSAGE CONTENT
byte[] byteArray = Encoding.UTF8.GetBytes(postData);

// CREATE REQUEST
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
Request.Method = "POST";
Request.KeepAlive = false;
Request.ContentType = postDataContentType;
Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
Request.ContentLength = byteArray.Length;

Stream dataStream = Request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

// SEND MESSAGE
string error = "";
try
{
WebResponse Response = Request.GetResponse();
HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
{
ermsg = error = "Unauthorized - need new token";
}
else if (!ResponseCode.Equals(HttpStatusCode.OK))
{
ermsg = error = "Response from web service isn't OK";
}

StreamReader Reader = new StreamReader(Response.GetResponseStream());
string responseLine = Reader.ReadToEnd();
Reader.Close();

return responseLine;
}
catch (Exception e)
{
ermsg = error = e.ToString();
}
return error;
}

public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}

}
}


 

9.  完成。

 

 


 

 

{   "registration_ids": [ "{0}" ] , "data": {"tickerText":"{1}", "contentTitle":"{2}", "message": "{3}"}}

同一訊息,要同時傳送給n個行動裝置時

針成上面的 JSON 中的 registration_ids 去修改 ( 一次上限1000個 )

例如:

一個行動裝置時:

 "registration_ids": [ "A0001" ]

 

兩個行動裝置時

 "registration_ids": [ "A0001" , "A0002" ]

 

多個行動裝置時

 "registration_ids": [ "A0001" , "A0002".... "A000n" ]

 

 


 

 

{

"registration_ids": [

"APA91bGcMdbuJ3ghvRNpvUhL69MMag2uofIMnWSbPeVUpts17a6DTDnZmxcMAuRK6vn34AUb9gNiJ74cM-Y1_Lw7BZkwBhqM3oRyz6Z98HYxWymhuO_SdAsavYM9JtodPLEC02zbaJBD"

,

"APA91bHBib2OQ0RSPknW2xKxm3p2aK7R9sUP0CFcMGFgX9pi1r6FEQRlaAOcvJa_FWdgIl-OrY-nSBrYD7jqRFULae1bhW06F_QMc7czHdEwj7KaC9vfa75XIZYFvDTnHTcaQbpEfXWB"

],

"data": {"tickerText":"ticker", "contentTitle":"title", "message": "測試訊息"}

}

 

上面的是同時發送給兩個行動裝置的完整JSON

 


 

 

{

"multicast_id":9999992091979545599,

"success":2,

"failure":0,

"canonical_ids":0,

"results":[

{"message_id":"0:9495592993591952%ba5925e9f9fd9ecd"},       {"message_id":"0:9495592993590356%ba5925e9f9fd9ecd"}

]

}

上面是由上面測試的JSON,,同時發送給兩個行動裝置

由GOOGLE回傳兩個都成功的結果

 


 

 

{

"multicast_id":9999992091979545599,"

success":1,

"failure":1,

"canonical_ids":0,

"results":[

{"message_id":"0:1447573717077899%ba7327e2f7fd7ecd"},

{"error":"InvalidRegistration"}

]

}

 

上面是由上面測試的JSON,同時發送給兩個行動裝置

由GOOGLE回傳一個成功,一個失敗的結果

 

 

 

 

arrow
arrow
    全站熱搜

    Jiang Ying-Fu 發表在 痞客邦 留言(0) 人氣()