読者です 読者をやめる 読者になる 読者になる

Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

Xamarin.Android で Azure Mobile Service の PUSH 通知を使う

こんにちは。エクセルソフトの田淵です。

友人が PUSH 通知を使ったアプリを作りたいというので Microsoft Azure を調べています。

事前準備

まずは Microsoft Azure モバイルサービスのチュートリアルに沿って ToDo アプリを作ってみます。

チュートリアルの ToDo アプリについては、技術評論社@nnasaki さんが連載している 第1回 Windows Azureモバイルサービスの基礎:Windows Azureモバイルサービスで始めるスマホアプリ開発|gihyo.jp … 技術評論社 の第4回までを読んでください。

f:id:ytabuchi:20150427100438p:plain:w450
こんな感じで作っていきます。

チュートリアルも日本語になっている のでここは特に躓かないと思います。

Visual Studio でやっている場合は、Package を Restore してあげましょう。
f:id:ytabuchi:20150427103026p:plain:w450

なお、このチュートリアルを Xamarin.Forms でやる方法については id:furuya02 さんが Xamarni.Forms AzureモバイルサービスによるToDoアプリ - SIN@SAPPOROWORKSの覚書 で紹介くださっていますので、併せてご参照ください。

実行すると

f:id:ytabuchi:20150427100607p:plain:w300

こんな感じで Azure のデータベースのデータを 追加/参照/doneにマーク などが出来るアプリができます。

連載でも触れていますが、Azure モバイルサービスは無料枠がありますので、是非遊んでみてください。

PUSH 通知の実装

さて、本題です。

ToDo アプリのチュートリアルページ の最後に、 「次のステップ」として プッシュ通知の使用 - Mobile Services へのリンクがありますが、日本語になっていないので、英語のドキュメントネイティブの Android 用のドキュメントの日本語訳 を見ながら進めたいと思います。

なお、この PUSH 通知のチュートリアルに間違いが山ほどあるのでこのエントリーでは注意点やドキュメントとの相違点を記載していきます。

手順としては以下になります。

  1. Google Cloud Messaging を有効にする
  2. プッシュ要求を送信するように Mobile Services を構成する
  3. アプリケーションにプッシュ通知を追加する
  4. プッシュ通知を送信するようにスクリプトを更新する
  5. アプリケーションでプッシュ通知をテストする

3 のアプリケーションの通知を追加する部分のみネイティブと異なりますが、その他は同じですので、ネイティブ Android のドキュメント をご覧ください。

1. Google Cloud Messaging を有効にする

ほぼ手順書通りです が、Google Developer Console の画面が少し新しくなっています。

プロジェクトを追加したら、概要ページの上に表示される プロジェクト番号 を控えておきます。次に API と認証 > API をクリックして、cloud android で検索して、Google Cloud Messaging for Android を有効にします。

f:id:ytabuchi:20150427123934p:plain:w450

f:id:ytabuchi:20150427123943p:plain:w450

APIと認証 > 認証情報 から 新しいキーを生成 をクリックして、サーバーキー を生成します。(Android キーではありませんので注意です)

f:id:ytabuchi:20150427124336p:plain:w450

生成された APIキー を控えておきます。

f:id:ytabuchi:20150427124700p:plain:w450

2. プッシュ要求を送信するように Mobile Services を構成する

ここは手順書通りです。

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

問題のアプリ部分です。

Configure the existing project for push notifications のパート

プロジェクトを開きます。

Components フォルダを右クリックして、Get More Components... から Google Cloud Messagin ClientAdd to App します。
f:id:ytabuchi:20150427125509p:plain:w450

ToDoActivity.cs を開き、using Gcm.Client; を追加します。

ToDoActivity クラスに以下を追加します。

// このアクティビティに新しいインスタンスを作成します。
static ToDoActivity instance = new ToDoActivity();

// 現在のアクティビティインスタンスを返します。
public static ToDoActivity CurrentActivity
{
    get
    {
        return instance;
    }
}
// モバイルサービスクライアントを返します。
public MobileServiceClient CurrentClient
{
    get
    {
        return client;
    }
}

既存の Mobile Services client の宣言を public に変更します。

public MobileServiceClient client { get; private set; }

OnCreate メソッドの MobileServiceClient をインスタンス化した後に以下を追加します。

