bitbank techblog

Push通知導入検討レジュメ

はじめに

こんにちは
エンジニアの taptappun です

私はこれまでにPush通知の導入・実装・運用を数多く行ってきました
今回、その中で培った知見を共有したいと思います
これからPush通知の導入を検討している方々へ参考になればと思います

Push通知概論

情報伝達の種類

ネットワークを介してユーザに情報を伝達する方法は主に3種類の方法に分類されます

型名 説明
Pull型 ユーザがサーバから情報を取得する方法 Webサイト、ネイティブアプリなど
Push型 サーバがユーザに情報を伝達する方法 Push通知、メール配信など
双方向 Push型、Pull型両方を用いて情報を伝達する方法 チャット、電話など

今回解説している「Push通知」はPush型の情報伝達の方法になります
なおPull型、Push型はマーケティング用語としても用いられています

参考

Pull型

ユーザ(端末)がサーバ(サービス)にアプローチすることで情報を取得する方法をPull型といいます。Webサイト(Webサービス)の運営などはPull型にあたります

pull_style_sequence_diagram

ほとんどのWebサービスでは伝達手段はPull型のみを用いているため、ユーザに利用してもらうことでのみユーザに情報を伝達することができ、Webサービスからユーザに情報を伝達するとことができません

Push型

サーバ(サービス)からユーザ(端末)へ情報を伝達する方法をPush型といいます
今回解説する「Push通知」もPush型の伝達方法になります
Push型および「Push通知」が行われる概要を以下に図示します

push_style_sequence_diagram

※図の中に出てきた用語について以下に解説します

  • Push通知Token: Push通知を送信するために必要なユーザ(端末)と紐づいた一意な文字列
  • AppServer: アプリケーションの配信を行っている(Push通知を配信するための)サーバ
  • Firebase/Apple(Web) Push Server: Android端末であればFirebaseのサーバ(Firebase Cloud Messaging:FCM)、iOS端末であればAppleのサーバ(Apple Push Notification Service:APNs)

Push通知を導入する効果

Push通知を導入する意義、Push通知を導入するにあたり気をつけること、Push通知の導入に対する要件を考える時に考え方などについて説明します

メリット
  • アクティブユーザ(サービスを利用してくれているユーザ)の増加
    • Push通知を受信するとユーザはその通知を確認し、サービスにアクセスするようになります。これによりオフライン状態のユーザや長期間利用していないユーザ(休眠ユーザ)が利用してくれるようになります
デメリット
  • Push通知の配信が多すぎると逆にユーザの離脱要因になる
    • Push通知が多すぎると通知を切られたり、アプリをアンインストールされてしまったりと逆にユーザが利用してくれなくなってしまう要因となります
留意点
  • 配信の即時性はベストエフォート
    • Push通知を配信したら「すぐに」「必ず」ユーザに通知が届くことを保証してくれてはいません。あくまでPush通知はベストエフォートで配信されます(例えば端末の電源が長時間OFFになっていたり場合、Push通知をユーザに届けることができず通知が削除されてしまい通知されないといったケースも存在します)
参考

Push通知の種類と補足

  • ネイティブアプリ(Android/iOS)へのPush通知
    • AndroidのPush通知
    • iOSのPush通知
  • Web Push(ブラウザへのPush通知)
    • ネイティブアプリへのPush通知とは概要やフローが異なるものとなります。今回は触れません
  • ローカル通知
AndroidのPush通知

Android端末にPush通知を行う場合に限りPush通知を受け取ってもユーザに受け取ったことを「通知」しないということもできます(つまりサーバから端末に対してデータだけを送ることもでます)

iOSのPush通知

iOS端末にPush通知を行う場合には必ずユーザに「通知」しなければなりません(つまりAndroidのようにサーバからデータだけを送るということはできない)

ローカル通知

サーバを介さないで端末内から通知を行う方法を ローカル通知 といいます
Push通知とは異なる特徴として

  • 端末がオフラインであってもユーザへ通知することができる
  • サーバに負荷がかからない(Push通知の配信のためにサーバを介すことがないため)

という特徴があります

ローカル通知とPush通知

ローカル通知を用いることによってサーバへの負荷が軽減されるため、Push通知とローカル通知の両方を使用することによってPush通知配信時へのサーバへの負荷を軽減することができます

ローカル通知とPush通知を両方を使用する場合の要件と実装方針の例

