チュートリアル:Azure Notification Hubs と Google Cloud Messaging を使用して Android デバイスにプッシュ通知を送信する (非推奨)

警告

2018 年 4 月 10 日に、Google は Google Cloud Messaging (GCM) を非推奨としました。 GCM サーバーおよびクライアント API は非推奨となり、早ければ 2019 年 5 月 29日に削除されます。 詳しくは、GCM and FCM Frequently Asked Questions を参照してください。

概要

このチュートリアルでは、Azure Notification Hubs を使用して Android アプリケーションにプッシュ通知を送信する方法について説明します。 Google Cloud Messaging (GCM) を使用してプッシュ通知を受信する空の Android アプリを作成します。

重要

Google Cloud Messaging (GCM) は非推奨となり、まもなく削除される予定です。

重要

このトピックでは、Google Cloud Messaging (GCM) を使用したプッシュ通知について説明します。 Google の Firebase Cloud Messaging (FCM) を使用している場合は、 Azure Notification Hubs と FCM を使用した Android へのプッシュ通知の送信に関する記事を参照してください。

このチュートリアルの完成したコードについては、GitHub の こちらからダウンロードできます。

このチュートリアルでは、次のアクションを実行します。

  • Google Cloud Messaging をサポートするプロジェクトを作成します。
  • 通知ハブを作成する
  • 通知ハブにアプリケーションを接続する
  • アプリケーションをテストする

前提条件

Google Cloud Messaging をサポートするプロジェクトを作成する

  1. Google Cloud Consoleに移動し、Google アカウントの資格情報でサインインします。

  2. ツールバーの [プロジェクトの作成] を選択します。

    新しいプロジェクトの作成

  3. [プロジェクト名] にプロジェクトの名前を入力し、[作成] をクリックします。

  4. ツールバーの [通知] ボタンを選択し、一覧から自分のプロジェクトを選択します。 プロジェクトのダッシュ ボードが表示されます。 URL "https://console.developers.google.com/home/dashboard?project=<YOUR PROJECT NAME>" を使用してダッシュボードに直接アクセスすることもできます。

    [通知] でプロジェクトを選択する

  5. ダッシュボードの [プロジェクト情報] タイルにある プロジェクト番号 をメモしておきます。

    プロジェクト ID

  6. ダッシュボードの [API] タイルで、[API の概要に移動] を選択します。

    API 概要へのリンク

  7. [API] ページで [API とサービスの有効化] を選択します。

    [API とサービスの有効化] ボタン

  8. [Google Cloud Messaging] を探して選択します。

    Google Cloud Messaging を探して選択

  9. プロジェクトで [Google Cloud Messaging] を有効にするには、[有効にする] を選択します。

    Google Cloud Messaging を有効にする

  10. ツールバーで [認証情報を作成] を選択します。

    [認証情報を作成] ボタン

  11. [プロジェクトへの認証情報の追加] ページで、[API キー] リンクを選択します。

    資格情報を追加する

  12. [API キー] ページで、[Create/Save](作成/保存) を選択します。 次の例では、[IP アドレス] のオプションが選択され、許可されている IP アドレスとして 0.0.0.0/0 が入力されています。 API キーには適切な制限を設定する必要があります。

    [API キー] ページの [Create](作成) ボタン

  13. API キー をクリップボードにコピーして、任意の場所に保存します。

    API キーをコピーする

    この API キー値を使用して、Azure が GCM で認証し、アプリの代わりにプッシュ通知を送信できるようにします。 プロジェクト ダッシュボードに戻るには、URL "https://console.developers.google.com/home/dashboard?project=<YOUR PROJECT NAME>" を使用します。

