Xamarin.Android アプリへのプッシュ通知の追加

概要

このチュートリアルでは、Xamarin.Android クイックスタート プロジェクトにプッシュ通知を追加して、レコードが挿入されるたびにプッシュ通知が送信されるようにします。

ダウンロードしたクイックスタートのサーバー プロジェクトを使用しない場合は、プッシュ通知拡張機能パッケージを追加する必要があります。 詳細については、「Azure Mobile Apps 用 .NET バックエンド サーバー SDK の操作」を参照してください。

前提条件

このチュートリアルでは、次のセットアップが必要です。

通知ハブを構成する

Azure App Service の Mobile Apps 機能は Azure Notification Hubs を使用してプッシュを送信するため、ここではモバイル アプリの通知ハブを構成します。

  1. Azure Portal で、[App Services] に移動し、アプリ バックエンドを選択します。 [設定][プッシュ] を選択します。

  2. 通知ハブ リソースをアプリに追加するには、[接続] を選択します。 ハブを作成することも、既存のハブに接続することもできます。

    ハブの構成

これで、通知ハブが Mobile Apps のバックエンド プロジェクトに接続されました。 後でこの通知ハブを構成して、デバイスにプッシュ通知を送信するプラットフォーム通知システム (PNS) に接続します。

Firebase Cloud Messaging を有効にする

  1. Firebase コンソールにサインインします。 Firebase プロジェクトがまだない場合は、新しく作成します。

  2. プロジェクトを作成した後、 [Add Firebase to your Android app](Android アプリに Firebase を追加する) を選択します。

    Android アプリへの Firebase の追加

  3. [Android アプリへの Firebase の追加] ページで、次の手順を実行します。

    1. [Android package name](Android パッケージ名) については、お使いのアプリケーションの build.gradle ファイル内にある applicationId の値をコピーします。 この例では com.fabrikam.fcmtutorial1app です。

      パッケージ名を指定する

    2. [アプリの登録] を選択します。

  4. [google-services.json をダウンロード] を選択し、プロジェクトの app フォルダーにファイルを保存して、[次へ] をクリックします。

    google-services.json をダウンロードする

  5. Android Studio で、プロジェクトに次の構成変更を加えます。

    1. プロジェクト レベルの build.gradle ファイル (<project>/build.gradle) で、dependencies セクションに次のステートメントを追加します。

      classpath 'com.google.gms:google-services:4.0.1'
      
    2. アプリレベルの build.gradle ファイル (<project>/<app-module>/build.gradle) で、dependencies セクションに次のステートメントを追加します。

      implementation 'com.google.firebase:firebase-core:16.0.8'
      implementation 'com.google.firebase:firebase-messaging:17.3.4'
      
    3. アプリ レベルの build.gradle ファイルの最後の dependencies セクションの末尾に次の行を追加します。

      apply plugin: 'com.google.gms.google-services'
      
    4. ツールバーの [今すぐ同期] を選択します。

      build.gradle の構成変更

  6. [次へ] を選択します。

  7. [この手順をスキップする] を選択します。

    最後の手順をスキップする

  8. Firebase コンソールで、プロジェクトの歯車アイコンを選択します。 次に、 [Project Settings](プロジェクト設定) を選択します。

    [Project Settings]\(プロジェクト設定\) の選択

  9. google-services.json ファイルを Android Studio プロジェクトの app フォルダーにダウンロードしていない場合は、このページでダウンロードできます。

  10. 上部にある [クラウド メッセージング] タブに切り替えます。

  11. 後で使用するために、サーバー キーをコピーし、保存します。 この値を使用して、ハブを構成します。

プッシュ要求を送信するように Azure を構成する

  1. Azure Portal で、[すべて参照]>[App Services] の順にクリックし、Mobile Apps バックエンドをクリックします。 [設定] で、[App Service Push (App Service プッシュ)]、通知ハブ名の順にクリックします。

  2. [Google (GCM)] をクリックし、前の手順で Firebase から取得した [サーバー キー] の値を入力し、[保存] をクリックします。

    ポータルで API キーを設定する

これで、Mobile Apps バックエンドは、Firebase Cloud Messaging を使用するように構成されました。 これにより、通知ハブを使用して、Android デバイスで実行中のアプリにプッシュ通知を送信できます。

プッシュ通知を送信するようにサーバー プロジェクトを更新する

このセクションでは、Mobile Apps の既存のバックエンド プロジェクトのコードを更新して、新しい項目が追加されるたびにプッシュ通知を送信するようにします。 このプロセスは、Azure Notification Hubs のテンプレート機能を使用しており、クロスプラットフォームのプッシュを有効にします。 テンプレートを使用してさまざまなクライアントがプッシュ通知に登録されるため、1 つの汎用プッシュがすべてのクライアント プラットフォームに届きます。