要件: イベントの開始時刻になったら通知してお知らせしたい
実装方法: イベント開始時刻の情報をユーザが事前に取得し、時間になったらローカル通知で通知を行う

このように ローカル通知とPush通知の両方を使用することによりサーバへの負荷を軽減した運用を行うことができます

Push通知の導入

Push通知の機能を実際に導入していくまでの流れや実装にあたり行う必要がある作業の内容について以降に紹介していきます

Android/iOS共通のワークフロー

Push通知を行うためにはAndroidではFirebaseのサーバ(Firebase Cloud Messaging:FCM)を使用して送信する必要があり、iOSではAppleのサーバ(Apple Push Notification Service: APNs)を使用して送信する必要があります
Push通知が実際に配信されるまでの処理の流れはAndroid、iOS共にほぼ共通しています。以下に処理の流れを示します

native_push_notification_sequence_diagram

Androidへの導入手順

AndroidにPush通知を導入する手順の概要

AndroidのPush通知の設定方法はFCM(Firebase Cloud Messaging)の設定と同様に行っていくことで設定できます
以下の手順で実装していきます

1. FirebaseのプロジェクトにFCMを開始する

start-fcm

すでにFCMを開始している場合には「プロジェクトの設定」を開き「アプリを追加」を選択することでFCMにて配信するプラットフォームの追加を行うことができます

firebase-project-settings

firebase-add-app-after

2. FCMの開始のために開発しているAndroidの情報を記入する

firebase-input-android-info

3. Push通知を受け取るためのFCMの設定情報が記述されたファイルを導入する

google-services.json というファイルをダウンロードしてきてAndroidプロジェクトの特定の場所(以下のように プロジェクトルート/app/google-services.json となるような場所)に設置します

firebase-download-google-services

4. FCMの実装手順に合わせてAndroidの実装

AndroidプロジェクトにてFCMを使用するための各種ライブラリをインストールしていきます(以下のように詳細な手順が表示されます)

firebase-android-sdk-install

5. Push通知Tokenを取得して記録する

AndroidにてFirebaseのライブラリが導入できている状態で以下のような処理を追加することによってPush通知Tokenを取得できます

FirebaseMessaging.getInstance().token
    .addOnCompleteListener(OnCompleteListener { task ->
        if (!task.isSuccessful) {
            return@OnCompleteListener
         }

         // Push通知Token
         val pushToken = task.result
})

上記の val pushToken の値をサーバに送信し、記録します

6. アプリIDやPush通知Tokenなどの必要な情報を付与してFCMのAPIに送る

サーバよりPush通知を送るために必要な情報であるFirebaseのアプリIDはプロジェクト設定より確認できる
このアプリIDやPush通知Tokenなどの必要な情報を用いてFirebase Cloud Messaging APIを実行してPush通知を送信する

firebase-check-appid

7. 対象のPush通知Tokenの端末にPush通知が届く

Push通知を受信したら通知した内容が表示される

iOSへの導入手順

iOSにPush通知を導入するためには Apple Developer Program (登録には年間登録料は99$を支払う必要がある) に登録する必要があります
Apple Developer Program に登録しなかった場合以降の証明書の作成などの画面に遷移することができません
またAppストアにすでにiOSアプリを配信している場合とこれから配信している場合とでは設定していく手順が異なります
以降ではすでにAppストアにiOSアプリが配信されている状態でのPush通知の導入手順を紹介していきます

1. Push通知の使用を有効にする

ストアに配信した物を含めた、すでに作成されている Identifiers を確認し、対象の Identifer を選択します

apple-identifiers-list

Identifer の詳細の中から Push Notification の部分が有効になっているかどうか確認します。有効になっていなかったら Push Notification を有効にした Identifer を作成します

push-notification-enable

2. APNs用証明書(.cer)の作成

Certificates にアクセスして新しくPush通知用の証明書の作成を行っていきます

apple-developer-certificates

Push通知を配信用の証明書の種類を選択します
※以降ではアプリストアに配信可能な権限をもつ人にのみ選択、設定を行うことができます

select-push-notification-certicates

Identifers の中から対応したい App ID を確認し、選択して、Continueを選択します

select-push-notification-appid

CSR(Certificate Signing Request)ファイル をアップロードしてContinueを選択します

upload-push-notification-csr