通知ハブを作成する

  1. Azure portal にサインインする

  2. 左側のメニューで [すべてのサービス] を選択し、 [モバイル] セクションの [Notification Hubs] を選択します。 サービス名の横にある星のアイコンを選択して、左側のメニューにある [お気に入り] セクションにサービスを追加します。 Notification Hubs[お気に入り] に追加した後、左側のメニューでそれを選択します。

    Azure portal - Notification Hubs を選択する

  3. [Notification Hubs] ページで、ツール バーの [追加] を選択します。

    Notification Hubs - [追加] ツール バー ボタン

  4. [Notification Hub] ページで、次の手順のようにします。

    1. [通知ハブ] に名前を入力します。

    2. [新しい名前空間の作成] に名前を入力します。 名前空間には、少なくとも 1 つのハブが存在します。

    3. [場所] ドロップダウン リスト ボックスで値を選択します。 この値には、ハブを作成する場所を指定します。

    4. [リソース グループ] で既存のリソース グループを選択します。または、新しいリソース グループに名前を作成します。

    5. 作成 を選択します。

      Azure Portal - 通知ハブのプロパティを設定

  5. [通知] (ベルのアイコン) を選択し、 [リソースに移動] を選択します。 [Notification Hubs] ページの一覧を最新の情報に更新して、お使いの通知ハブを選択することもできます。

    Azure portal - リソースに移動

  6. リストから [アクセス ポリシー] を選択します。 使用可能な 2 つの接続文字列を書き留めてください。 これらは、後でプッシュ通知を処理するために必要になります。

    重要

    DefaultFullSharedAccessSignature ポリシーはアプリケーションで使用 "しない" でください。 これの使用が意図されているのはバックエンドだけです。

    Azure Portal - 通知ハブの接続文字列

GCM の設定を通知ハブ用に構成する

  1. [通知設定][Google (GCM)] を選択します。

  2. Google Cloud Console から取得した API キー を入力します。

  3. ツールバーの [保存] を選択します。

    Azure Notification Hubs - Google (GCM)

これで、通知ハブが GCM と連動するように構成されました。接続文字列を使用して、プッシュ通知の受信と送信の両方にアプリを登録できます。

通知ハブにアプリを接続する

新しい Android プロジェクトを作成する

  1. Android Studio で新しい Android Studio プロジェクトを開始する

    Android Studio - new project

  2. [Phone and Tablet (電話とタブレット)] フォーム ファクターを選択し、サポートする [Minimum SDK (最低限の SDK)] を選択します。 続けて、 [次へ] をクリックします。

    Android Studio - project creation workflow

  3. メイン アクティビティに [Empty Activity (空のアクティビティ)] を選択し、 [Next (次へ)] をクリックして、 [Finish (完了)] をクリックします。

プロジェクトへの Google Play Services の追加

  1. Android Studio で、メニューから [ツール] を選択し、 [SDK Manager] を選択します。

  2. 自分のプロジェクトで使用される Android SDK のターゲット バージョンを選択します。 次に、 [パッケージの詳細ページの表示] を選択します。

    Android SDK Manager - ターゲット バージョンを選択する

  3. まだインストールされていない場合は、 [Google API] を選択します。

    Android SDK Manager - Google API の選択

  4. [SDK Tools](SDK ツール) タブに切り替えます。Google Play 開発者サービスをまだインストールしていない場合は、次の図に示すように [Google Play 開発者サービス] を選択します。 次に、 [適用] をクリックしてインストールします。 SDK のパスは後の手順で使用するので、メモしておいてください。

    Android SDK Manager - Google Play 開発者サービスの選択

  5. [Confirm Change](変更の確認) ダイアログ ボックスが表示される場合は、 [OK] を選択します。 コンポーネント インストーラーによって、要求したコンポーネントがインストールされます。 コンポーネントがインストールされた後、 [Finish](完了) を選択します。

  6. [OK] を選択して、 [Settings for New Projects](新しいプロジェクトの設定) ダイアログ ボックスを閉じます。

  7. app ディレクトリの build.gradle ファイルを開き、dependencies の下に次の行を追加します。

    implementation 'com.google.android.gms:play-services-gcm:16.0.0'
    
  8. ツール バーの [今すぐ同期] アイコンを選択します。

    Gradle と同期する

  9. AndroidManifest.xml ファイルを開き、次のタグを application タグに追加します。

    <meta-data android:name="com.google.android.gms.version"
         android:value="@integer/google_play_services_version" />
    