バックエンド プロジェクトの種類 ( .NET バックエンド またはバックエンドNode.js) に一致する次のいずれかの手順 選択します。

.NET バックエンド プロジェクト

  1. Visual Studio で、サーバー プロジェクトを右クリックします。 次に、[NuGet パッケージの管理] を選択します。 Microsoft.Azure.NotificationHubs を検索し、 [インストール] を選択します。 このプロセスにより、バックエンドから通知を送信するための Notification Hubs ライブラリがインストールされます。

  2. サーバー プロジェクトで、 Controllers>TodoItemController.cs を開きます。 次の using ステートメントを追加します。

    using System.Collections.Generic;
    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.Mobile.Server.Config;
    
  3. 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);
    
    // Send the message so that all template registrations that contain "messageParam"
    // 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");
    }
    

    このプロセスにより、新しい項目が挿入されたときに、item.Text を含むテンプレート通知が送信されます。

  4. サーバー プロジェクトを発行します。

Node.js バックエンド プロジェクト

  1. バックエンド プロジェクトを設定します。

  2. todoitem.js 内の既存のコードを、次のコードに置き換えます。

    var azureMobileApps = require('azure-mobile-apps'),
    promises = require('azure-mobile-apps/src/utilities/promises'),
    logger = require('azure-mobile-apps/src/logger');
    
    var table = azureMobileApps.table();
    
    table.insert(function (context) {
    // For more information about the Notification Hubs JavaScript SDK,
    // see https://aka.ms/nodejshubs.
    logger.info('Running TodoItem.insert');
    
    // Define the template payload.
    var payload = '{"messageParam": "' + context.item.text + '" }';  
    
    // Execute the insert. The insert returns the results as a promise.
    // Do the push as a post-execute action within the promise flow.
    return context.execute()
        .then(function (results) {
            // Only do the push if configured.
            if (context.push) {
                // Send a template notification.
                context.push.send(null, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });
            }
            // Don't forget to return the results from the context.execute().
            return results;
        })
        .catch(function (error) {
            logger.error('Error while running context.execute: ', error);
        });
    });
    
    module.exports = table;  
    

    このプロセスにより、新しい項目が挿入されたときに、item.text を含むテンプレート通知が送信されます。

  3. ローカル コンピューターでファイルを編集するときは、サーバー プロジェクトを再発行します。

プッシュ通知のクライアント プロジェクトを構成する

  1. ソリューション ビュー (または Visual Studio の ソリューション エクスプローラー) で、[コンポーネント] フォルダーを右クリックし、[その他のコンポーネントの取得]...をクリックし、Google Cloud Messaging Client コンポーネントを検索してプロジェクトに追加します。

  2. ToDoActivity.cs プロジェクト ファイルを開き、次の using ステートメントをクラスに追加します。

    using Gcm.Client;
    
  3. ToDoActivity クラスに、次の新しいメソッドを追加します。

    // Create a new instance field for this activity.
    static ToDoActivity instance = new ToDoActivity();
    
    // Return the current activity instance.
    public static ToDoActivity CurrentActivity
    {
        get
        {
            return instance;
        }
    }
    // Return the Mobile Services client.
    public MobileServiceClient CurrentClient
    {
        get
        {
            return client;
        }
    }
    

    これにより、プッシュ ハンドラー サービス プロセスからモバイル クライアント インスタンスにアクセスできるようになります。

  4. MobileServiceClient が作成された後で、次のコードを OnCreate メソッドに追加します。

    // Set the current instance of TodoActivity.
    instance = this;
    
    // Make sure the GCM client is set up correctly.
    GcmClient.CheckDevice(this);
    GcmClient.CheckManifest(this);
    
    // Register the app for push notifications.
    GcmClient.Register(this, ToDoBroadcastReceiver.senderIDs);
    

これで、 ToDoActivity は、プッシュ通知を追加するための準備が整いました。

