UnityのMobile Notification Packageの使い方

ランタイムAPIは、AndroidNotificationCenteriOSNotificationCenterの二つに分割されています(コードのサンプルのための適切なセクションを参照してください)。それぞれのプラットフォームの通知をスケジュールや管理することができます。同じAPIを使用してAndroidとiOSの両方に通知を送信できるようにする、高レベルのラッパーを実装したサンプルプロジェクトが、GitHubページにあります




サポートされている機能:

  • 繰り返し可能なローカル通知または1回限りの通知をスケジュールします。
  • スケジュールされた通知またはすでに表示されている通知をキャンセル
  • アンドロイド:
    • Android Oreo以上で通知チャンネル(カテゴリ)を作成および変更します。
    • 通知は、デバイスの再起動時に保存することができます
    • カスタム通知アイコンを設定します。
  • iOS:
    • Apple Push Notification Service(APN)を使ってリモート通知を受信します。
    • アプリの実行中に通知を受信した場合は、リモート通知の内容を変更します。
    • 通知をスレッドにグループ化する(iOS 12以降でのみサポート)

必要条件

  • Android 4.1(API 16)/ iOS 10以上をサポートしています。
  • Unity 2018.3以降と互換性があります。  

アンドロイド

通知チャンネルを作成する。

すべてのローカル通知は通知チャンネルに属します。通知チャンネルは、Oreo(8.0)以降のAndroidでのみサポートされています。古いバージョンでパッケージを使用すると、チャンネルの振る舞いはエミュレートされます。そのため、8.0より前の各通知に対して個別に設定された設定(priority(Importance)など)は、8.0より前のバージョンでもチャンネルに設定される必要があります。
var c = new AndroidNotificationChannel()
{
    Id = "channel_id",
    Name = "Default Channel",
    Importance = Importance.High,
    Description = "Generic notifications",
};
AndroidNotificationCenter.RegisterNotificationChannel(c);

簡単な通知を送る:

この例では、テキストを含む簡単な通知をスケジュールし、前の手順で作成した通知チャネルに送信する方法を示します。

var notification = new AndroidNotification();
notification.Title = "SomeTitle";
notification.Text = "SomeText";
notification.FireTime = System.DateTime.Now.AddMinutes(5);

AndroidNotificationCenter.SendNotification(notification, "channel_id");
通知ごとにカスタムアイコンを指定する必要があります。そうしないと、デフォルトのUnityアイコンが代わりにステータスバーに表示されます。で通知アイコンを設定できますEdit->Project Settings->Mobile Notification Settingsスクリプトで通知をスケジュールするときは、設定ウィンドウで定義したIDを使用してください。
notification.Icon = "my_custom_icon_id";
オプションで、小さいアイコンの代わりに通知ビューに表示される大きいアイコンを設定することもできます(大きいアイコンの上に小さいバッジが配置されます)。
notification.LargeIcon = "my_custom_large_icon_id"
スケジュールされた後、各通知には、後で通知のステータスを追跡したりキャンセルしたりするために使用できる固有の識別子が割り当てられます。
var identifier = AndroidNotificationCenter.SendNotification(n, "channel_id");
通知がすでに配信されているかどうかを確認し、結果に応じてアクションを実行できます。ただし、通知ステータスはAndroid Marshmallow(6.0)以降でのみ追跡できます。
if ( CheckScheduledNotificationStatus(identifier) == NotificationStatus.Scheduled)
{
    // Replace the currently scheduled notification with a new notification.
    UpdateScheduledNotifcation(identifier, newNotification);
}
else if ( CheckScheduledNotificationStatus(identifier) == NotificationStatus.Delivered)
{
    //Remove the notification from the status bar
    CancelNotification(identifier)
}
else if ( CheckScheduledNotificationStatus(identifier) == NotificationStatus.Unknown)
{
    var identifier = AndroidNotificationCenter.SendNotification(n, "channel_id");
}

デバイスの再起動後にスケジュールされた通知を保存する

デフォルトでは、スケジュールされた通知はデバイスの再起動時に削除されます。デバイスの電源を入れたときにすべての通知を自動的に再スケジュールするには、のReschedule Notifications on Device Restartオプションを有効にします。Edit->Project Settings->Mobile Notification SettingsこれRECEIVE_BOOT_COMPLETEDにより、アプリのマニフェストに権限が追加されます。

アプリの実行中に受信した通知を処理する:

アプリの実行中に通知が配信されるたびにコールバックを受信するために、AndroidNotificationCenter.OnNotificationReceivedイベントを購読することができます
AndroidNotificationCenter.NotificationReceivedCallback receivedNotificationHandler = 
    delegate(AndroidNotificationIntentData data)
    {
        var msg = "Notification received : " + data.Id + "\n";
        msg += "\n Notification received: ";
        msg += "\n .Title: " + data.Notification.Title;
        msg += "\n .Body: " + data.Notification.Text;
        msg += "\n .Channel: " + data.Channel;
        Debug.Log(msg);
    };
