ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

プッシュ通知の届き方(iOS13編)

f:id:mbaasdevrel:20180524170416p:plain

アプリのアクティブ率などを上げる上で欠かせないのがプッシュ通知です。昔は単にバナー表示するだけでしたが、今はアイコンを付けたり、グルーピングするなど、様々なプッシュ通知が送信できます。

また、OSがバージョンアップしたり、SwiftやSDKが更新されるのに伴って、プッシュ通知の実装方法も変わってきています。今回、執筆時点での最新版でありiOS13.4について、実装方法と実際に届くプッシュ通知の違いをまとめてみました。

実装について

プッシュ通知を使う場合には、 UserNotifications をインポートします。

import UserNotifications

そしてAppDelegateにUNUserNotificationCenterDelegateを追加します。iOS10以降であればextensionを使う方法もあるのですが、この場合一部のプッシュ通知がコード側で補足できませんでした。

class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate {

次に UNUserNotificationCenter.current() をデリゲートします。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
  let center = UNUserNotificationCenter.current()
  center.delegate = self
  // 以下省略
}

プッシュ通知のデバイストークン取得

デバイストークンの取得、そして保存についてはニフクラ mobile backendの例で紹介します。まず、アプリケーションキーとクライアントキーで初期化します。

NCMB.initialize(applicationKey: "APPLICATION_KEY", clientKey: "CLIENT_KEY");

後は UNUserNotificationCenter.current()requestAuthorization でユーザの確認用ダイアログを出します。

center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
  if((error) != nil) {
    return
  }
  if granted {
    DispatchQueue.main.async {
      UIApplication.shared.registerForRemoteNotifications()
    }
  }
}

プッシュ通知が許諾されると didRegisterForRemoteNotificationsWithDeviceToken が呼ばれますので、以下のようなコードで保存可能です。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    //端末情報を扱うNCMBInstallationのインスタンスを作成
    let installation : NCMBInstallation = NCMBInstallation.currentInstallation
    //Device Tokenを設定
    installation.setDeviceTokenFromData(data: deviceToken)
    //端末情報をデータストアに登録
    installation.saveInBackground(callback: { result in
        switch result {
        case .success:
            //端末情報の登録が成功した場合の処理
            print("保存に成功しました")
        case let .failure(error):
            //端末情報の登録が失敗した場合の処理
            print("保存に失敗しました: \(error)")
            return;
        }
    })
}

プッシュ通知の受信

プッシュ通知を受信したタイミングのアプリの状態は次のように分けて考えられます。

  • アプリがフォアグラウンドの時
  • アプリがバックグラウンドの時
  • アプリがキルされている時

そしてプッシュ通知は以下の3パターンが想定されます。

  • バナーが表示されて、かつ開かれた時
  • バナーが表示されて、開かれなかった時
  • サイレントプッシュ

これら、それぞれの状態において、アプリ側で補足できるのか確認してみました。メソッドは3つあります。

didReceiveRemoteNotificationを使う場合、アプリ側でRemote Notificationを有効にしなければなりません。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    completionHandler(.newData)
}

そして userNotificationCenter をデリゲートしたメソッドを用意します。一つは didReceive です。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {

    let trigger = response.notification.request.trigger
    completionHandler()
}

もう一つは willPresent です。

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
     completionHandler(.badge)
}

検証結果

結果は次のようになります。※1の場合、コードは実行されますが、プッシュ通知のバナーは表示されませんでした。

フォアグラウンド バックグラウンド キル
メッセージ付き(開かない)
メッセージ付き(開く) willPresent ※1 didReceive didReceive
サイレントプッシュ didReceiveRemoteNotification didReceiveRemoteNotification

確実にいえるのは、メッセージ付きのプッシュ通知の場合、開かないとアプリ側のコードは実行されないと言うことです。プッシュ通知に気付いたユーザが、バナーをタップせずにアプリを起動した場合も同様です。

メッセージ付きのプッシュ通知を開いた場合、フォアグラウンドかバックグラウンド(またはアプリがキルされた状態)であるかによって、呼ばれるメソッドが異なります。フォアグラウンドの場合はメッセージは表示されないので、注意が必要です。もしフォアグラウンドにあってもバナーを表示したい場合は completionHandler(.alert) のようにするとバナーが表示できます。

サイレントプッシュは、アプリがキルされていたり、低消費電力モードになっている、バックグラウンド更新を無効にしている場合はコードの実行ができないようです。

まとめ

プッシュ通知の開き方、アプリの状態によって表示方法が異なるので注意が必要です。単純な開封率だけでなく、MAUなども合わせてウォッチすることで、アプリの活性化施策を考えてみてください。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。