close

ANDROID 的推播功能實作


Android 的推播功能實作

本篇將會先對推播做簡單介紹,後續有server端及client端實作範例。

什麼是推播?
當我們在使用行動裝置上的應用程式時,若剛好有簡訊傳送進來,這時就會發現手機上方會有通知告訴使用者有新的簡訊進來,這種通知的方式便稱為推播,因此現在有許多的App都將推播通知視為是一種必備的功能,例如當App推出更新版或是在做什麼優惠的時候,便可以利用這種推播方式來通知使用者。


這種推播的技術在ios平台上叫做APNS(Apple Push Notification Service),而Android平台上則叫做GCM(Google Cloud Messaging),接下來就來講講GCM的運作流程:

1.App跟Google GCM Server註冊
首先我們開發的手機App必須先跟Google GCM Server註冊,這邊會傳送Sender ID,告訴GCM Server現在是哪個人要來使用這GCM服務。 

2.GCM Server回傳Reg ID
手機上的App註冊成功後GCM Server會丟回一個Reg ID給App,這個Reg ID就是要給我們等一下架設的第三方Server識別所用,這樣我們在發送訊息的Server端才能知道這訊息要發送給哪些手機裝置。

3.App跟我們架設Server註冊
這邊當然是要先架設發送訊息的主控Server,透過下方的說明中跟Google Service拿到的API Key,取得使用GCM服務的許可。剛剛App拿到Reg ID後,必須傳送到我們架設發送訊息的Server,並且把它存起來,當然如果App要丟其他的東西過來Server也是可以。

4.我們架設Server發送訊息
我們架設的Server要發送訊息,必須透過Google GCM Service,所以要跟它說你要丟給誰,也就是API Key、Reg ID以及Message。

5.Google GCM Service發送訊息
一旦我們的Server請求GCM發送時,它並不保證多久會送達、會不會miss、也不保證訊息的順序,所以接下來就必須等待GCM傳送訊息到擁有這Reg ID的手機上了。


實作前準備

1.先到https://cloud.google.com/console/project建立專案


2.將所產生的Project Number記下來
3.點擊進入剛剛所建立的專案裡,點選API 與驗證>API,找到Google Cloud Messaging for Android並選擇開啟


4.接著點選API 與驗證>憑證,在公開API存取的地方選擇建立新的金鑰>伺服器金鑰,且把所產生的金鑰給紀錄下來。


Server端實作
//發送推播,請自行加入觸發條件
private SendGCM ()
{
string BrowserAPIKey = "這裡請輸入剛剛申請的API Key";
string message = "這裡請輸入您所要傳送的訊息";
string tickerText = "example test GCM";
string contentTitle = "content title GCM";
string postData = "{ \"registration_ids\": [ \"" + 這裡請填入要傳送的裝置ID + "\" ], \"data\": {\"tickerText\":\"" + tickerText + "\", \"contentTitle\":\"" + contentTitle +"\", \"message\": \"" + message + "\"}}";
string response = SendGCMNotification(BrowserAPIKey, postData);
string reponse = response;
}

//GCM功能
private string SendGCMNotification(string apiKey, string postData, stringpostDataContentType = "application/json")
{
ServicePointManager.ServerCertificateValidationCallback += newRemoteCertificateValidationCallback(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))
{
    error = "Unauthorized - need new token";

}
else if (!ResponseCode.Equals(HttpStatusCode.OK))
{
    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)
    {
error = e.ToString();
    }
return error;
}

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


}


App端實作

1.先打開Android SDK Manager後,下載要執行的Android版本的Google APIs

2.接著再下載Extras>Google Cloud Messaging for Android Library



3.下載安裝完成後請到你Android SDK的安裝目錄底下的/extras/google/gcm/ gcm-client/dist/,找到gcm.jar然後把他複製到專案底下的libs資料夾底下



AndroidManifest.xml
請將底下的PackageName換成自己的專案名稱
<?xml version="1.0" encoding="utf-8"?>
    package="PackageName"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
<permission android:name="PackageName.permission.C2D_MESSAGE"android:protectionLevel="signature" />
<uses-permission android:name="PackageName.permission.C2D_MESSAGE" />
<!-- 接收 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" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="PackageName.MainActivity"
            android:label="@string/app_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" />
    <category android:name="PackageName" />
  </intent-filter>
</receiver>
<!-- 繼承自 GCMBaseIntentService 的類別, 若由 GCMBroadcastReceiver 呼叫則不能改類別名 -->
<service android:name=".GCMIntentService" />
    </application>

</manifest>


GCMIntentService.java
接著請新增GCMIntentService
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gcm.GCMBaseIntentService;

/**
 * {@link IntentService} responsible for handling GCM messages.
 */
public class GCMIntentService extends GCMBaseIntentService {

@SuppressWarnings("hiding")
private static final String TAG = "GCMIntentService";

public GCMIntentService() {
super("這裡請輸入剛剛申請的API的專案編號(Project Number)");
}

private static void generateNotification(Context context, String message) {
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, message, when);
//這裡可以設定推播通知的icon
String title = "Hunger TV";
//這裡可以設定推播通知的標題
Intent notificationIntent = new Intent(context, NowList.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");
// Get the data from intent and send to notificaion bar
generateNotification(arg0, arg1.getStringExtra("message"));
}

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

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

}


Main.java
在你的主程式當中加入setGCM這支副程式,並且讓程式在onCreate的時候去執行它
private void setGCM()
{
//推播用
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
if (GCMRegistrar.isRegistered(this)) {
Log.d("info", GCMRegistrar.getRegistrationId(this));
}
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
GCMRegistrar.register(this, "這裡請輸入剛剛申請的API的專案編號(Project Number)");
Log.d("info", GCMRegistrar.getRegistrationId(this));
} else {
Log.d("info", "already registered as" + regId);
//這裡的regId就是前面server端所需的裝置ID
}


}


arrow
arrow
    創作者介紹
    創作者 Johnson峰 的頭像
    Johnson峰

    Johnson峰的部落格

    Johnson峰 發表在 痞客邦 留言(0) 人氣()