Azure Notification Hubs ライブラリを追加する

  1. [app (アプリ)]Build.Gradle ファイルの dependencies セクションに次の行を追加します。

    implementation 'com.microsoft.azure:notification-hubs-android-sdk:0.6@aar'
    implementation 'com.microsoft.azure:azure-notifications-handler:1.0.1@aar'
    
  2. [dependencies] セクションの後に次のリポジトリを追加します。

    repositories {
        maven {
            url "https://dl.bintray.com/microsoftazuremobile/SDK"
        }
    }
    

プロジェクトの AndroidManifest.xml を更新する

  1. GCM をサポートするには、Google のインスタンス ID API を使用して、登録トークンを取得するために使用されるインスタンス ID リスナー サービスをコード内に実装します。 このチュートリアルでは、クラスの名前は MyInstanceIDService です。

    次のサービス定義を AndroidManifest.xml ファイルの <application> タグ内に追加します。 <your package> プレースホルダーを、AndroidManifest.xml ファイルの先頭にある実際のパッケージ名に置き換えます。

    <service android:name="<your package>.MyInstanceIDService" android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>
    
  2. アプリケーションは、インスタンス ID API から GCM 登録トークンを受信した後、そのトークンを使用して Azure 通知ハブに登録します。 この登録は、RegistrationIntentService という名前の IntentService を使用してバックグラウンドで実行されます。 このサービスは、GCM 登録トークンを更新する役割を果たします。

    次のサービス定義を AndroidManifest.xml ファイルの <application> タグ内に追加します。 <your package> プレースホルダーを、AndroidManifest.xml ファイルの先頭にある実際のパッケージ名に置き換えます。

    <service
        android:name="<your package>.RegistrationIntentService"
        android:exported="false">
    </service>
    
  3. 通知を受信するレシーバーを定義します。 次のレシーバー定義を AndroidManifest.xml ファイルの <application> タグ内に追加します。 <your package> プレースホルダーを、AndroidManifest.xml ファイルの先頭にある実際のパッケージ名に置き換えます。

    <receiver android:name="com.microsoft.windowsazure.notifications.NotificationsBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="<your package name>" />
        </intent-filter>
    </receiver>
    
  4. 次の必要な GCM アクセス許可を <application> タグの下に追加します。 <your package>AndroidManifest.xml ファイルの先頭に示されているパッケージ名に置き換えます。

    これらのアクセス許可の詳細については、Android 用 GCM Client アプリの設定に関するページを参照してください。

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    
    <permission android:name="<your package>.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="<your package>.permission.C2D_MESSAGE"/>
    

