這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務。

這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下Xamarin網站上的文章原文來了解Android GCM的運作邏輯:

Remote Notifications:An Overview of Remote Notifications in Xamarin.Android

http://docs.xamarin.com/guides/cross-platform/application_fundamentals/notifications/android/remote_notifications_in_android

1. GCM Overview

GCM(Google cloud messaging )是Google提供的一個免費的 Service,這個Service功能是在handles,sending,routing,queuing從Service 端要推播給你手機的訊息。

若你的手機要能接收從GCM傳送的訊息,你的手機上必須要有安裝Google Service Framework。Google Service Framework是在你的手機上有安裝Google Play Application的時候會自動安裝起來。在你的手機開機執行的時候,Google Service Framework會Run在背景執行程序中。然後在背景程序裡面接聽GCM傳送過來的訊息。接著它會負責將訊息反序列化給註冊在App中的Intents 或是broadcast。

 

2. GCM Requirements

  • 4kb message limit -你要推送的訊息大小不可以超過4kb。
  • Android 2.2-你的Android devices必須run在Android 2.2(API level 8)以上的版本。
  • Google Play Store – Android Devices 必須有安裝Google Play Store。如果你要在模擬器上測試GCM功能的話,模擬器上就需要有安裝Google APIs。
  • Google Account-如果你的Android Device目前run的版本低於4.0.4的話,你就需要申請一個Google Account。

3. Google Cloud Messaging in Action

3.1 App GCM註冊流程

App在一開始行時,App必須先向GCM註冊。註冊完成,GCM會回傳一個registration ID給App。

這個registration ID是你的App run在這個Android Device的唯一識別。這個App會負責傳送registration ID給Server Application。當Server Application收到了registration ID後,目前這個註冊的流程才被視為完成。

*官方是說這個registration ID不是常常更改,所以你不需要在每次App被啓用的時候都去Run這個註冊過程。

如果GCM要改變registration ID,GCM會在發送個通知給Android Application。

 

3.1 Server Application 推播訊息給Android Device流程

在Server Application要發送一個推播通知到Client端的時候,Server Application會把Message送給GCM,GCM會負責傳送這個訊息給Device。GCM允許Server Application一次指定1000個接受訊息者。

* 如果當Server嘗試要推播資訊給一個Device,而這個Device剛好是離線的狀態。(ex.關機中,收不到訊號)。

GCM會Queue著這個訊息,等到Device重新連上線時,GCM會再重新傳送這個訊息。不過GCM只會傳送近期的訊息,這個設計是為了避免一些過期的資訊或是重複性的訊息。(ex.你的Server正在推播一些限時優惠,但是使用者可能是關機的狀態,等使用者重新開機後,這個限時優惠有可能已經過期了,這時候就沒有在推播的必要。)

*如果使用者從手機上移除這個Application。但是Server application 與 GCM都還不知道這個Device上App已經被移除了。這個推播訊息會繼續被傳送到Device上。不過Google Services Framework會接收到Server Application推送過來的訊息,然後它會發現這個App已經在手機上被移除了。這時候這個Device會回送一個訊息給GCM,告知GCM這個registration ID已經無效了。

 

3.3 GCM嘗試推播資訊給一個已經移除APPAndroid Device流程

當Server application嘗試推播一個訊息給一個已經無效的registration ID,GCM會回傳一個錯誤訊息"Device Not Registered"。接著Server application就可以負責在它儲存registration ID的資料庫列表中移除掉已經失效的registration ID

 

4. Setting Up Google Cloud Messaging

要建立一個整合GCM功能的App,有底下三個主要步驟要執行:

1. 建立一個Google API Project – 必須建立一個Google API 專案,然後啓用CGM服務與建立所對應的API Key。

2. 開發一個Android App – 這邊可以建立或者是維護一個Android App。

3. 建立一個Server Application – 這個Server Application是負責推送訊息給Device。這個Server Application可以是任何平台來假設,例如ASP.Net,PHP…。在這一次的範例我先用Windows Azure來擔任Server Application。

