FirebaseのHTTP APIでiOS端末にPush通知を送る(Topic編)

FirebaseのHTTP APIでiOS端末にPush通知を送る(Topic編)

FirebaseのHTTP APIを使ってPush通知を送るための検証をしたいと思います。
FirebaseでPush通知を送る方法は管理画面から送る方法と、HTTP APIを使う方法があります。
単発であれば管理画面でも良さそうですが、定期的に送るとなった場合はHTTP APIを使う事になると思います。

検証環境

  • XCode 7.3.1
  • iOS 8.1以上
  • Swift 2.2.1
  • Ruby 2.3.1

送信対象の選択方法

以下の3種類を送信対象にできます。
今回はTopicで送信するパターンを検証します。

対象 説明
Device Registration Token アプリ側で端末ごとに取得できるレジストレーショントークンを指定して送信する
Topic Name アプリが購読しているトピックの端末全体に送信する
Device Group HTTP APIで登録できるデバイスグループ毎に送る

HTTP APIの実行には、rubyのfcmというgemを使います。

HTTP APIを実行するためのGemをインストール

以下のコマンドを実行してHTTP APIを実行するためのgemをインストールします。

gem install fcm

Topicとは何か

Firebaseのクライアント側(アプリ側)が購読するもので、トピックを購読している端末全体にPush通知を送ることが出来ます。
TopicはDevice Groupと違ってTopic自体を登録するという概念は無く、クライアントが購読した時点で該当のトピックが作成されるようです。
Device Groupはグループ化したデバイスをFirebaseのサーバ側が管理する方式ですが、トピックの場合は購読、購読停止についてHTTP APIの実行は不要で、完全にアプリのみで完結できるものです。

作成したトピックに対してPush通知を送信する方法はFirebaseの管理画面から行う方法と、HTTP APIを使う方法があります。
管理画面を使う場合の注意点として、作成したトピックは管理画面にはすぐに反映されず、管理画面から選択するトピックの一覧に表示されるまでにはしばらく時間がかかるというところです。(ドキュメントには24時間と書いてありました)

Firebaseの紹介動画では、アプリ内課金の特定のアイテムを購入した際のアクションでトピックの購読をすることで、アイテム購入者に対してPush通知を送ることができる、という例が紹介されていました。
こういうことがサーバ側の仕組みを用意しなくてもできるというのが便利だと思いました。

Topicを購読する

アプリ側からFIRMessaging.messaging().subscribeToTopicメソッドでトピック名を指定して購読します。
トピックの購読を解除する場合はFIRMessaging.messaging().unsubscribeToTopicを使います。

import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        FIRApp.configure()
        
        // アプリ起動時にPush通知のパーミッションをとる+オブザーバを登録してトークンの更新を検知する
        registerForPushNotifications(application)

        return true
    }
    
    // Push Notification
    func registerForPushNotifications(application: UIApplication) {
        let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()
        
        // Observerを登録し、トークン更新時に`tokenRefreshNotification`が呼ばれるようにする
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification(_:)), name: kFIRInstanceIDTokenRefreshNotification, object: nil)
        
        if FIRInstanceID.instanceID().token() != nil {
            connectToFcm()
        }
    }

    func tokenRefreshNotification(notification: NSNotification) {
        connectToFcm()
    }

    func applicationWillResignActive(application: UIApplication) {
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // バックグラウンドになった時に切断する
        FIRMessaging.messaging().disconnect()
    }

    func applicationWillEnterForeground(application: UIApplication) {
    }

    func applicationDidBecomeActive(application: UIApplication) {
    }

    func applicationWillTerminate(application: UIApplication) {
    }
    
    func connectToFcm() {
        FIRMessaging.messaging().connectWithCompletion { (error) in
            if error != nil {
                print("Unable to connect with FCM. \(error)")
            } else {
                print("Connected to FCM.")
                FIRMessaging.messaging().subscribeToTopic("/topics/news")
            }
        }
    }
}

トピック名は以下の様な命名規則があり、命名規則に反したトピック名を指定するとエラーが返却されます。

“/topics/[a-zA-Z0-9-_.~%]+”

命名規則に関するドキュメント原文
Developers can choose any topic name that matches the regular expression, “/topics/[a-zA-Z0-9-_.~%]+”. You can configure when to subscribe, when to send messages, and how to handle the notification when it reaches the client app.

Topicを指定してPush通知を送信する。

fcmを使ってpush通知を送るにはFcm#send_to_topicにtopic名を渡します。
指定するトピック名はこのgemを使う場合、/topics/を付ける必要はありません。

require 'fcm'

fcm = FCM.new("APIキーを指定します")

options = {
  priority: 'high',
  notification: { body: 'test message!' },
}
response = fcm.send_to_topic('news', options )

puts response

TAG

  • このエントリーをはてなブックマークに追加
金子 将範
エンジニア 金子 将範 rubyist

新しいことや難しい課題に挑戦することにやりがいを感じ、安定やぬるい事は退屈だと感じます。 考えるより先に手が動く、肉体派エンジニアで座右の銘は諸行無常。 大事なのは感性、プログラミングにおいても感覚で理解し、感覚で書きます。