在 Xamarin.Forms 專案,修正進行 Azure 行動應用推播中樞註冊
在這裡,我們將要把我們寫好的 Xamarin.Forms 專案,設定使用 Azure 行動應用的推播服務功能,也就是要在應用程式啟動時候,與 Azure 行動應用的推播中樞進行註冊,並且可以接收與顯示推播訊息內容。
第一次準備工作
在您原先做好的 Xamarin.Forms 專案中,需要加入
Google Cloud Messaging Client
元件加入 Google Cloud Messaging Client 元件
- 使用 Visual Studio 2015 打開
XFDoggy.sln
專案 - 滑鼠右擊 原生Android專案的
Components
,選擇Get More Components
- 在搜尋文字輸入盒內,填入
Google Cloud Messaging Client
搜尋這個元件 - 點選
Google Cloud Messaging Client
元件,接著點選Add to App
按鈕
修改 原生 Android 專案
在這裡,我們僅需要修正 原生 Android 專案,讓 Android 應用程式可以與行動中樞溝通。
設計自己的 GcmServiceBase 類別
- 滑鼠右擊 原生Android專案中的
Infrastructure
資料夾,選擇加入
>類別
- 在對話窗中,點選
Visual C#
>Class
- 在名稱欄位中,輸入
GcmService
- 最後,點選
新增
按鈕 - 將底下程式碼置換這個
GcmService
類別請解析要加入的適當命名空間 - 請將這行程式碼
public static string[] SENDER_IDS = new string[] { "300143732939" };
的 300143732939 文字,置換成為您申請到的 FCM寄件者 ID
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 XFDoggy.Helpers;
[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 XFDoggy.Droid.Infrastructure
{
[Service]
public class GcmService : GcmServiceBase
{
public static string RegistrationID { get; private set; }
public GcmService()
: base(PushHandlerBroadcastReceiver.SENDER_IDS) { }
protected override void OnRegistered(Context context, string registrationId)
{
Log.Verbose("PushHandlerBroadcastReceiver", "GCM Registered: " + registrationId);
RegistrationID = registrationId;
var push = MainHelper.client.GetPush();
MainActivity.CurrentActivity.RunOnUiThread(() => Register(push, null));
}
public async void Register(Microsoft.WindowsAzure.MobileServices.Push push, IEnumerable<string> 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();
}
}
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("多奇數位創意通知", 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);
}
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);
}
}
[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[] { "300143732939" };
}
}
修改 MainActivity
- 在 原生Android專案中,開啟
MainActivity.cs
- 將底下程式碼置換這個
GcmService
類別請解析要加入的適當命名空間
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Prism.Unity;
using Microsoft.Practices.Unity;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using XFDoggy.Helpers;
using Gcm.Client;
using XFDoggy.Droid.Infrastructure;
[assembly: UsesPermission(Android.Manifest.Permission.AccessNetworkState)]
[assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.CallPhone)]
namespace XFDoggy.Droid
{
[Activity(Label = "多奇數位創意", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IAuthenticate
{
#region Firebase 的推播設定用程式碼
// Create a new instance field for this activity.
static MainActivity instance = null;
// Return the current activity instance.
public static MainActivity CurrentActivity
{
get
{
return instance;
}
}
#endregion
#region Azure 行動應用之身分驗證用到程式碼
// Define a authenticated user.
private MobileServiceUser user;
public async Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式)
{
// 驗證結果
var success = false;
// 要顯示的訊息
var message = string.Empty;
try
{
// 呼叫 Azure Mobile 用戶端的 LoginAsync 方法,依據指定的登入類型,進行身分驗證登入
user = await MainHelper.client.LoginAsync(this, p登入方式);
if (user != null)
{
message = string.Format("you are now signed-in as {0}.", user.UserId);
success = true;
}
}
catch (Exception ex)
{
message = ex.Message;
}
// 顯示登入成功或者失敗.
//AlertDialog.Builder builder = new AlertDialog.Builder(this);
//builder.SetMessage(message);
//builder.SetTitle("Sign-in result");
//builder.Create().Show();
return success;
}
#endregion
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.tabs;
ToolbarResource = Resource.Layout.toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
#region Azure 行動應用之身分驗證用到程式碼
// 將在 Android 原生平台實作的 IAuthenticate 物件,指定到 核心PCL 專案內
App.Init((IAuthenticate)this);
#endregion
#region Firebase 的推播設定用程式碼
// Set the current instance of MainActivity.
instance = this;
#endregion
LoadApplication(new App(new AndroidInitializer()));
#region Firebase 的推播設定用程式碼
try
{
// Check to ensure everything's set up 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");
}
#endregion
}
#region Firebase 的推播設定用程式碼
private void CreateAndShowDialog(String message, String title)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage(message);
builder.SetTitle(title);
builder.Create().Show();
}
#endregion
#region Firebase 的推播設定用程式碼
#endregion
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
}
執行與測試
- 您需要有安裝 Google Play 服務的裝置,才能夠進行底下的測試