AndroidNotificationCenter.OnNotificationReceived += receivedNotificationHandler;

カスタムデータを保存し、通知を使用してアプリを開くときに取得する

IntentDataプロパティを設定することで、通知オブジェクトに任意の文字列データを格納できます。
            var notification = new AndroidNotification();
            notification.IntentData = "{\"title\": \"Notification 1\", \"data\": \"200\"}";
            AndroidNotificationCenter.SendNotification(notification, "channel_id");
通知がアプリを開くために使用されている場合、あなたはそれをそれに割り当てられた任意のデータと任意のデータを取得することができます:
var notificationIntentData = AndroidNotificationCenter.GetLastNotificationIntent();

if (notificationIntentData != null)
{
    var id = notificationIntentData.Id;
    var channel = notificationIntentData.Channel;
    var notification = notificationIntentData.Notification;

    return notification.IntentData;
}
アプリが他の方法で開かれた場合はGetLastNotificationIntentnullを返します。 

iOS


承認をリクエストする:

あなたは、ローカルに投稿し、リモート通知を受け取るための許可をシステムに要求する必要があります。ユーザーが承認要求を確認した後にユーザーにリモート通知を送信する場合は、DeviceTokenを取得できます (要求はregisterForRemoteNotificationsをtrueに設定して作成する必要があります)。デバイスへのプッシュ通知を使用する方法、およびアプリにプッシュ通知サポートを追加する方法については、Apple Developer Site参照してください。
必要に応じて、特定の種類の通知を送信するためのアクセス許可をユーザーに要求することができます(以下の例を参照してください)。ただし、設定アプリケーションの任意の時点で、ユーザーが各通知タイプの承認ステータスを変更する可能性があります。iOSNotificationCenter.GetNotificationSettingsを呼び出すことで実際の承認ステータスを確認できます
または、アプリの起動時リクエストの承認を有効にすることもできます。Edit -> Project Settings -> Mobile Notification Settingsこの場合、アプリは起動時に自動的に権限ダイアログを表示します。その後、このメソッドを再度呼び出して現在の認証ステータスを確認することができますが、ユーザがすでに認証を許可または拒否している場合、UIシステムプロンプトは再び表示されません。
using (var req = new AuthorizationRequest(AuthorizationOption.AuthorizationOptionAlert | AuthorizationOption.AuthorizationOptionBadge, true))
{
    while (!req.IsFinished)
    {
        yield return null;
    };

    string res = "\n RequestAuthorization: \n";
    res += "\n finished: " + req.IsFinished;
    res += "\n granted :  " + req.Granted;
    res += "\n error:  " + req.Error;
    res += "\n deviceToken:  " + req.DeviceToken;
    Debug.Log(res);
}


簡単な通知を送る:

var timeTrigger = new iOSNotificationTimeIntervalTrigger()
{
    TimeInterval = new TimeSpan(0, minutes, seconds),
    Repeats = false
};

var notification = new iOSNotification()
{
    // You can optionally specify a custom Identifier which can later be 
    // used to cancel the notification, if you don't set one, an unique 
    // string will be generated automatically.
    Identifier = "_notification_01",
    Title = title,
    Body = "Scheduled at: " + DateTime.Now.ToShortDateString() + " triggered in 5 seconds",
    Subtitle = "This is a subtitle, something, something important...",
    ShowInForeground = true,
    ForegroundPresentationOption = (PresentationOption.NotificationPresentationOptionAlert | PresentationOption.NotificationPresentationOptionSound),
    CategoryIdentifier = "category_a",
    ThreadIdentifier = "thread1",
    Trigger = timeTrigger,
};

iOSNotificationCenter.ScheduleNotification(notification);
通知がトリガーされなかった場合は、次のようにして取り消すことができます。
iOSNotificationCenter.RemoveScheduledNotification(notification.Identifier);
通知がすでにユーザーに表示されている場合は、通知センターから削除できます。
iOSNotificationCenter.RemoveDeliveredNotification(notification.Identifier)


その他のトリガー

時間間隔トリガーのほかに、カレンダーおよびロケーショントリガーも使用できます。iOSNotificationCalendarTriggerのすべてのフィールドはオプションですが、トリガーを機能させるには少なくとも1つのフィールドを設定する必要があります。たとえば、時間と分のフィールドのみを設定した場合、システムは次の指定された時間と分に自動的に通知をトリガーします。
var calendarTrigger = new iOSNotificationCalendarTrigger()
{
    // Year = 2018,
    // Month = 8,
    //Day = 30,
    Hour = 12,
    Minute = 0,
    // Second = 0
    Repeats = false
};
デバイスが特定の地域に出入りするときに通知の配信をスケジュールしたい場合は、ロケーショントリガーを作成することもできます。このトリガーを使用して通知をスケジュールする前に、アプリにCore Locationを使用する権限と、使用中の権限が必要です。この承認を要求するには、Unity LocationService APIを使用します。詳細についてはhttps://developer.apple.com/documentation/corelocation/clregion?language=objc参照してください
この例では、中心座標はWGS 84システムを使用して定義されています。この場合、ユーザーがパリのエッフェル塔の周囲250メートルの半径内の領域に入ると、通知がトリガーされます。
var locationTrigger = new iOSNotificationLocationTrigger()
{
    Vector2 Center = new Vector2(2.294498f, 48.858263f),
    Radius = 250f,
    NotifyOnEntry = true,
    NotifyOnExit = false,
}


