close
ANDROID 的推播功能實作
星期六, 3月 29, 2014 from http://blog.jeremyhuang.com/2014/03/android_29.htm...
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端實作
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
}
}
文章標籤
全站熱搜
留言列表