所以在這個範例中主要的執行流程如下:

1. 前往Google APIs網站上啓用 Google Cloud Message服務。

2. 建立API鑰匙。

3. 在Windows Azure上建立Mobile Service。

4. 在Windows Azure上輸入CGM的API Key。

5. 在Visual Studio 2012裡面新建一個Android Application 專案。

6. 修改程式專案程式

4.1 Creating a Google API Project

4.1.1在開始Google Cloud Message前,首先要在Google apis裡面建立一個Project.

請連結底下的網址來登入Google apis:

(https://code.google.com/apis/console/)

 

4.1.2完成建立Google apis project之後,可以在網址列上看見你的Project ID。稍後會在建立Android App時用到這個Project ID。

 

4.1.3接著在Google apis網站上,點選左邊的Services按鈕。這時會看到中間的網頁部分List出所有的Service服務。

 

4.1.4在下方找到Google Cloud Messaging for Android 這個服務,然後把它開啓。

 

4.1.5然後點選左邊的API Access,這個步驟我們要建立一個API Key,這個Key是要給Server Application所使用的。

在這個頁面中間下方,點選下方[Create Android key]。

 

4.1.6在彈出的Configure Server Key for Xamarin Evolve GCM Example對話筐中,在Accept requests from these server IP adderss下方輸入你的GCM允許從那些IP位置來的Server Application可以傳送推播訊息。若你在這邊沒有輸入特定的IP位置,那就代表預設你允許任何IP位置來的Server Application要求這個GCM執行推播訊息的動作。

 

4.1.7 建立完成可以看到一個Key for server apps,底下的API Key會是在你建立Server Application時所需要的必要項目。

 

4.2 Create the Android Application

在建立Android App時,首先很重要的是要取得Google API Project ID,這是作為App中的Sender ID。

接下來會有三個主要的步驟要處理:

1. 權限(Permissions):一個Android application 必須要設定權限可以使用Internet以及從GCM接收訊息。

2. 廣播接受器(BroadcastReceiver:當GCM要推送一個訊息到Android Device,Device上的背景程序Google Service Framework會負責接收由GCM推送過來的訊息,接著Google Service Framework會把這個訊息在傳送給App。

在這個App裡面我們就要建立一個廣播接受器(BroadcastReceiver),來接收一個由Google Service Framework送過來的訊息。

3. IntentService : 當廣播接受器(BroadcastReceiver)並不會去對訊息做一些處理,如果要處理這些訊息,廣播接受器會啓動一個IntentService來處理接收到的訊息。

4.2.1. Declare Permissions

l 在Android Application裡面我們有幾個權限必須要宣告,

android.permission.INTERNET – 要與GCM互動,必須允許APP有連接網路的權限。

android.permission.WAKE_LOCK  這是要防止在處理關於推播通知時,處理器不會進入睡眠狀態。

com.google.android.c2dm.permission.RECEIVE-這是讓App有權限去向GCM註冊以及接收GCM要推播的訊息。

<package_name>.permission.C2D_MESSAGE - 這個權限有兩個目的,告知我們的Device這個APP可以去接收所有C2D_Messages。也告知Device沒有其他的Application可以接收這些訊息。

01 // This will prevent other apps on the device from receiving GCM messages for this app
02 // It is crucial that the package name does not start with an uppercase letter - this is forbidden by Android.
03 [assembly: Permission(Name = "xamarin.sample.com.permission.C2D_MESSAGE")]
04 [assembly: UsesPermission(Name = "xamarin.sample.com.permission.C2D_MESSAGE")]
05  
06 // Gives the app permission to register and receive messages.
07 [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
08  
09 // This permission is necessary only for Android 4.0.3 and below.
10 [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
11  
12 // Need to access the internet for GCM
13 [assembly: UsesPermission(Name = "android.permission.INTERNET")]
14  
15 // Needed to keep the processor from sleeping when a message arrives
16 [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]

4.2.2. Creating a Broadcast Receiver

接下來建立一個BroadcastReceiver類別,這個會接聽以下從GCM回傳的Intent:

com.google.android.c2dm.intent.RECEIVE – 這是接收GCM推播的訊息。

com.google.android.c2dm.intent.REGISTRATION – 這是接收前往GCM註冊相關的訊息。

com.google.android.gcm.intent.RETRY – 這是接收重新嘗試前往GCM註冊的訊息。

下方是建立BroadcastReceiver類別的範例程式:

01 [BroadcastReceiver(Permission= "com.google.android.c2dm.permission.SEND")]
02 [IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] {"@PACKAGE_NAME@" })]
03 [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] {"@PACKAGE_NAME@" })]
04 [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@PACKAGE_NAME@"})]
05 public class MyGCMBroadcastReceiver : BroadcastReceiver
06 {
07     const string TAG = "PushHandlerBroadcastReceiver";
08     public override void OnReceive(Context context, Intent intent)
09     {
10         MyIntentService.RunIntentInService(context, intent);
11         SetResult(Result.Ok, nullnull);
12     }
13 }

4.2.3. AndroidManifest.xml裡面新增底下的權限 to support the receiver:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

 

4.2.4. Creating the IntentService

BroadcastReceiver裡面不應該包括著處理通知訊息的邏輯,所以我們這邊要在撰寫一個IntentService類別,讓這個Serveice來負責處理當收到訊息時要和使用者進行的互動。

在上一個小節,在BroadcastReceiver的OnReceive事件裡面呼叫了MyIntentService.RunIntentInService(context, intent);

這個方法。可以看到這個方法是被宣告在MyIntenService類別裡面的一個靜態方法。而在下方Service類別中,裡面有一段intent.Action;宣告,表示你可以經由這個宣告來判定目前所接收到的訊息到底是由App向GCM註冊後得到回傳的訊息還是由GCM發起推播,Device接收到訊息?

01 [Service]
02 public class MyIntentService : IntentService
03 {
04     static PowerManager.WakeLock sWakeLock;
05     static object LOCK = new object();
06  
07     static void RunIntentInService(Context context, Intent intent)
08     {
09         lock (LOCK)
10         {
11             if (sWakeLock == null)
12             {
13                 // This is called from BroadcastReceiver, there is no init.
14                 var pm = PowerManager.FromContext(context);
15                 sWakeLock = pm.NewWakeLock(
16                 WakeLockFlags.Partial, "My WakeLock Tag");
17             }
18         }
19  
20         sWakeLock.Acquire();
21         intent.SetClass(context, typeof(MyIntentService));
22         context.StartService(intent);
23     }
24  
25     protected override void OnHandleIntent(Intent intent)
26     {
27         try
28         {
29             Context context = this.ApplicationContext;
30             string action = intent.Action;
31  
32             if (action.Equals("com.google.android.c2dm.intent.REGISTRATION"))
33             {
34                 HandleRegistration(context, intent);
35             }
36             else if (action.Equals("com.google.android.c2dm.intent.RECEIVE"))
37             {
38                 HandleMessage(context, intent);
39             }
40         }
41         finally
42         {
43             lock (LOCK)
44             {
45                 //Sanity check for null as this is a public method
46                 if (sWakeLock != null)
47                     sWakeLock.Release();
48             }
49         }
50     }
51 }

4.2.5. Registering with Google Cloud Messaging

接下來就是了解Android App如何去向GCM做註冊的動作。在Android Application要去向GCM註冊前,首先Android App會傳送一個com.google.android.c2dm.intent.REGISTER Intent給GCM。

這個Intent會需要兩個參數值:

app – 這是一個允許Google Services Framework去向Application取得向GCM註冊必要資訊的PendingIntent。

Sender- 這是一個用逗號分隔字串陣列,裡面包含著要推播資訊給這個App的Sender IDs。

請參考下方的Sample code。

1 string senders = "<google cloud="" messaging="" sender="">";
2 Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
3 intent.SetPackage("com.google.android.gsf");
4 intent.PutExtra("app", PendingIntent.GetBroadcast(context, 0, new Intent(), 0));
5 intent.PutExtra("sender", senders);
6 context.StartService(intent);</google>

4.3 Roles of the Application Server

在這一篇我們是用Window Azure來當作我們的Server Application。在Windows Azure上要執行的步驟有底下幾個:

1. 建立一個Mobile Service

在Windows Azure網站上按[New]的項目,然後選擇建立Mobile Service。

這邊需要自定一個Mobile Service URL 名稱。到這個步驟Windows Azure Mobile Service就建立完成。

2. 建立一個todoitem資料庫

點選到剛剛建立的Mobile Service,展開畫面中間下方的[CREATE A NEW ANDROID APP],在中間找到

[Create a table]。這邊Windows Azure會幫我們在Windows Azure上面建立一個[Todoitem]資料庫。

3. 新增你的API KeyWindows Azure

點選Windows Azure上方的PUSH項目,找到[Google Cloud messaging settings],把在Google apis裡面建立的API Key貼過來。在Windows Azure的設定到目前為止就完成了。

4. 新增Server siteScript

01 function insert(item, user, request) {
02     request.execute({
03         success: function() {
04             // Write to the response and then send the notification in the background
05             request.respond();
06             push.gcm.send(item.channel, item.text, {
07                 success: function(response) {
08                     console.log('Push notification sent: ', response);
09                 }, error: function(error) {
10                     console.log('Error sending push notification: ', error);
11                 }
12             });
13         }
14     });
15 }

4.4 測試Android App

要能在模擬器上測試GCM,你的模擬器必須要有支援with Google Apps的模擬器。

範例程式可從Xamarin的網站下載。

http://components.xamarin.com/view/azure-mobile-services/

這個範例需要根據Windows Azure的資料庫結構做一些微調,在我的測試中,我在Android應用程式中新增了文字之後,按下Add Item的按鈕。

可以看到Android 手機的左上角出現了一個小icon。

下拉這一個icon,可以看到GCM送來的通知項目。

這時我們回到Windows Azure的資料庫上去查詢剛剛被我們寫入的資料,可以看到多了一筆我們剛剛新增的資料。

在這邊有兩個部分比較重要,第三個complete欄位裡面是一個false值,這個欄位是用來判斷使用者到底讀取了這則訊息沒有。

第四個channel欄位裡面記載的就是Android Device向GCM註冊後,GCM回傳的registration ID。

回到Android Device點選到剛剛推播過來的訊息,這時資訊已經被讀取。接著再回到Windows Azure查詢資料庫,可以看見complete欄位的屬性被改成true。

參考文獻

Remote Notifications

http://docs.xamarin.com/guides/cross-platform/application_fundamentals/notifications/android/remote_notifications_in_android

Get started with push notifications in Mobile Services

http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-with-push-android/

[Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)的更多相关文章

  1. Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)

    前期项目一直用的是Windows azure NotificationHub+Google Cloud Message 实现消息推送, 但是GCM google已经不再推荐使用,慢慢就不再维护了, 现 ...

  2. JavaFX結合 JDBC, Servlet, Swing, Google Map及動態產生比例圖 (1):NetBeans 寫 Servlet (转帖)

    JavaFX結合 JDBC, Servlet, Swing, Google Map及動態產生比例圖 (1):NetBeans 寫 Servlet 功能:這支程式的主要功能是將 javafx 與 swi ...

  3. [Windows Azure] Windows Azure Web Sites, Cloud Services, and VMs: When to use which?

    This document provides guidance on how to make an informed decision in choosing between Windows Azur ...

  4. AWS、阿里云、Azure、Google Cloud、华为云、腾讯云 各种云服务器价格收费对比(上)

    他来了,他来了~ 他带着六家公有云厂商的资源价格走来了~ 不久前,我们上线了一款小工具——[多云成本计算器]1.0版,公众号菜单栏可以直接体验.详细介绍可以戳这里<3秒即得最低价,速石上线「多云 ...

  5. windows azure Vm、cloud service、web application 如何选择可用的服务

    windows azure 的web应用和虚拟机都经常用.我们经常把我们的网站部署上去.一般选择web应用或者开一个虚拟机.开一个虚拟机就会按照虚拟机的使用时间进行计费. 那么我们选择web部署在哪里 ...

  6. JavaFX結合 JDBC, Servlet, Swing, Google Map及動態產生比例圖 (2):JavaFX建立及程式碼說明 (转帖)

    說明:就如同標題一樣,前端會用到JavaFX.Swing.Java Web Start.Google Map 的技術, 後端就是JDBC.Servlet的技術,以及我們會簽署認證jar檔案,這樣才可存 ...

  7. JavaFX結合 JDBC, Servlet, Swing, Google Map及動態產生比例圖 (3):部署設定及應用 (转帖)

    說明:這一篇主要是說明如何將程式部署到Application Server,以及程式如何運作,產生的檔案置於何處,以及如何以瀏覽器呈現(Applet),或是當成桌面應用程式,或是 桌面Applet,這 ...

  8. [Xamarin.Android] 儲存資料於Windows Azure (转帖)

    在準備討論Xamarin.Android 如何整合GCM與Windows Azure來實作Push Notification之前, 先來了解如何將Xamarin.Android 與Windows Az ...

  9. [转]探索 Windows Azure Storage

    本文转自:https://msdn.microsoft.com/zh-tw/jj573842 概觀 儲存服務 (Storage services) 在 Windows Azure 運算模擬器中提供了可 ...