コードを追加する

  1. [Project (プロジェクト)] ビューで、 [app] > [src] > [main] > [java] の順に展開します。 [java] のパッケージ フォルダーを右クリックして、 [New (新規)][Java Class (Java クラス)] の順にクリックします。 NotificationSettingsという名前の新しいクラスを追加します。

    Android Studio - new Java class

    NotificationSettings クラスの次のコードにある 3 つのプレースホルダーを更新します。

    • SenderId:Google Cloud Console で取得しておいたプロジェクト番号。

    • HubListenConnectionString:ハブの DefaultListenAccessSignature 接続文字列。 その接続文字列は、Azure Portal のハブの [設定] ページで [アクセス ポリシー] をクリックすることによってコピーできます。

    • HubName:Azure portal のハブ ページに表示される通知ハブの名前を使用します。

      NotificationSettings のコードは次のとおりです。

      public class NotificationSettings {
         public static String SenderId = "<Your project number>";
         public static String HubName = "<Your HubName>";
         public static String HubListenConnectionString = "<Your default listen connection string>";
      }
      
  2. MyInstanceIDService という名前の別の新しいクラスを追加します。 このクラスは、インスタンス ID リスナー サービスの実装です。

    このクラスのコードが IntentService を呼び出して、バックグラウンドで GCM トークンを更新します

    import android.content.Intent;
    import android.util.Log;
    import com.google.android.gms.iid.InstanceIDListenerService;
    
    public class MyInstanceIDService extends InstanceIDListenerService {
    
        private static final String TAG = "MyInstanceIDService";
    
        @Override
        public void onTokenRefresh() {
    
            Log.i(TAG, "Refreshing GCM Registration Token");
    
            Intent intent = new Intent(this, RegistrationIntentService.class);
            startService(intent);
        }
    };
    
  3. RegistrationIntentService という名前の別の新しいクラスをプロジェクトに追加します。 このクラスは、GCM トークンの更新通知ハブへの登録を処理する IntentService を実装します。

    次のコードをこのクラスに使用します。

    import android.app.IntentService;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.preference.PreferenceManager;
    import android.util.Log;
    
    import com.google.android.gms.gcm.GoogleCloudMessaging;
    import com.google.android.gms.iid.InstanceID;
    import com.microsoft.windowsazure.messaging.NotificationHub;
    
    public class RegistrationIntentService extends IntentService {
    
        private static final String TAG = "RegIntentService";
    
        private NotificationHub hub;
    
        public RegistrationIntentService() {
            super(TAG);
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
            String resultString = null;
            String regID = null;
    
            try {
                InstanceID instanceID = InstanceID.getInstance(this);
                String token = instanceID.getToken(NotificationSettings.SenderId,
                        GoogleCloudMessaging.INSTANCE_ID_SCOPE);
                Log.i(TAG, "Got GCM Registration Token: " + token);
    
                // Storing the registration id that indicates whether the generated token has been
                // sent to your server. If it is not stored, send the token to your server,
                // otherwise your server should have already received the token.
                if ((regID=sharedPreferences.getString("registrationID", null)) == null) {
                    NotificationHub hub = new NotificationHub(NotificationSettings.HubName,
                            NotificationSettings.HubListenConnectionString, this);
                    Log.i(TAG, "Attempting to register with NH using token : " + token);
    
                    regID = hub.register(token).getRegistrationId();
    
                    // If you want to use tags...
                    // Refer to : https://azure.microsoft.com/documentation/articles/notification-hubs-routing-tag-expressions/
                    // regID = hub.register(token, "tag1", "tag2").getRegistrationId();
    
                    resultString = "Registered Successfully - RegId : " + regID;
                    Log.i(TAG, resultString);
                    sharedPreferences.edit().putString("registrationID", regID ).apply();
                } else {
                    resultString = "Previously Registered Successfully - RegId : " + regID;
                }
            } catch (Exception e) {
                Log.e(TAG, resultString="Failed to complete token refresh", e);
                // If an exception happens while fetching the new token or updating the registration data
                // on a third-party server, this ensures that we'll attempt the update at a later time.
            }
    
            // Notify UI that registration has completed.
            if (MainActivity.isVisible) {
                MainActivity.mainActivity.ToastNotify(resultString);
            }
        }
    }
    
  4. MainActivity クラスで、そのクラスの先頭に次の import ステートメントを追加します。

    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.GoogleApiAvailability;
    import com.google.android.gms.gcm.*;
    import com.microsoft.windowsazure.notifications.NotificationsManager;
    import android.util.Log;
    import android.widget.TextView;
    import android.widget.Toast;
    import android.content.Intent;
    
  5. クラスの最上位に、次のプライベート メンバーを追加します。 このコードは、Google の推奨に従って Google Play 開発者サービスの可用性をチェックします

    public static MainActivity mainActivity;
    public static Boolean isVisible = false;
    private GoogleCloudMessaging gcm;
    private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    private static final String TAG = "MainActivity";
    
  6. MainActivity クラスに、Google Play Services が利用可能かどうかを確認する次のメソッドを追加します。

    /**
        * Check the device to make sure it has the Google Play Services APK. If
        * it doesn't, display a dialog that allows users to download the APK from
        * the Google Play Store or enable it in the device's system settings.
        */
    private boolean checkPlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (apiAvailability.isUserResolvableError(resultCode)) {
                apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                        .show();
            } else {
                Log.i(TAG, "This device is not supported by Google Play Services.");
                ToastNotify("This device is not supported by Google Play Services.");
                finish();
            }
            return false;
        }
        return true;
    }
    
  7. MainActivity クラスで、IntentService を呼び出して GCM 登録トークンを取得したり、通知ハブに登録したりする前に Google Play 開発者サービスをチェックする次のコードを追加します。

    public void registerWithNotificationHubs()
    {
        Log.i(TAG, " Registering with Notification Hubs");
    
        if (checkPlayServices()) {
            // Start IntentService to register this application with GCM.
            Intent intent = new Intent(this, RegistrationIntentService.class);
            startService(intent);
        }
    }
    
  8. MainActivity クラスの OnCreate メソッドで、アクティビティの作成時に登録プロセスを開始するために次のコードを追加します。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mainActivity = this;
        NotificationsManager.handleNotifications(this, NotificationSettings.SenderId, MyHandler.class);
        registerWithNotificationHubs();
    }
    
  9. 次の追加メソッドを MainActivity に追加して、アプリの状態を確認してアプリ内で報告します。

    @Override
    protected void onStart() {
        super.onStart();
        isVisible = true;
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        isVisible = false;
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        isVisible = true;
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        isVisible = false;
    }
    
    public void ToastNotify(final String notificationMessage) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, notificationMessage, Toast.LENGTH_LONG).show();
                TextView helloText = (TextView) findViewById(R.id.text_hello);
                helloText.setText(notificationMessage);
            }
        });
    }
    
  10. ToastNotify メソッドでは "Hello World" TextView コントロールを使用し、アプリで状態と通知を継続的にレポートします。 activity_main.xml レイアウトでは、そのコントロールに次の ID を追加します。

    android:id="@+id/text_hello"
    
  11. AndroidManifest.xml で定義されているレシーバーのサブクラスを追加します。 MyHandlerという名前の別の新しいクラスをプロジェクトに追加します。

  12. 次の import ステートメントを MyHandler.java の先頭に追加します。

    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v4.app.NotificationCompat;
    import com.microsoft.windowsazure.notifications.NotificationsHandler;
    import android.net.Uri;
    import android.media.RingtoneManager;
    
  13. MyHandler クラス用に次のコードを追加して、com.microsoft.windowsazure.notifications.NotificationsHandler のサブクラスにします。

    このコードによって OnReceive メソッドがオーバーライドされるため、ハンドラーは受信した通知を報告します。 ハンドラーは sendNotification() メソッドを使用して Android の通知マネージャーにもプッシュ通知を送信します。 sendNotification() メソッドは、アプリが動作していないときに通知を受信した場合に実行される必要があります。

    public class MyHandler extends NotificationsHandler {
        public static final int NOTIFICATION_ID = 1;
        private NotificationManager mNotificationManager;
        NotificationCompat.Builder builder;
        Context ctx;
    
        @Override
        public void onReceive(Context context, Bundle bundle) {
            ctx = context;
            String nhMessage = bundle.getString("message");
            sendNotification(nhMessage);
            if (MainActivity.isVisible) {
                MainActivity.mainActivity.ToastNotify(nhMessage);
            }
        }
    
        private void sendNotification(String msg) {
    
            Intent intent = new Intent(ctx, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
            mNotificationManager = (NotificationManager)
                    ctx.getSystemService(Context.NOTIFICATION_SERVICE);
    
            PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
                    intent, PendingIntent.FLAG_ONE_SHOT);
    
            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(ctx)
                            .setSmallIcon(R.mipmap.ic_launcher)
                            .setContentTitle("Notification Hub Demo")
                            .setStyle(new NotificationCompat.BigTextStyle()
                                    .bigText(msg))
                            .setSound(defaultSoundUri)
                            .setContentText(msg);
    
            mBuilder.setContentIntent(contentIntent);
            mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
        }
    }
    
  14. Android Studio のメニュー バーで、 [Build (ビルド)] > [Rebuild Project (プロジェクトのリビルド)] の順にクリックし、コードにエラーがないことを確認します。

