Azure 行動推播中樞
想要能夠讓您開發的 Xamarin.Forms 應用程式,接收到來自遠端的訊息推播,這需要您:
- 申請與啟用
Google Cloud Messaging (GCM)
(對於 Google 平台行動裝置而言) /Apple Push Notification Service (APNS)
(對於 iOS 行動平台裝置而言) /Windows Push Notification Services (WNS)
(對於 Windows 行動平台裝置而言) - 申請與建立 Azure 行動應用的推播設定
- 修改 Azure 行動應用的後端
- 修改 Xamarin.Forms 應用程式
在這裡,將以 Android 平台作為實作說明,首先,需要申請
oogle Cloud Messaging (GCM)
, 接著,嘗試修正 附件 Azure Mobile App 後端服務建立說明 文章中的 Azure Mobile App 後端服務專案
與 Azure Mobile App 前端專案
程式碼。申請 Google Cloud Messaging (GCM)
- 首先,打開網頁,進入到
Google Cloud Console
https://console.developers.google.com/iam-admin/projects - 點選
+ 建立專案
連結 - 當
建立專案
對話窗出現之後,請在專案名稱
欄位內填入DoggyMobileGCM
,您可以看到您的專案 ID 顯示在對話窗內,而後點選建立
按鈕 - 當專案建立完成之後並且出現在所有專案清單內,請點選這個剛剛產生的專案
DoggyMobileGCM
- 當
IAM與管理員
頁面出現後,點選設定
,您會看到專案編號
欄位,請將此編號 (213736323010
) 複製下來,等下會用到 - 接著,請點畫面中右上方的
Google APIs
圖示連結,進入到 Google APIs 申請頁面,當然,也可以直接輸入這個網址 : https://console.developers.google.com/apis/library?project=doggymobilegcm - 進入到
API管理員
頁面,請找到行動服務類 API
標題,接著點選Google Cloud Messaging
- 總覽頁面看到之後,請點選
啟用
按鈕,當啟用完成之後,接著點選左方的憑證
進入到憑證設定頁面下圖圍啟用完成 - 此時,網頁中間會出現
API 憑證
這個對話窗 ,請點選建立憑證
按鈕,接著點選API金鑰
選項。 - 而後,會出現
建立新的金鑰
對話窗,請點選「伺服器」金鑰
按鈕 - 當回到
憑證
頁面,如下圖,請在名稱
欄位內輸入伺服器金鑰DoggyMobile
做為日後識別之用,接著點選建立
按鈕。 - 最後,您會看到您申請的 API 金鑰 已經產生出來了
AIzaSyCp2pENhEkrSD1tErz1AQyb2FN8zuz7TpQ
請複製這個金鑰,等下會用到。您可以點選確定
按鈕,以關閉這個對話窗。
Azure 行動應用之推送設定
- 請回到 Azure 儀表板,接著點選
doggymobilebe 行動 App
圖示,進入到doggymobilebe 行動 App
設定刀鋒頁面。 - 在
設定
刀鋒頁面,點選推送
- 在
Create Notificati...
刀鋒頁面,點選Notification Hub
- 在
Notification Hub
刀鋒頁面,點選+ Notification Hub
- 在剛剛出現新的
Notification Hub
刀鋒頁面- 請在
Notification Hub
欄位內,輸入DoggyMobileNotificationHub
- 請點選
Namespace 設定必要設定
下面一點點的Or create new
這個連結。(在此假設您需要為這個 Notification Hub產生一個新的Namespace`, 若您的 Azure 上已經有新的 Namespace,可以直接選取)。 - 請在
Create a new namespace
欄位內,輸入DoggyMobileNotiHubNamespace
- 請選擇
釘選到儀表板
檢查盒,使其在勾選狀態下 - 最後請點選
確定
按鈕
- 此時,多餘的刀鋒視窗會自動關閉,剩下
Create Notificati...
刀鋒視窗,請在該刀鋒視窗下方,點選建立
按鈕 - 此時會回到 Azure 儀表板,當剛剛建立的 Notification Hub & Namespace 建立完成之後(您也可以從右上方的提示圖示中看到處理進度與是否完成),點選
doggymobilebe 行動 App
圖示,進入到doggymobilebe 行動 App
設定刀鋒頁面。 - 此時在
設定
刀鋒頁面內,您會看到一個推送 (DoggyMobileNotificationHu...
項目,請點選這個項目 - 在
Push notification...
刀鋒頁面,點選Google (GCM)
- 在
Google (GC...)
刀鋒頁面,請在API Key
欄位中,輸入剛剛在 Google Cloud Messaging (GCM) 內申請得到的 API Key (AIzaSyCp2pENhEkrSD1tErz1AQyb2FN8zuz7TpQ),而後,點選Save
按鈕。當儲存成功的訊息 (Success Notification Hub updated successfully!) 顯示在螢幕上,請點選確定
按鈕
修改 Azure 行動應用的後端
- 請根據 Azure Mobile App 後端服務建立說明 文章中,最後下載的
Azure Mobile App 後端服務專案
, 使用 Visual Studio 2015,開啟 Azure Mobile App 前端專案DoggyMobileBE.sln
- 請先安裝這個
Microsoft.Azure.NotificationHubs
NuGet 套件到專案內。 - 在方案總管內,展開專案
DoggyMobileBEService
>Controllers
,接著打開TodoItemController.cs
檔案。- 將底下 using 程式碼加入到這個檔案內
using System.Collections.Generic;
using Microsoft.Azure.NotificationHubs;
using Microsoft.Azure.Mobile.Server.Config;
- 在 PostTodoItem 方法內,請將底下程式碼加入到呼叫 InsertAsync 方法之後
// Get the settings for the server project.
HttpConfiguration config = this.Configuration;
MobileAppSettingsDictionary settings =
this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
// Get the Notification Hubs credentials for the Mobile App.
string notificationHubName = settings.NotificationHubName;
string notificationHubConnection = settings
.Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
// Create a new Notification Hub client.
NotificationHubClient hub = NotificationHubClient
.CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
// Sending the message so that all template registrations that contain "messageParam"
// will receive the notifications. This includes APNS, GCM, WNS, and MPNS template registrations.
Dictionary<string,string> templateParams = new Dictionary<string,string>();
templateParams["messageParam"] = item.Text + " was added to the list.";
try
{
// Send the push notification and log the results.
var result = await hub.SendTemplateNotificationAsync(templateParams);
// Write the success result to the logs.
config.Services.GetTraceWriter().Info(result.State.ToString());
}
catch (System.Exception ex)
{
// Write the failure result to the logs.
config.Services.GetTraceWriter()
.Error(ex.Message, null, "Push.SendAsync Error");
}
- 請重新
發行
這個專案
修改 DoggyMobileBE.Droid 專案
- 請根據 Azure Mobile App 後端服務建立說明 文章中,最後下載的
Azure Mobile App 前端專案
, 使用 Visual Studio 2015,開啟 Azure Mobile App 前端專案DoggyMobileBE.sln
- 請展開專案
DoggyMobileBE.Droid
,使用滑鼠右擊Components
節點,選擇Get More Components...
- 在
All Components
對話窗內,請搜尋Google Cloud Messaging Client
這個元件,找到後,點選這個找到項目 - 當出現
Xamarin Component Store ▶ Google Cloud Messaging Client
對話窗時候,請點選右方的Add to App
按鈕
- 打開
MainActivity.cs
檔案- 加入底下 using 敘述到這個檔案內
using Gcm.Client;
- 在 OnCreate 方法內,在 LoadApplication 之後,加入底下程式碼
try
{
// Check to ensure everything's setup right
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);
// Register for push notifications
System.Diagnostics.Debug.WriteLine("Registering...");
GcmClient.Register(this, PushHandlerBroadcastReceiver.SENDER_IDS);
}
catch (Java.Net.MalformedURLException)
{
CreateAndShowDialog("There was an error creating the client. Verify the URL.", "Error");
}
catch (Exception e)
{
CreateAndShowDialog(e.Message, "Error");
}
- 將底下程式碼的 CreateAndShowDialog 輔助方法加入到這個檔案 MainActivity 類別
private void CreateAndShowDialog(String message, String title)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage (message);
builder.SetTitle (title);
builder.Create().Show ();
}
- 在 MainActivity 類別內,加入底下屬性宣告程式碼
// Create a new instance field for this activity.
static MainActivity instance = null;
// Return the current activity instance.
public static MainActivity CurrentActivity
{
get
{
return instance;
}
}
- 在 OnCreate 方法內的最前面,加入底下初始化 instance 的程式碼
// Set the current instance of MainActivity.
instance = this;
- 滑鼠右擊專案 DoggyMobileBE.Droid 節點,選擇
加入
>類別
- 請點選
Visual C#
>Class
- 在底下
名稱
欄位內輸入GcmService
- 點選
新增
按鈕
- 在 GcmService.cs 檔案內
- 加入底下 using 敘述
using Android.App;
using Android.Content;
using Android.Media;
using Android.Support.V4.App;
using Android.Util;
using Gcm.Client;
using Microsoft.WindowsAzure.MobileServices;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
- 在 using 敘述之後與 namespace 之前,加入底下程式碼
[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
//GET_ACCOUNTS is only needed for android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
- 在 namespace 之後,加入底下新增的類別定義程式碼
- 請將之前在
Google Cloud Messaging (GCM)
取得的專案編號
(也就是 213736323010 ) 替換掉底下文字<PROJECT_NUMBER>
- 請將之前在
[BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new string[] { "@PACKAGE_NAME@" })]
public class PushHandlerBroadcastReceiver : GcmBroadcastReceiverBase<GcmService>
{
public static string[] SENDER_IDS = new string[] { "213736323010" };
}
- 使用底下程式碼,將 GcmService 類別定義替換掉
[Service]
public class GcmService : GcmServiceBase
{
public static string RegistrationID { get; private set; }
public GcmService()
: base(PushHandlerBroadcastReceiver.SENDER_IDS){}
}
- 使用底下程式碼,加入到 GcmService 類別內```cs protected override void OnRegistered(Context context, string registrationId) { Log.Verbose("PushHandlerBroadcastReceiver", "GCM Registered: " + registrationId); RegistrationID = registrationId;var push = TodoItemManager.DefaultManager.CurrentClient.GetPush();MainActivity.CurrentActivity.RunOnUiThread(() => Register(push, null)); }
public async void Register(Microsoft.WindowsAzure.MobileServices.Push push, IEnumerable tags) { try { const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";
JObject templates = new JObject();
templates["genericMessage"] = new JObject
{
{"body", templateBodyGCM}
};
await push.RegisterAsync(RegistrationID, templates);
Log.Info("Push Installation Id", push.InstallationId.ToString());
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
Debugger.Break();
}
}
10. 使用底下程式碼,加入到 GcmService 類別內
```cs
protected override void OnMessage(Context context, Intent intent)
{
Log.Info("PushHandlerBroadcastReceiver", "GCM Message Received!");
var msg = new StringBuilder();
if (intent != null && intent.Extras != null)
{
foreach (var key in intent.Extras.KeySet())
msg.AppendLine(key + "=" + intent.Extras.Get(key).ToString());
}
//Store the message
var prefs = GetSharedPreferences(context.PackageName, FileCreationMode.Private);
var edit = prefs.Edit();
edit.PutString("last_msg", msg.ToString());
edit.Commit();
string message = intent.Extras.GetString("message");
if (!string.IsNullOrEmpty(message))
{
createNotification("New todo item!", "Todo item: " + message);
return;
}
string msg2 = intent.Extras.GetString("msg");
if (!string.IsNullOrEmpty(msg2))
{
createNotification("New hub message!", msg2);
return;
}
createNotification("Unknown message details", msg.ToString());
}
void createNotification(string title, string desc)
{
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
//Create an intent to show ui
var uiIntent = new Intent(this, typeof(MainActivity));
//Use Notification Builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
//Create the notification
//we use the pending intent, passing our ui intent over which will get called
//when the notification is tapped.
var notification = builder.SetContentIntent(PendingIntent.GetActivity(this, 0, uiIntent, 0))
.SetSmallIcon(Android.Resource.Drawable.SymActionEmail)
.SetTicker(title)
.SetContentTitle(title)
.SetContentText(desc)
//Set the notification sound
.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
//Auto cancel will remove the notification once the user touches it
.SetAutoCancel(true).Build();
//Show the notification
notificationManager.Notify(1, notification);
}
- 使用底下程式碼,加入到 GcmService 類別內
protected override void OnUnRegistered(Context context, string registrationId)
{
Log.Error("PushHandlerBroadcastReceiver", "Unregistered RegisterationId : " + registrationId);
}
protected override void OnError(Context context, string errorId)
{
Log.Error("PushHandlerBroadcastReceiver", "GCM Error: " + errorId);
}
- 滑鼠右擊
DoggyMobileBE.Droid
,選擇 選擇設定為起始專案
,並且按下 F5 開始執行