アプリケーションにプッシュ通知コードを追加する

  1. ToDoBroadcastReceiverという名前のプロジェクトに新しいクラスを作成します。

  2. 次の using ステートメントを ToDoBroadcastReceiver クラスに追加します。

    using Gcm.Client;
    using Microsoft.WindowsAzure.MobileServices;
    using Newtonsoft.Json.Linq;
    
  3. 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")]
    //GET_ACCOUNTS is only needed for android versions 4.0.3 and below
    [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
    [assembly: UsesPermission(Name = "android.permission.INTERNET")]
    [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
    
  4. 既存の ToDoBroadcastReceiver クラスの定義を次の内容に置き換えます。

    [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 ToDoBroadcastReceiver : GcmBroadcastReceiverBase<PushHandlerService>
    {
        // Set the Google app ID.
        public static string[] senderIDs = new string[] { "<PROJECT_NUMBER>" };
    }
    

    上記のコードの <PROJECT_NUMBER> を、Google の開発者ポータルでアプリケーションをプロビジョニングしたときに Google によって割り当てられたプロジェクト番号に置き換える必要があります。

  5. ToDoBroadcastReceiver.cs プロジェクト ファイルに、 PushHandlerService クラスを定義する次のコードを追加します。

    // The ServiceAttribute must be applied to the class.
    [Service]
    public class PushHandlerService : GcmServiceBase
    {
        public static string RegistrationID { get; private set; }
        public PushHandlerService() : base(ToDoBroadcastReceiver.senderIDs) { }
    }
    

    このクラスは GcmServiceBase から派生したものであり、このクラスに Service 属性を適用する必要があることに注意してください。

    注意

    GcmServiceBase クラスでは、OnRegistered()OnUnRegistered()OnMessage()OnError() の各メソッドを実装しています。 PushHandlerService クラスでは、これらのメソッドをオーバーライドする必要があります。

  6. OnRegistered イベント ハンドラーをオーバーライドする次のコードを PushHandlerService クラスに追加します。

    protected override void OnRegistered(Context context, string registrationId)
    {
        System.Diagnostics.Debug.WriteLine("The device has been registered with GCM.", "Success!");
    
        // Get the MobileServiceClient from the current activity instance.
        MobileServiceClient client = ToDoActivity.CurrentActivity.CurrentClient;
        var push = client.GetPush();
    
        // Define a message body for GCM.
        const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";
    
        // Define the template registration as JSON.
        JObject templates = new JObject();
        templates["genericMessage"] = new JObject
        {
            {"body", templateBodyGCM }
        };
    
        try
        {
            // Make sure we run the registration on the same thread as the activity, 
            // to avoid threading errors.
            ToDoActivity.CurrentActivity.RunOnUiThread(
    
                // Register the template with Notification Hubs.
                async () => await push.RegisterAsync(registrationId, templates));
    
            System.Diagnostics.Debug.WriteLine(
                string.Format("Push Installation Id", push.InstallationId.ToString()));
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(
                string.Format("Error with Azure push registration: {0}", ex.Message));
        }
    }
    

    このメソッドでは、返された GCM 登録 ID を使用して、プッシュ通知のために Azure に登録します。 タグは、作成後にのみ登録に追加できます。 詳細については、「 方法: タグへのプッシュを有効にするために、タグをデバイス インストールに追加する」を参照してください。

  7. PushHandlerServiceOnMessage メソッドを次のコードでオーバーライドします。

    protected override void OnMessage(Context context, Intent intent)
    {
        string message = string.Empty;
    
        // Extract the push notification message from the intent.
        if (intent.Extras.ContainsKey("message"))
        {
            message = intent.Extras.Get("message").ToString();
            var title = "New item added:";
    
            // Create a notification manager to send the notification.
            var notificationManager = 
                GetSystemService(Context.NotificationService) as NotificationManager;
    
            // Create a new intent to show the notification in the UI. 
            PendingIntent contentIntent =
                PendingIntent.GetActivity(context, 0,
                new Intent(this, typeof(ToDoActivity)), 0);
    
            // Create the notification using the builder.
            var builder = new Notification.Builder(context);
            builder.SetAutoCancel(true);
            builder.SetContentTitle(title);
            builder.SetContentText(message);
            builder.SetSmallIcon(Resource.Drawable.ic_launcher);
            builder.SetContentIntent(contentIntent);
            var notification = builder.Build();
    
            // Display the notification in the Notifications Area.
            notificationManager.Notify(1, notification);
    
        }
    }
    
  8. OnUnRegistered() メソッドと OnError() メソッドを次のコードでオーバーライドします。

    protected override void OnUnRegistered(Context context, string registrationId)
    {
        throw new NotImplementedException();
    }
    
    protected override void OnError(Context context, string errorId)
    {
        System.Diagnostics.Debug.WriteLine(
            string.Format("Error occurred in the notification: {0}.", errorId));
    }
    

アプリケーションでプッシュ通知をテストする

エミュレーターで仮想デバイスを使用して、アプリをテストできます。 エミュレーターで実行するときに必要な追加の構成手順があります。

  1. 仮想デバイスには、Android Virtual Device (AVD) Manager で Google API をターゲットとして設定する必要があります。

  2. [アプリ>設定>] をクリックして Google アカウントを Android デバイスに追加し、画面の指示に従います。

  3. これまでと同様に ToDoList アプリを実行し、新しい ToDo 項目を挿入します。 今回は、通知領域に通知アイコンが表示されます。 通知ドロアーを開いて、通知の全文を表示できます。