アプリケーションのテスト

モバイル アプリケーションを実行する

  1. アプリケーションを実行し、登録 ID の登録完了が報告されていることを確認します。

    Testing on Android - Channel registration

  2. ハブに登録されているすべての Android デバイスに送信される通知メッセージを入力します。

    Testing on Android - sending a message

  3. [Send Notification (通知の送信)] を押します。 アプリケーションが実行されているすべてのデバイスで、プッシュ通知メッセージを示す AlertDialog インスタンスが表示されます。 実行中のアプリケーションがなくても事前にプッシュ通知に登録されているデバイスでは、Android 通知マネージャーで通知が受信されます。 通知メッセージは、左上隅から下へスワイプすることによって表示できます。

    Testing on Android - notifications

Azure Portal からプッシュ通知をテスト送信する

Azure Portal からプッシュ通知を送信することによって、それらの通知のアプリでの受信をテストできます。

  1. [トラブルシューティング] セクションで、 [テスト送信] を選択します。

  2. [プラットフォーム] として、 [Android] を選択します。

  3. [送信] を選択してテスト通知を送信します。

  4. Android デバイスに通知メッセージが表示されることを確認します。

    Azure Notification Hubs - Test Send

プッシュ通知は通常、互換性のあるライブラリを使用して Mobile Apps などのバックエンド サービスや ASP.NET に送信されます。 ライブラリがバックエンドに使用できない場合は、REST API を直接使用して通知メッセージを送信することもできます。