随机推荐

  1. Qracle 11g 插图安装

    1.下载两个包 然后把包二的内容放入包一里 2.管理员身份运行setup 3.选择去掉复选框 4.下一步,然后选择是 5.选择第一项,然后选择下一步 6.个人使用选桌面类 7.不要放在C盘中 8.设置 ...

  2. Could not load file or assembly 'System.Data.SQLite ... 试图加载格式不正确的程序

    坑爹的System.Data.SQLite. 先给出下载地址:http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki ...

  3. npm是干什么的?

    允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用. 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用. 其实npm ...

  4. nginxのerror_logはformat指定できない.

    備忘録です. http://toshitanian.hatenablog.com/entry/2013/10/25/023838 2013-10-25 nginxのerror_logはformat指定 ...

  5. Oracle Alert - APP-ALR-04108: SQL error ORA-01455

    SELECT OD.ORGANIZATION_CODE, TO_CHAR(H.ORDER_NUMBER), --ORACLE ALERT 自动转数字类型最长11位,转字符处理解决APP-ALR-041 ...

  6. J-Link eclipse Plug-ins install

    Quicklinks If you know what this is all about and you just need the update site details: name: GNU A ...

  7. C# winform无边框窗体移动

    public partial class MessageHints : Form { //窗体移动API [DllImport("user32.dll")] public stat ...

  8. .net core 使用 redis

    .net core 使用 redis 个人感觉.net core 对于微软技术而言有很重要的意义 ,所以最近已有时间就想看一看关于.net core 的文章. 今天我就来写一写如何在.net core ...

  9. 在Windows Server 2008上部署免费的https证书

    背景 后web时代,https加密的重要性不言而喻.主流浏览器均对http站点标记不安全,敦促web服务提供商尽快升级至https. 原先的https证书多由各大域名服务商提供,动辄成千上万的部署证书 ...

  10. Fiddler4无法抓取HttpWebRequest本地请求的解决办法

    网上很多解决案例是如下方代码设置代理,但在我的Fiddler4环境下无效,后寻得官方处理方法证实与代理无关. HttpWebRequest request= WebRequest.Create(&qu ...