これでAPNs用証明書(.cer) が作成されるのでcerファイルをダウンロードしておきます

CSRファイルの作り方

以降では途中でアップロードする必要があった CSRファイル の作り方を紹介します

キーチェーンアクセスを開き
「キーチェーンアクセス」>「証明書アシスタント」>「認証局に証明書を要求」を選択します

generate-keychain

メールアドレスを入力して「続ける」を選択します

input-assistant-info

鍵のサイズなどはそのままで「続ける」を選択します

assistant-input-rsa

これで CSRファイル が作成されます。この CSRファイル をアップロードして用いるようにしてください

3. APNs用証明書(.p12) の作成

ダウンロードした APNs用証明書(.cer) ファイルを開くと キーチェーンアクセス が起動して証明書が読み込まれます
読み込んだ証明書を選択して「書き出す」を選択して書き出しを行います

export-keychain

フォーマットを 個人情報交換(.p12) を選択して保存することでAPNs用証明書(.p12)ファイルとして保存します

※ FCM(Firebase Cloud Messaging)やAmazon PinpointなどのSaaSを用いる場合、cerファイルp12ファイル をアップロードして設定すればpush通知の設定を行うことができます

4. p12ファイルからpemファイルに変換する

書き出した p12ファイル をOpenSSLコマンドを使用してpemファイルへと変換を行います

openssl pkcs12 -in **.p12 -out **.pem -nodes -clcerts

この変換した pemファイルcerファイル をPush通知を配信するサーバに設置します

5. deviceTokenを取得して記録する

Swift にて以下のような処理を記述後、iOSアプリ向けにビルドを行います
ビルドしたiOSアプリを実行することでその端末に紐づいたdeviceToken(iOSでのPush通知Token)が取得できるようになります

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // ① プッシュ通知の利用許可のリクエスト送信
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            guard granted else { return }

            DispatchQueue.main.async {
                // ② プッシュ通知利用の登録
                UIApplication.shared.registerForRemoteNotifications()
            }
        }

        return true
    }
}

extension AppDelegate {

    // ③ プッシュ通知の利用登録が成功した場合
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
        print("Device token: \(token)")
    }

    // ④ プッシュ通知の利用登録が失敗した場合
    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register to APNs: \(error)")
    }
}

上記の let token の値をPush通知配信サーバに送ってその値を記録します

6. APNs証明書ファイルやdeviceTokenなどの必要な情報を付与してAPNsのAPIに送る

APNsのAPIへの実行方法の詳細についてはこちらに記載されています Sending Notification Requests to APNs

以下のようなBashコマンドを用いて実行することでPush通知を送信することができます

#!/bin/bash

CERTIFICATE_FILE_NAME=**.cer
CERTIFICATE_KEY_FILE_NAME=**.pem
TOPIC=com.example.MyApp
DEVICE_TOKEN=<Your device token>
APNS_HOST_NAME=api.sandbox.push.apple.com

curl -v --header "apns-topic: ${TOPIC}" --header "apns-push-type: alert" --cert "${CERTIFICATE_FILE_NAME}" --cert-type DER --key "${CERTIFICATE_KEY_FILE_NAME}" --key-type PEM --data '{"aps":{"alert":"test"}}' --http2  https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

この時に参照している **.cer**.pem はそれぞれ 2. APNs用証明書(.cer)の作成4. p12ファイルからpemファイルに変換する で取得したファイルを参照しています

7. 対象のdeviceTokenの端末にPush通知が届く

Push通知を受信したら通知が表示されるようになります

参考

Push通知配信SaaSについて

Push通知を運用していく中でよく起こる困りごと

  • Push通知の配信に時間がかかる
    • Push通知を配信するユーザ数が多くなれば処理の実行時間が長くなりユーザに通知が届くまでに時間がかかってしまう
    • Push通知配信時のサーバへの負荷が大きい(長時間バッチ処理を実行している状態であるため、CPU使用率やメモリ使用量が大きくなる)

FCM(Firebase Cloud Messaging)やAmazon PinpointなどのSaaSを用いることでこのような問題の解決に役立ちます
Push通知のためのSaaSを追加すると以下のようなフローにてPush通知が配信されます

push_notification_saas_sequence_diagram

FCM(Firebase Cloud Messaging)

FCMのアーキテクチャの概要

diagram-FCM

FCMアーキテクチャの概要