通知の送信方法を確認できるチュートリアルの一覧を次に示します。

エミュレーターでのプッシュ通知

エミュレーターの内部でプッシュ通知をテストする場合は、エミュレーター イメージがアプリケーション用に選択した Google API レベルをサポートしていることを確認してください。 イメージがネイティブの Google API をサポートしていない場合は、最終的に SERVICE_NOT_AVAILABLE 例外を受け取ることになります。

さらに、 [設定] > [アカウント] で、実行中のエミュレーターに Google アカウントを追加したことを確認します。 アカウントを追加していないと、GCM での登録の試行が AUTHENTICATION_FAILED 例外につながる可能性があります。

(省略可能) アプリから直接プッシュ通知を送信する

通常は、バックエンド サーバーを使用して通知を送信します。 場合によっては、クライアント アプリケーションから直接プッシュ通知を送信できることが必要になります。 このセクションでは、 Azure Notification Hubs REST APIを使用してクライアントから通知を送信する方法を説明します。

  1. Android Studio の [Project (プロジェクト)] ビューで [app] > [src] > [main] > [res] > [layout] の順に展開します。 activity_main.xml レイアウト ファイルを開き、 [Text (テキスト)] タブをクリックしてファイルのテキストの内容を更新します。 次のコードで更新します。これにより、通知ハブにプッシュ通知メッセージを送信するための新しい Button コントロールと EditText コントロールが追加されます。 このコードは一番下の </RelativeLayout> のすぐ前に追加します。

    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/send_button"
    android:id="@+id/sendbutton"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:onClick="sendNotificationButtonOnClick" />
    
    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/editTextNotificationMessage"
    android:layout_above="@+id/sendbutton"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="42dp"
    android:hint="@string/notification_message_hint" />
    
  2. Android Studio の [Project (プロジェクト)] ビューで [app] > [src] > [main] > [res] > [values] の順に展開します。 strings.xml ファイルを開き、新しい Button コントロールと EditText コントロールで参照される文字列の値を追加します。 ファイルの一番下の </resources> の直前に次の行を追加します。

    <string name="send_button">Send Notification</string>
    <string name="notification_message_hint">Enter notification message text</string>
    
  3. NotificationSetting.java ファイルで、次の設定を NotificationSettings クラスに追加します。

    HubFullAccess をハブの DefaultFullSharedAccessSignature 接続文字列で更新します。 この接続文字列は、通知ハブの [設定] ページで [アクセス ポリシー] をクリックすることによって Azure Portal からコピーできます。

    public static String HubFullAccess = "<Enter Your DefaultFullSharedAccess Connection string>";
    
  4. MainActivity.java ファイルで、そのファイルの先頭に次の import ステートメントを追加します。

    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLEncoder;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import android.util.Base64;
    import android.view.View;
    import android.widget.EditText;
    
  5. MainActivity.java ファイルで、MainActivity クラスの先頭に次のメンバーを追加します。

    private String HubEndpoint = null;
    private String HubSasKeyName = null;
    private String HubSasKeyValue = null;
    
  6. 通知ハブにメッセージを送信するには、POST 要求を認証するための Shared Access Signature (SaS) トークンを作成します。 接続文字列のキー データを解析してから、「共通概念」の REST API リファレンスの説明に従って SaS トークンを作成します。 次のコードでは、実装例を示します。

    MainActivity.java で、接続文字列を解析する次のメソッドを MainActivity クラスに追加します。

    /**
        * Example code from https://msdn.microsoft.com/library/azure/dn495627.aspx
        * to parse the connection string so a SaS authentication token can be
        * constructed.
        *
        * @param connectionString This must be the DefaultFullSharedAccess connection
        *                         string for this example.
        */
    private void ParseConnectionString(String connectionString)
    {
        String[] parts = connectionString.split(";");
        if (parts.length != 3)
            throw new RuntimeException("Error parsing connection string: "
                    + connectionString);
    
        for (int i = 0; i < parts.length; i++) {
            if (parts[i].startsWith("Endpoint")) {
                this.HubEndpoint = "https" + parts[i].substring(11);
            } else if (parts[i].startsWith("SharedAccessKeyName")) {
                this.HubSasKeyName = parts[i].substring(20);
            } else if (parts[i].startsWith("SharedAccessKey")) {
                this.HubSasKeyValue = parts[i].substring(16);
            }
        }
    }
    
  7. MainActivity.java で、SAS 認証トークンを作成する次のメソッドを MainActivity クラスに追加します。

    /**
        * Example code from https://msdn.microsoft.com/library/azure/dn495627.aspx to
        * construct a SaS token from the access key to authenticate a request.
        *
        * @param uri The unencoded resource URI string for this operation. The resource
        *            URI is the full URI of the Service Bus resource to which access is
        *            claimed. For example,
        *            "http://<namespace>.servicebus.windows.net/<hubName>"
        */
    private String generateSasToken(String uri) {
    
        String targetUri;
        String token = null;
        try {
            targetUri = URLEncoder
                    .encode(uri.toString().toLowerCase(), "UTF-8")
                    .toLowerCase();
    
            long expiresOnDate = System.currentTimeMillis();
            int expiresInMins = 60; // 1 hour
            expiresOnDate += expiresInMins * 60 * 1000;
            long expires = expiresOnDate / 1000;
            String toSign = targetUri + "\n" + expires;
    
            // Get an hmac_sha1 key from the raw key bytes
            byte[] keyBytes = HubSasKeyValue.getBytes("UTF-8");
            SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
    
            // Get an hmac_sha1 Mac instance and initialize with the signing key
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(signingKey);
    
            // Compute the hmac on input data bytes
            byte[] rawHmac = mac.doFinal(toSign.getBytes("UTF-8"));
    
            // Using android.util.Base64 for Android Studio instead of
            // Apache commons codec
            String signature = URLEncoder.encode(
                    Base64.encodeToString(rawHmac, Base64.NO_WRAP).toString(), "UTF-8");
    
            // Construct authorization string
            token = "SharedAccessSignature sr=" + targetUri + "&sig="
                    + signature + "&se=" + expires + "&skn=" + HubSasKeyName;
        } catch (Exception e) {
            if (isVisible) {
                ToastNotify("Exception Generating SaS : " + e.getMessage().toString());
            }
        }
    
        return token;
    }
    
  8. MainActivity.java で、次のメソッドを MainActivity クラスに追加します。このメソッドは [Send Notification] ボタンのクリックを処理し、組み込みの REST API を使用してハブにプッシュ通知メッセージを送信します。

    /**
        * Send Notification button click handler. This method parses the
        * DefaultFullSharedAccess connection string and generates a SaS token. The
        * token is added to the Authorization header on the POST request to the
        * notification hub. The text in the editTextNotificationMessage control
        * is added as the JSON body for the request to add a GCM message to the hub.
        *
        * @param v
        */
    public void sendNotificationButtonOnClick(View v) {
        EditText notificationText = (EditText) findViewById(R.id.editTextNotificationMessage);
        final String json = "{\"data\":{\"message\":\"" + notificationText.getText().toString() + "\"}}";
    
        new Thread()
        {
            public void run()
            {
                try
                {
                    // Based on reference documentation...
                    // https://msdn.microsoft.com/library/azure/dn223273.aspx
                    ParseConnectionString(NotificationSettings.HubFullAccess);
                    URL url = new URL(HubEndpoint + NotificationSettings.HubName +
                            "/messages/?api-version=2015-01");
    
                    HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
    
                    try {
                        // POST request
                        urlConnection.setDoOutput(true);
    
                        // Authenticate the POST request with the SaS token
                        urlConnection.setRequestProperty("Authorization",
                            generateSasToken(url.toString()));
    
                        // Notification format should be GCM
                        urlConnection.setRequestProperty("ServiceBusNotification-Format", "gcm");
    
                        // Include any tags
                        // Example below targets 3 specific tags
                        // Refer to : https://azure.microsoft.com/documentation/articles/notification-hubs-routing-tag-expressions/
                        // urlConnection.setRequestProperty("ServiceBusNotification-Tags",
                        //        "tag1 || tag2 || tag3");
    
                        // Send notification message
                        urlConnection.setFixedLengthStreamingMode(json.length());
                        OutputStream bodyStream = new BufferedOutputStream(urlConnection.getOutputStream());
                        bodyStream.write(json.getBytes());
                        bodyStream.close();
    
                        // Get response
                        urlConnection.connect();
                        int responseCode = urlConnection.getResponseCode();
                        if ((responseCode != 200) && (responseCode != 201)) {
                            BufferedReader br = new BufferedReader(new InputStreamReader((urlConnection.getErrorStream())));
                            String line;
                            StringBuilder builder = new StringBuilder("Send Notification returned " +
                                    responseCode + " : ")  ;
                            while ((line = br.readLine()) != null) {
                                builder.append(line);
                            }
    
                            ToastNotify(builder.toString());
                        }
                    } finally {
                        urlConnection.disconnect();
                    }
                }
                catch(Exception e)
                {
                    if (isVisible) {
                        ToastNotify("Exception Sending Notification : " + e.getMessage().toString());
                    }
                }
            }
        }.start();
    }
    

次のステップ

このチュートリアルでは、バックエンドに登録されているすべての Android デバイスにブロードキャスト通知を送信しました。 特定の Android デバイスにプッシュ通知を送信する方法を学習するには、次のチュートリアルに進んでください。