// ToDoActivity の現在のインスタンスをセットします。
instance = this;

// GCM client が正しくセットアップされているかチェックします。
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);

// プッシュ通知にアプリを登録します。
GcmClient.Register(this, ToDoBroadcastReceiver.senderIDs);

これで ToDoActivity が PUSH 通知を追加する準備が整いました。

Add push notifications code to your app のパート

PUSH 通知受け取り部分を作成します。

ToDoBroadcastReceiver クラス を作成します。

using を追加します。

using Gcm.Client;
using Microsoft.WindowsAzure.MobileServices;

permission のリクエストを using ステートメントと namespace 宣言の間に追加します。

[assembly: Permission(Name = "<アプリのパッケージ名>.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "<アプリのパッケージ名>.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]

//GET_ACCOUNTS は Android 4.0.3 以下で必要です。
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]

既存の ToDoBroadcastReceiver クラスの定義を以下で置き換えます。
ドキュメントでは、継承する GcmBroadcastReceiverBase<TIntentService> の <TIntentService> が <GcmService> になっていますが正しくは <PushHandlerService> です。

[BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE },
    Categories = new string[] { "<アプリのパッケージ名>" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK },
    Categories = new string[] { "<アプリのパッケージ名>" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY },
    Categories = new string[] { "<アプリのパッケージ名>" })]

// 【注意】ドキュメントでは <TIntentService> が <GcmService> ですが、正しくは <PushHandlerService> です。
public class ToDoBroadcastReceiver : GcmBroadcastReceiverBase<PushHandlerService>
{
    // 「Google Cloud Messaging を有効にする」で控えておいた プロジェクト番号 を記述してください。
    public static string[] senderIDs = new string[] { "568586192081" };
}

ToDoBroadcastReceiver.cs 内に PushHandlerService クラスを定義する以下のコードを追加します

// このサービス定義はこのクラスに適用しなければいけません。
[Service] 
public class PushHandlerService : GcmServiceBase
{
    public static string RegistrationID { get; private set; }

    public PushHandlerService() : base(ToDoBroadcastReceiver.senderIDs) { }
}

GcmServiceBase クラスは OnRegistered(), OnUnRegistered(), OnMessage() と OnError() を実装しなければいけないので、これらを override します。

PushHandlerService クラスで OnRegistered イベントハンドラーを override します。
【注意】ドキュメントでは ToDoBroadcastReceiver クラスで override せよ。と書いてありますが、GcmServiceBase が OnRegisterd() などを実装しろと書いてある通り、正しくは 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();

    List<string> tags = null;

    //// (Optional) Uncomment to add tags to the registration.
    //var tags = new List<string>() { "myTag" }; // create tags if you want

    try
    {
        // Make sure we run the registration on the same thread as the activity, 
        // to avoid threading errors.
        ToDoActivity.CurrentActivity.RunOnUiThread(
            async () => await push.RegisterNativeAsync(registrationId, tags));
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(
            string.Format("Error with Azure push registration: {0}", ex.Message));
    }
}

続いて PushHandlerService クラスで OnMessage メソッド、OnUnRegistered() と OnError() メソッドも override します

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);

    }
}

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));
}

アプリ側はこれで終わりです。次は Azure のテーブルにスクリプトを追加します。

4. 管理ポータルで登録されている挿入スクリプトを更新する

ここは手順書通りです。

5. テストしてみましょう

自身で追加した場合や別の端末にデプロイして他の端末で追加した場合の通知をチェックしてみてください。

f:id:ytabuchi:20150427142508p:plain:w300 f:id:ytabuchi:20150427142515p:plain:w300

いかがでしょうか?後はこのベースのアプリを @nnasaki さん のスライド Azure Mobile Services と Azure Mobile Apps などを参考にしながら、色々変更して、チャットアプリを作ってみたいと思います。

アップしました

現時点の PUSH 通知のプロジェクトを GitHub にアップしました。お時間ある方は見てみてください。

Xamarin 気になった方は

是非 ダウンロード(直接) / ダウンロード(弊社経由) して触ってみてください。 学習用リソースJXUG リンクページ に参考資料を纏めてますので併せてどうぞ。

このブログも購読いただいたりすると嬉しいです。

以上です。