アプリの実行中に受信した通知を処理する

アプリの実行中に通知アラートが表示された場合は、通知アラートを表示するのではなく、カスタムアクションを実行することをお勧めします。デフォルトでは、それをスケジュールしたアプリがフォアグラウンドにある間にローカル通知がトリガーされた場合、その通知に対してアラートは表示されません。通知がアプリが実行されていない場合と同じように動作するようにしたい場合は、通知をShowInForegroundスケジュールするときにプロパティを設定する必要があります

notification.ShowInForeground = True

// In this case you will also need to specify it's 'ForegroundPresentationOption'
notification.ForegroundPresentationOption = (PresentationOption.NotificationPresentationOptionSound | PresentationOption.NotificationPresentationOptionAlert)
あるいは、通知がトリガーされたときにゲーム内UIを使用して通知コンテンツを表示するなど、他のアクションを実行することをお勧めします。この場合OnNotificationReceived、ローカルまたはリモートの通知が受信されたときに必ず呼び出されるイベントを購読する必要があります(前景で表示されている場合は無視されます)。
アプリの実行中にリモート通知を受信した場合は、リモート通知の内容を変更するか、まったく表示しないようにします。あなたはOnRemoteNotificationReceivedイベントを購読することによってこれを行うことができますこれを行うと、アプリの実行中にリモート通知が表示されなくなります。それでもアラートを表示したい場合は、次のようにリモート通知コンテンツを使用してローカル通知をスケジュールする必要があります。

iOSNotificationCenter.OnRemoteNotificationReceived += notification =>
{
    // When a remote notification is received modify it's contents and show it
    // after 1 second.
    var timeTrigger = new iOSNotificationTimeIntervalTrigger()
    {
        TimeInterval = new TimeSpan(0, 0, 1),
        Repeats = false
    };

    iOSNotification  n = new iOSNotification()
    {
        Title = "Remote : " + notification.Title,
        Body =  "Remote : " + notification.Body,
        Subtitle =  "RERemote: " + notification.Subtitle,
        ShowInForeground = true,
        ForegroundPresentationOption = PresentationOption.NotificationPresentationOptionSound | PresentationOption.NotificationPresentationOptionAlert | PresentationOption.NotificationPresentationOptionBadge,
        CategoryIdentifier = notification.CategoryIdentifier,
        ThreadIdentifier = notification.ThreadIdentifier,
        Trigger = timeTrigger,
    };
    iOSNotificationCenter.ScheduleNotification(n);

    Debug.Log("Rescheduled remote notifications with id: " + notification.Identifier);

};

カスタムデータを保存し、通知を使用してアプリを開くときに取得する

Dataプロパティを設定することで、通知オブジェクトに任意の文字列データを格納できます。
var notification = new iOSNotification()();
notification.Data = "{\"title\": \"Notification 1\", \"data\": \"200\"}";
//..assign other fields..
iOSNotificationCenter.ScheduleNotification(notification);
アプリが最後に受け取った通知は、次のようにして取得できます。
var n = iOSNotificationCenter.GetLastNotification();
if (n != null)
{
    var msg = "Last Received Notification : " + n.Identifier + "\n";
    msg += "\n - Notification received: ";
    msg += "\n - .Title: " + n.Title;
    msg += "\n - .Badge: " + n.Badge;
    msg += "\n - .Body: " + n.Body;
    msg += "\n - .CategoryIdentifier: " + n.CategoryIdentifier;
    msg += "\n - .Subtitle: " + n.Subtitle;
    msg += "\n - .Data: " + n.Data;
    Debug.Log(msg);
}
else
{
    Debug.Log("No notifications received.");
}
アプリが通知を使用して開かれた場合、その通知も返されます。アプリが他の方法で開かれた場合はGetLastNotificationnullを返します。 

よくある質問

ロケーショントリガーによる通知は機能しません。

CoreLocationフレームワークがプロジェクトに追加されていることを確認してください。これMobile Notification SettingsはUnity Editorのメニューで行えます。またはそれをXcodeプロジェクトに手動で追加することによって(またはUnity Xcode APIを使用することによって)。また、アプリで位置情報を使用する許可を要求する必要がありますこれは、位置情報サービスAPIを使用して行うことができます