.NET MAUI でプッシュ通知を実装する(Android 編)
表題の通り .NET MAUI でプッシュ通知を実装してみます。
(案の定というか).NET MAUI でのプッシュ通知に関するドキュメントが見つからないということもあり、Xamarin.Forms のドキュメントを参考にしながらやってみます。
やるべきこととしては以下のようになります。
- 1. Firebase プロジェクトを作成し、Firebase Cloud Messaging を有効にする
- 2. 通知ハブ(Notification Hubs)を作成する
- 3. FCM の設定を通知ハブ用に構成する
- 4. Visual Studio プロジェクトを作成し、NuGet パッケージを追加する
- 5. Google Services JSON ファイルを追加する
- 6. プロジェクトで Notification Hubs を設定する
- 7. Azure Portal からテスト通知を送信する
1. Firebase プロジェクトを作成し、Firebase Cloud Messaging を有効にする
Firebase プロジェクトを作成します。ここでのプロジェクト名は任意で構いません。
Android パッケージ名を入力してアプリ登録をおこないます。
ここで入力した Android パッケージ名は .NET MAUI でも使用しますのでメモしておきます(後述)。
google-services.json
をダウンロードします。このファイルは .NET MAUI で使用します(後述)。
以降は Java での実装なのでここでの作業はこれで終わりです。
プロジェクトの先頭に戻り、「プロジェクトの設定」(「プロジェクトの概要」の隣にあるタイヤアイコン)→「Cloud Messageing」と進みます。
「Cloud Messaging(レガシー)」の右側にある三点ボタンをクリックして、Cloud Messaging を有効にします。
(リロードすると Cloud Messaging が有効になるので)「サーバーキーを追加」をクリックします。ここでのサーバーキーは Notification Hubs の設定で使用しますのでメモしておきます。
2. 通知ハブ(Notification Hubs)を作成する
Azure ポータルから Notification Hub を検索して作成します。
ハブ名は .NET MAUI で使用しますのでメモしておきます。
Notification Hub の「Access Policies」から「DefaultListenSharedAccessSignature」(Permission=Listen)の値をメモしておきます。この後 .NET MAUI のプロジェクトで使用します。
3. FCM の設定を通知ハブ用に構成する
Notification Hubs で「Google (GCM/FCM)」 を選択します。
先ほど Firebase Console でメモしておいた API キーをペーストして保存します。
4. Visual Studio プロジェクトを作成し、NuGet パッケージを追加する
Visual Studio 2022 を起動して「新しいプロジェクトの作成」を選択します。
"maui" で検索するなどして、「.NET MAUI アプリ」を作成します。
プロジェクトのプロパティを選択して、「Andoird >マニフェスト」を選択します。
Firebase Console でメモしておいた「アプリケーションパッケージ名」をペーストします。アプリケーション名は任意です。
ここで設定した「アプリケーションパッケージ名」は
Platforms/Android/AndroidManifest.xml
へ反映されますが、このファイルも同時にプロジェクトで開いていると反映されないケースがあるようです。
パッケージを二つインストールします。バージョンは 2022年10月28日時点のものです。
<PackageReference Include="Xamarin.Azure.NotificationHubs.Android" Version="1.1.4.1" /> <PackageReference Include="Xamarin.Firebase.Messaging" Version="123.0.8" />
Android の Framework のバージョンを 30 にしておきます。
5. Google Services JSON ファイルを追加する
Google Firebase Console からダウンロードした google-services.json
ファイルをプロジェクト フォルダーにコピーします。
ソリューション エクスプローラーで google-services.json を選択して、プロパティでビルド アクションを GoogleServicesJson
に設定します。
パッケージが正常にインストールされていないと GoogleServicesJson
が選択できない場合があります。Visual Studio を再起動してプロジェクトを再度開くと表示されることもあります。
6. プロジェクトで Notification Hubs を設定する
<application>
要素の後ろに(前でも良いですが)、以下のステートメントを追加します。
<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"/>
プロジェクトで下記の Constants.cs
クラスを作成します。プレースホルダーの値を実際の値に置き換えます。
ListenConnectionString
は「Access Policies」の「DefaultListenSharedAccessSignature」で取得した値、NotificationHubName
は Notification Hubs で作成したハブ名になります。
public static class Constants { public const string ListenConnectionString = "<Listen connection string>"; public const string NotificationHubName = "<hub name>"; }
下記の FirebaseService
クラスを Platforms/Android
フォルダに追加します。
OnNewToken
メソッドはアプリの初回起動時に呼ばれます。ここで取得できるトークンをつかって Notification Hubs への登録をおこないます。
プッシュ通知を受信すると OnMessageReceived
メソッドが呼ばれます。ここではアプリがバックグラウンドの状態の時のローカル通知用の設定(SendLocalNotification
)と、アプリが起動している場合は MainPage
へメッセージを追加する処理(SendMessageToMainPage
)をおこなっています。
using Android.App; using Android.Content; using Android.Util; using AndroidX.Core.App; using Firebase.Messaging; using WindowsAzure.Messaging; namespace MauiPush.Platforms.Android; [Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class FirebaseService : FirebaseMessagingService { public override void OnNewToken(string token) { SendRegistrationToServer(token); } public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); string messageBody = string.Empty; if (message.GetNotification() != null) { messageBody = message.GetNotification().Body; } else { messageBody = message.Data.Values.First(); } // convert the incoming message to a local notification SendLocalNotification(messageBody); // send the incoming message directly to the MainPage SendMessageToMainPage(messageBody); } private void SendLocalNotification(string body) { try { var intent = new Intent(this, typeof(MainActivity)); intent.AddFlags(ActivityFlags.ClearTop); intent.PutExtra("message", body); var requestCode = new Random().Next(); var pendingIntent = PendingIntent.GetActivity(this, requestCode, intent, PendingIntentFlags.OneShot); var notificationBuilder = new NotificationCompat.Builder(this, Constants.NotificationChannelId) .SetContentTitle("IDEQ Alert") .SetSmallIcon(Resource.Drawable.ic_launcher) .SetContentText(body) .SetAutoCancel(true) .SetShowWhen(false) .SetContentIntent(pendingIntent); var notificationManager = NotificationManagerCompat.From(this); notificationManager.Notify(0, notificationBuilder.Build()); } catch (Exception e) { Log.Error("firebase", e.ToString()); } } void SendMessageToMainPage(string body) { var appShell = App.Current.MainPage as AppShell; var mainPage = appShell.CurrentPage as MainPage; mainPage.AddMessage(body); Log.Debug("firebase", $"Message:{body}"); } void SendRegistrationToServer(string token) { try { NotificationHub hub = new NotificationHub(Constants.NotificationHubName, Constants.ListenConnectionString, this); // register device with Azure Notification Hub using the token from FCM Registration registration = hub.Register(token, Constants.SubscriptionTags); } catch (Exception e) { Log.Error("firebase", $"Error registering device: {e.Message}"); } } }
プッシュ通知を受信した時に表示するコントロールを MainPage.xaml
に追加します。今回は <Button>
の下に追加しました。
<StackLayout x:Name="messageDisplay" HorizontalOptions="Center" VerticalOptions="Start"> </StackLayout>
これで実装ができたので実機を使ってデバッグします。
7. Azure Portal からテスト通知を送信する
アプリの通知の受信をテストするには、Azure Portal の「テスト送信(Test Send)」オプションを使用します。 プラットフォームで「Android」を選択して「Send」をクリックします。
Android デバイスが正常に登録されていれば、送信結果に登録された Registration Id が出力されます。
アプリが起動されていればプッシュ通知を受信する都度メッセージが追加されます。
アプリがバックグラウンドにいる場合はローカル通知で受信します。