採用はこちら!

Shinonome Tech Blog

株式会社Shinonomeの技術ブログ
3 min read

Firebase In-App MessagingでカスタムUIのポップアップを表示する

こんにちは、モバイルコースのEtsushiです。 Advent Calendar13日目の記事は「Firebase In-App Messaging」を題材にします。

こんにちは、モバイルコースのEtsushiです。
Advent Calendar13日目の記事は「Firebase In-App Messaging」を題材にします。

Firebase In-App Messaging

Firebase In-App Messagingとは、Firebaseのコンソールで入力した情報を元にモバイルアプリ上でポップアップ形式のキャンペーンを表示できる機能です。Android、iOS、およびFlutterのプロジェクトにSDKを入れるだけで表示することが出来ます。

表示形式は、card、 modal、image only、bannerの4つでそれぞれ以下のようなUIになります。

card modal
Screenshot_20221212-000050
image only banner
Screenshot_20221212-000128 Screenshot_20221212-000205

Firebaseコンソールでは、キャンペーンとして表示する要素のうち、タイトル、画像、本文、およびボタンアクションなどを設定することでポップアップの見た目を多少カスタマイズできます。

また、配信頻度、ターゲットユーザ、表示トリガー、およびメタデータなど表示条件を設定することにより、配信するキャンペーンの想定ターゲットに絞ってポップアップを表示させることが可能です。

問題点

とても便利なIn-App Messagingですが、問題点もあります。

In-App Messagingでは、Firebaseコンソール上でポップアップの内容を入力するだけでポップアップを表示できますが、文字フォントやサイズ、レイアウトといったポップアップのデザイン要素をカスタマイズして複雑なUIを表示することはできません。また、ポップアップを押下した際の挙動もURLを設定できるのみです。

このため、SDKを入れて表示するだけではアプリデザインとマッチせずアプリの世界観を壊してしまう可能性があり、モバイル側でデザインのカスタマイズをしてあげることが必須となります。

カスタムUIの表示

それではポップアップのUIをカスタムするための実装を行います。
本記事では、Android版の実装を行います。iOSが気になる方はこちらの記事がとても参考になりましたのでご覧ください。

前提

なお、ここでは前提として以下が済んでいるものとして割愛します。
これらの操作が終わっていると、アプリ上でデフォルトのIn-App Messagingのポップアップを表示できると思います。

  1. Androidプロジェクトの作成
  2. Firebaseの初期設定
  3. In-App Messagingライブラリの導入
  4. GCP上でIn-App Messagingを有効化する

実装

まず、In-App Messagingの表示イベントを受け取った際の動作をカスタマイズするために、FirebaseInAppMessagingDisplayを継承したクラスを実装します。
本実装では、FirebaseInAppMessagingDisplayActivityLifecycleCallbacksを継承したFirebaseInAppMessagingDisplayImplを利用しています。
FirebaseInAppMessagingDisplayを継承するとdisplayMessage()の実装が必須となるのでこちらの中身を記述します。

第一引数のInAppMessageはメッセージの本体でFirebaseコンソール上で設定したタイトルテキストやボタンアクションURLなどを含みます。このメッセージの内容を自作ダイアログなどに注入してカスタムUIの表示を実現します。

第二引数のFirebaseInappMessagingDisplayCallbacksは、displayMessage()内で呼び出せるFirebaseへのコールバック群です。中でもcallbacks.impressionDetected()は、呼び出すことによりFirebaseへユーザがメッセージを受け取ったことを通知します。これにより、表示条件で指定した「キャンペーン中一度のみ表示」などの条件が機能するので忘れず呼び出しましょう。

class InAppMessagingDisplayComponent : FirebaseInAppMessagingDisplayImpl() {

    private var listener: InAppMessagingEventListener? = null

    interface InAppMessagingEventListener {
        fun showModal(title: String?, imageUrl: String?, body: String?, buttonText: String?)
    }

    override fun displayMessage(
        inAppMessage: InAppMessage,
        callbacks: FirebaseInAppMessagingDisplayCallbacks
    ) {
        callbacks.impressionDetected()
        when (inAppMessage) {
            is CardMessage -> {
                // カードスタイルの処理
            }
            is ModalMessage -> {
                // モーダルスタイルの処理
                val title = inAppMessage.title.text
                val imageUrl = inAppMessage.imageData?.imageUrl
                val body = inAppMessage.body?.text
                val buttonText = inAppMessage.action?.button?.text?.text
                listener?.showModal(title, imageUrl, body, buttonText)
            }
            is ImageOnlyMessage -> {
                // 画像のみスタイルの処理
            }
            is BannerMessage -> {
                // バナースタイルの処理
            }
        }
    }

    fun registerListener(listener: InAppMessagingEventListener) {
        this.listener = listener
    }
    ...
}

次に、FirebaseInAppMessagingのインスタンスにこのInAppMessagingDisplayComponentをセットしてあげます。これにより、イベントを受け取った際に先ほど実装したdisplayMessage()が呼び出されるようになるので、In-App Messagingを自由にハンドリングし、カスタムUIで表示できるようになります。

class MainActivity : AppCompatActivity(), InAppMessagingDisplayComponent.InAppMessagingEventListener {
    private val displayComponent = InAppMessagingDisplayComponent()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        displayComponent.registerListener(this)
    }

    override fun onResume() {
        super.onResume()
        FirebaseInAppMessaging
            .getInstance().setMessageDisplayComponent(displayComponent)
    }

    override fun showModal(title: String?, imageUrl: String?, body: String?, buttonText: String?) {
        // モーダルスタイルのカスタムUIを表示
        CustomDialog
            .create(title, imageUrl, body, buttonText)
            .show(supportFragmentManager, "CustomDialog")
    }
}

本実装の場合はMainActivityをイベントリスナーとして登録してMainActivity側でイベントをハンドリングするようにしているのですが、この辺の仕組みは何でも良いです。プロジェクトの方針に合わせた実装にして下さい。

また、例ではモーダルのみハンドリングしています。それ以外は、このままではハンドリングされずデフォルトUIのポップアップすら表示されないので注意して下さい。

実装例は以下の通りです。
例では、Firebaseコンソール上では設定できないタイトルや本文の文字色、サイズ、画像のレイアウトなどをカスタマイズしました。

カスタマイズ前 カスタマイズ後
Screenshot_20221212-131256-1 Screenshot_20221212-131235-1

サンプル実装なので、世界観は行方不明ですがカスタムUIが表示できていることがわかります。

おわりに

本記事がIn-App Messagingを利用する際の参考になれば幸いです。
明日はバックエンドのAkinori君の記事です。

参考文献