FCMについて
  1. AndroidのPush通知を行うためには必須
  2. iOSへのPush通知の他にもWeb PushへのPush通知もサポートしている
  3. 料金は無制限で無料→Firebase Priceing
  4. Firebaseのコンソール画面からもPush通知を送信できる
  5. セグメントPush(送る対象を絞ってPush通知を配信する機能)にも対応(セグメント対象はFirebase Analyticsで収集されているデータが基になる)

その他、仕様や制約についてはFCMメッセージについてを参照

FCMのiOSでの設定方法

Androidの設定方法はAndroidへの導入手順 にて説明したため省力します
ここではiOSの設定方法を紹介していきます

1. FCMにて新しくiOS向けに実装を開始する

Android の時と同様にiOSも設定していきます

firebase-add-ios-app

2. FCMでiOSアプリの情報を入力する

firebase-start-app-apple

3. iOSにFCM用の情報の設置

firebase-add-apple

4. iOSのサーバ用の追加設定

plistファイルの設定を行ったらiOSの場合、APNsへの登録が必要になります。FIrebaseでは各種APNs証明書などの取得が完了したらその情報を以下のように設定する必要があります

firebase-APNs-settings

5. FCMのAPIよりPush通知を送信する

4.のAPNsの設定まで完了したらAndroidと同様にFirebaseのコンソールまたはFirebase Cloud Messaging APIを実行することでPush通知を送信することができます

Amazon Pinpoint

Amazon Pinpointについて
  1. SMS、Eメール、Push通知、アプリ内メッセージ、音声など、さまざまな方法でPush型の情報伝達を行うことができます(Push通知はその中の一つ)
  2. Web Pushには非対応
  3. 通知 100 万件までは無料。その後は通知 100 万件あたり 1 USD の料金が発生。詳しくはAmazon Pinpointの料金より
Amazon PinpointでのPush通知の設定方法

Amazon PinpointにてAndroid/iOSのPush通知の実装・設定を行なっていく様子を説明していきます

1.Amazon PinpointにてPush通知の設定を開始する

amazon-pinpoint-start

2.Amazon Pinpoint Androidの設定を行う

セットアップ画面にてAndroidのタブを選択してAPIキーなどを設定します
ここで設定するAPIキーの値は上記のAndroidへの導入手順よりFIrebaseの設定画面より確認できます

amazon-pinpoint-Android-setup

3. Amazon Pinpoint iOSの設定を行う

セットアップ画面にてAPNsのタブを選択して証明書や署名鍵などのファイルを設定をアップロードします
ここで設定する証明書や署名鍵などの取得方法について上記のiOSへの導入手順にて取得したものを用います

amazon-pinpoint-APNs-setup

amazon-pinpoint-APNs-setup2

4. Amazon Pinpointを使ってPush通知を配信する

Amazon PinpointでのPush通知の配信方法は2種類あります

  1. Amazon Pinpointのコンソール画面よりPush通知を配信する
  2. AWS SDKを用いて設定しPush通知を配信する

AWS SDK での Amazon Pinpoint の使用

それぞれ用途に合わせた配信方法を用いることによってAmazon PinpointからPush通知を端末に向けて配信することができます

その他Push通知にまつわる色々な質問について

  • Q: 送ったPush通知を見てどれだけのユーザがアクセスしてくれたのか知りたい
    • A: Push通知配信サービスのコンソール画面からある程度、確認することができます。Firebaseのコンソール画面においては以下のように表示されます。(AWS Pinpointにも似たようなコンソール画面が存在します)またこのAPNs単体で使用している場合では開封率などを確認することができません。そのような場合においてはアプリの中に開封などが行われたかどうかのトラッキング処理を埋め込むことによって確認することができます
      push-notification-metrics-cosole
  • Q: Push通知がユーザに届かないことはあるのか?
  • Q: Push通知を切っているユーザのPush通知Tokenを削除できるようにしたい
    • A: Push通知を切ったという情報がサーバに自動的に送られるくるようなことはありません。そのためユーザからPush通知を切ったことがわかるような情報を送ってもらうことで判別することができます

まとめ

Push通知がどういったものなのかおおよそ内容について紹介しました
またPush通知の実装方法やツールの比較についての大まかな流れについても紹介しました
Push通知の導入や運用を検討するにあたり参考となりましたら幸いです

Author image
About taptappun
expand_less