Azure Notification HubsでXamarin.FormsアプリにPush通知 メモ (Android編)
このチュートリアルの通りにやってみる.
Azure Notification Hubsを使う場合の流れ
Firebase Cloud MessagingやApple Push Notification ServiceなどをAzure Notification Hubsを介して利用する形.
Azure Notification HubsはあくまでHubとしての役割を果たすものであって,それ単体でPush通知を行うサービスではない.
また,デバイスがPush通知を受け取ったときの処理は実装す
Xamarin.Android
ここでXamarin.Androidのチュートリアルはこちら.
Android側のFirebase Cloud MessagingとAzure Notification Hubsを使うPush通知のチュートリアルです.
Firebase Cloud Messagingプロジェクトを作成
サインインする.
プロジェクトを作成する.
プロジェクトに名前をつける
Googleアナリティクスを有効にするか?
もう一つGoogleアナリティクスについて
プロジェクト作成完了
プロジェクトにAndroidアプリを追加する
プロジェクトの作成が完了すると,プロジェクトのページが表示されるのでアプリケーションを登録する.
アプリの登録にはAndroidのパッケージ名が必要なので,それを先に取得しておきます.
Xamarin.FormsのAndroidプロジェクトのプロパティを開き,「Android Manifest」タブを開くとそこにPackage Nameが記述されています.
これをFirebaseのアプリ登録画面に入力します.
google-services.json
ファイルをダウンロードする.
次のステップはスキップする.
次のステップもスキップする.
Androidアプリの追加が完了しました.
登録したアプリの設定画面を開くために「⚙」アイコンをクリックします.
以下のような設定画面が開きます.
「クラウドメッセージング」タブを開いて「サーバーキー」をコピーします.
Azure Notification Hubsの作成
Azure Portalに移動する. portal.azure.com
「Notification Hub」リソースを作成する.
「Add」ボタンを押してNotification Hubを作成する.
以下のように項目を埋めて「Create」ボタンを押す.無料プランがあるので選んでおくこと.
リソースの作成が完了したらリソースに移動する.
左側のブレードから「Access Policies」を選択する.
ここでConnection String
が2つ表示されるが,DefaultFullSharedAccessSignature
は使わないこと.こちらはバックエンドのサーバーアプリでのみ使用すること,とのこと.
Do not use the DefaultFullSharedAccessSignature policy in your application. This is meant to be used in your back end only.
Connection Stringは後で使う.
今度は左側のブレードから「Google(GCM/FCM)」を選択する.
ここの「API Key」の欄に,Firebaseの方の「サーバーキー」をコピペして「Save」ボタンを押す.
Visual Studio
今度はVisual Studio側の設定です.Xamarin.Formsプロジェクトを作成しておきます.
Nugetパッケージをインストールする
インストールするのは以下の3つのパッケージ.
- Xamarin.GooglePlayServices.Base
- Xamarin.Firebase.Messaging
- Xamarin.Azure.NotificationHubs.Android
Androidプロジェクトで右クリックしてManage Nuget Packages
を選択してインストールを行う.
google-services.jsonファイルを追加する
ダウンロードしておいたgoogle-services.json
ファイルをAndroidプロジェクトに追加する.
そして,Build ActionをGoogleServicesJson
に設定する.
AndroidManifest.xmlの編集
以下のように追加します.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.xfazurenotificationhubs"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" /> <!-- 追加ここから 1--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <!-- ここまで --> <application android:label="XFAzureNotificationHubs.Android"> <!-- 追加ここから 2--> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" /> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" 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="${applicationId}" /> </intent-filter> </receiver> <!-- ここまで --> </application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> </manifest>
接続情報を保持するクラスを作成する
Constants.cs
ファイルを共有プロジェクトに追加し,以下の情報をAzureから取得して保持するようにする.
この情報はAndroid,iOSの両方から使う.
- Listen connection string
- hub name
public static class Constants { public const string ListenConnectionString = "<DefaultListenSharedAccessSignature from Azure>"; public const string NotificationHubName = "<Hub Name from Azure>"; }
MainActivity.csの編集
MainActivity.csに以下usingを追加する.
using Android.Util; using Android.Gms.Common;
次はMainActivityクラス内に以下を追加する.
public const string TAG = "MainActivity"; internal static readonly string CHANNEL_ID = "my_notification_channel";
MainActivityクラス内に次のメソッドを追加する.これはGoogle Play Serviceが有効かどうかを確認するためのもの.
public bool IsPlayServicesAvailable() { int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.Success) { if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode)) Log.Debug(TAG, GoogleApiAvailability.Instance.GetErrorString(resultCode)); else { Log.Debug(TAG, "This device is not supported"); Finish(); } return false; } Log.Debug(TAG, "Google Play Services is available."); return true; }
更に,MainActivityクラス内にNotification Channelを作成するメソッドを追加する.
private void CreateNotificationChannel() { if (Build.VERSION.SdkInt < BuildVersionCodes.O) { // Notification channels are new in API 26 (and not a part of the // support library). There is no need to create a notification // channel on older versions of Android. return; } var channelName = CHANNEL_ID; var channelDescription = string.Empty; var channel = new NotificationChannel(CHANNEL_ID, channelName, NotificationImportance.Default) { Description = channelDescription }; var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.CreateNotificationChannel(channel); }
MainActivity.cs内のOnCreateメソッド内で,base.OnCreate(savedInstanceState);
の後ろに以下を追加する.
if (Intent.Extras != null) { foreach (var key in Intent.Extras.KeySet()) { if(key!=null) { var value = Intent.Extras.GetString(key); Log.Debug(TAG, "Key: {0} Value: {1}", key, value); } } } IsPlayServicesAvailable(); CreateNotificationChannel();
MyFirebaseMessagingService
クラスをAndroidプロジェクトに追加する.
以下のusingを追加する.
using Android.Util; using Firebase.Messaging; using Android.Support.V4.App; using WindowsAzure.Messaging;
MyFirebaseMessagingServiceクラスは以下のように宣言する. Push通知をクラウド側から受け取った場合にこのクラス内のOnMessageReceivedメソッドが実行される.
[Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })] public class MyFirebaseMessagingService : FirebaseMessagingService { ... }
MyFirebaseMessagingServiceクラス内に以下を追加.
Push通知を受け取った際の処理をOnMessageReceived
メソッド内に記述する.今回の例ではローカル通知に表示させている.
const string TAG = "MyFirebaseMsgService"; NotificationHub hub; public override void OnMessageReceived(RemoteMessage message) { Log.Debug(TAG, "From: " + message.From); if (message.GetNotification() != null) { //These is how most messages will be received Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body); SendNotification(message.GetNotification().Body); } else { //Only used for debugging payloads sent from the Azure portal SendNotification(message.Data.Values.First()); } } void SendNotification(string messageBody) { var intent = new Intent(this, typeof(MainActivity)); intent.AddFlags(ActivityFlags.ClearTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot); var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID); notificationBuilder.SetContentTitle("FCM Message") .SetSmallIcon(Resource.Drawable.ic_launcher) .SetContentText(messageBody) .SetAutoCancel(true) .SetShowWhen(false) .SetContentIntent(pendingIntent); var notificationManager = NotificationManager.FromContext(this); notificationManager.Notify(0, notificationBuilder.Build()); }
さらにMyFirebaseMessagingServiceクラスに以下を追加する.
ここのnew NotificationHub(Constants.NotificationHubName, Constants.ListenConnectionString, this);
でAzure Notification Hubs`に端末を登録している.
ということは,このコードが実行されるときにオンラインである必要があるな.
public override void OnNewToken(string token) { Log.Debug(TAG, "FCM token: " + token); SendRegistrationToServer(token); } void SendRegistrationToServer(string token) { // Register with Notification Hubs hub = new NotificationHub(Constants.NotificationHubName, Constants.ListenConnectionString, this); var tags = new List<string>() { }; var regID = hub.Register(token, tags.ToArray()).RegistrationId; Log.Debug(TAG, $"Successful registration of ID {regID}"); }
プロジェクトをビルドする.
アプリを実行する.
Azure Notification Hubsからテスト送信する.
作成してあるNotification Hubリソースのページに移動し,左側のブレードからTest Send
を選択する.
PlatformにAndroid
を指定して,「Send」ボタンを押す.
以下のメッセージが出れば送信成功.
少しすると実行中のアプリに以下のように通知が表示される.
今回のソースコード
メモ
Firebase Cloud Messagingを介したメッセージの受信は,アプリが起動していなくても行われる.
一度でも起動すれば,アプリケーションがFCMを利用することが登録?されるので,例えば端末再起動後にアプリを起動しなくても通知を受信できる.
端末起動後,メッセージ受信までに1分程かかる感じ.
ASP.NETアプリから利用する
ASP.NETアプリからNotification Hubsを使ってPush通知を送ってみたくなりました.
こちらを参考にやってみます.
ASP .NET Core Web API with Azure Notification Hubdevislandblog.wordpress.com
上の記事ではWebAPIからNotification Hubsを利用していますが,渡しの場合は,Webアプリから使いたいと思います.
Webアプリ上のボタンを押すとランダムな応援メッセージが届くというものを作ってみたい.
まずはNotification Hubsに接続する情報を保持するクラスを作成.
public static class NotificationHubConfiguration { public const string ConnectionString = "<DefaultFullSharedAccessSignature from Azure>"; public const string NotificationHubName = "<Notification Hub Name from Azure>"; }
次にappsettings.jsonに以下を追加します.
"NotificationHub": { "ConnectionString": "<Endpoint...>", "HubName": "<DevIslandNotificationHub>" },
ここで,Connection Stringに使用するのはモバイルアプリのクライアント側とは異なりDefaultFullSharedAccessSignature
の方なので注意しましょう.
うーん,こっちの方がわかりやすいかな.
NotificationHubClient _hub = NotificationHubClient.CreateClientFromConnectionString("<DefaultFullSharedAccessSignature from Azure>", "<Notification Hub Name from Azure>"); string message = "Hello World."; var androidMessage = "{\"data\":{\"message\": \"" + message + "\"}}"; await _hub.SendFcmNativeNotificationAsync(androidMessage);
iOS
持ってないのでわかりません.