moyashidaisuke's diary

平日はエンジニア、土日はミュージシャン(自称)のダイスケです。プログラム関連とかギター関連とかなんでも。

UnityでAndroid O向けに通知をする

概要

Android O では通知にChannel(チャンネル)という概念が導入されています。

Android O というのはAndroid8系の事で、APIバージョン26でAndroidManifestで言う所のtargetSdkVersion=26の事です。

で、Channelというのは通知をグルーピングして設定を変えたりできる類のものなのですが、Android O ではこの新機能のChannelを使う事が必須になっています。

使わない結果は↓の通りです。 チャンネルが無いよ(No Channel found)ってエラーが出ます。

07-08 13:28:25.682 1152-2944/? E/NotificationService: No Channel found for pkg=com.XXXXX.XXXXXXX, channelId=null, id=560, tag=null, opPkg=com.XXXXXX.XXXXXX, callingUid=10219, userId=0, incomingUserId=0, notificationUid=10219, notification=Notification(channel=null pri=0 contentView=null vibrate=[250,500,250,500] sound=android.resource://com.XXXXXX.XXXXXX/2131034112 defaults=0x4 flags=0x11 color=0x00000000 vis=PRIVATE)

当然Unityでも通知はAndroidの機能を使っていますので影響がありますので、既存アプリで通知機能があるアプリは更新が必要です。

対応案

案1:targetSdkVersionを25以下にする

急場はしのげるかもしれませんが、2018年の後半にはtargetSdkVersion=26以上がアプリの更新に必要となりますので、おすすめできません。 www.telemarks.co.jp

案2:自前で実装する

Androidのネイティブ処理詳しい方はどうぞ。 公式にサンプルコードがあります。

Notifications Overview  |  Android Developers

案3:Assetを使う

AssetStoreで通知(Notification)で検索すると、Assetがけっこうな数ヒットします。 Asset Store

ここで気をつけなければいけないのが、「Android Oに対応してる」「Channelに対応している」と明記されているかどうかです。

f:id:moyashidaisuke:20180713013615p:plain

こんな感じで書いてあれば多分大丈夫。更新が2017年の8月より昔のもの(まだAndroid Oが出ていない)や、明記されてないものは動かない可能性が高いです。

今回はこれを使ってみましたが、どれもそんなに変わらないと思います。

Android Local Notification Plugin - Asset Store

実装例

初期処理

private const string ANDROID_CHANNEL_ID = "channel1";

void Start(){
       #if UNITY_EDITOR
        // nothing
       #elif UNITY_IOS

       #elif UNITY_ANDROID
        LocalNotificationUnity.CreateChannel(ANDROID_CHANNEL_ID, Define.APP_TITLE, Define.APP_TITLE, NotificationImportance.HIGH, true, true, "soundName", NotificationSoundContentType.UNKNOWN);
       #endif
    }

割と適当ですが、こんな感じで最初に起動する処理のStart() あたりでChannelを作ってあげましょう。 Channelを複数作って〜という事であればもっと複雑になりますが、とりあえず通知したいだけならこれで十分。 通知の時の音とかもこのタイミングで指定するようです。

通知処理

public static void SetAndroidLocalNotification(int id, int sec, string body){
       #if UNITY_EDITOR
        Debug.Log("localnotify " + body);
       #elif UNITY_ANDROID

        DateTime now = DateTime.Now;
        TimeSpan secTS = new TimeSpan(0, 0, sec);
        LocalNotificationUnity.SendNotification(ANDROID_CHANNEL_ID, Define.APP_TITLE, body, now.Add(secTS), id);

       #endif
    }

このAssetはDatetimeを引数に取るタイプだったので、使いやすいようにラップする関数を適当に作ります。 通知するChanelも一緒に指定しますが、今回は1Channelしかないので固定値でOK。

つぶやき

  • iOSはUnityの組み込み処理で通知ができるのになぜAndroidは無いのか
  • このAssetは全部キャンセル処理がなぜか無かったです、、、
  • Channel必須にしなくてもいいのになぁ、、、