前回は、Google I/0 2016で発表された新しいFirebaseの概要とそのプロダクト群をご紹介しました。
新しく追加された機能は非常に多く、とてもすべてを解説することはできませんが、今回は筆者が特に重要だと感じた以下の3つの機能を実際にAndroidアプリに組み込む方法を解説したいと思います。
- Analytics
- Storage
- Remote Config
Analytics
Analyticsは新しくなったFirebaseの中核となる分析基盤です。ユーザのさまざまな行動を簡単に収集・分析することができます。
AnalyticsをAndroidで利用するにはアプリのbuild.gradle
に次の依存関係を追加するだけです。
この設定は基本的にすべてのFirebaseプロダクト群を導入する際にかならず実行しているはずなので、Analyticsは特に追加インストールする必要なく利用可能です。
イベントの記録
イベントの記録はFirebaseAnalytics
インスタンスのlogEvent()
メソッドを利用します。
次の例のように、ActivityのフィールドにFirebaseAnalytics
の変数を用意しておき、onCreate()
内で
FirebaseAnalytics.getInstance(this)
を使って初期化します。
あとはイベントを記録したい任意の場所でlogEvent()
メソッドを呼ぶだけです。
logEvent()
には記録するイベントと任意のパラメータを次のようにBundle
形式で渡します。
これだけです。ここでは表示したページを記録するためのopen_screen
というイベントを定義し、パラメータとしてscreen_name
に対応するページ情報を送信しています。
この例では記録する際にイベント名もパラメータも任意のものを指定しましたが、Firebaseがあらかじめ用意した定形のイベントとパラメータがそれぞれFirebaseAnalytics.Event
とFirebaseAnalytics.Param
という名前空間に定義されているのでいくつか紹介します。
イベント | 概要 |
ADD_PAYMENT_INFO | 支払情報を入力したイベント |
ADD_TO_CART | 商品をカートに追加したイベント |
ADD_TO_WISHLIST | 商品をウィッシュリストに追加したイベント |
パラメータ | 概要 |
ITEM_ID | 商品ID |
ITEM_NAME | 商品名 |
PRICE | 値段 |
これらは次のように利用します。
ここではオンラインショッピングアプリで使うようなイベントとパラメータを一例としてご紹介しましたが、他にも数多く定義されています。詳しくはFirebaseAnalytics.EventとFirebaseAnalytics.Paramのドキュメントをご参照ください。
ここに定義されたものを使わなければならないということはまったくありませんが、利用できそうなものがあれば利用してみても良いでしょう。
なお、Analyticsでは明示的にlogEvent()
を呼びださなくても、導入するだけで自動的に収集されるイベントがいくつも存在します。
たとえばユーザが初めてアプリを開いたときにはfirst_open
イベントが記録され、ユーザが最小セッション継続時間を超えてアプリを利用している場合にはsession_start
が自動で記録されます。他にもアプリの更新やアンインストールまでも自動的に収集してくれます。詳しくは自動的に収集されるイベントのドキュメントをご参照ください。
記録したイベントは数時間程度でWebコンソールに反映されます。Analyticsのコンソールから「イベント」タブに切り替えて自分が送信したイベントが記録されていることを確認してみてください。
ただ、これは現行のWebコンソールの制限だと思われますが、ユーザが任意に定義したイベントの細かいプロパティはコンソール上では確認できないようです。今後の改善が望まれます。
制限事項
現状、イベントのパラメータとして独自に定義したカスタムパラメータを指定した場合、Webコンソールのイベントタブから確認した際に詳細な値の内訳を確認することができません。前述のFirebaseAnalytics.Param
で定義されたパラメータのみ細かく確認することができます。
ワークアラウンドとして既存のパラメータを流用するか、汎用的な値を表現するFirebaseAnalytics.Param.VALUE
を利用する、あるいはBigQueryにエクスポートして確認する方法などが紹介されています。興味のある方はLog eventsの公式ドキュメントをご参照ください。
ユーザプロパティ
Analyticsではユーザプロパティという属性を各ユーザに設定することで、言語や地域など任意の指標でユーザをセグメント分けし、分析時のフィルタとして利用することができます。
FirebaseのWebコンソールにログインし、プロジェクトのAnalyticsから「ユーザープロパティ」を選択し「新しいユーザーのプロパティ」を選択します。
「ユーザープロパティ名」に任意のプロパティ名を入力し「作成」を選択します。
あとはプログラムからこのプロパティ名に対応する値を送信してやるだけです。
次の例ではカスタムApplicationクラスのonCreate()
内でユーザープロパティを設定しています。設定にはsetUserProperty()
メソッドを利用します。
これで以後のイベントの記録にはこのユーザープロパティが付与されて記録されるようになります。
数時間後ユーザープロパティが反映されたら、記録したイベント等をユーザープロパティでフィルタすることができます。
イベントタブから「フィルタを追加」を選択します。
その後「ユーザープロパティ」から指定したプロパティを選択してフィルタとして利用することができます。
AnalyticsのTips
Instant Runの無効
Android Studio 2.2未満でInstant Run機能を有効にしている場合、Analyticsのイベントが正しく送られないことが知られています。
もしAndroid Studio 2.2未満を使って開発している場合には、Android Studioの設定画面から次の図を参考にEnable Instant Run
のチェックを外してInstant Runを無効にしてください。
デバッグ時のイベント送信確認
AnalyticsのイベントがWebコンソールに反映されるには数時間かかります。もし開発環境でイベントがきちんと記録されているか確認したい場合は、次のようにadbコマンドを実行した状態でアプリを実行してみてください。
次のようにコンソールにイベントの記録の様子が出力されれば成功です。
Storage
StorageはGoogle Cloud Storageのバケットを利用して大容量の画像やファイルを簡単かつセキュアにアップロードしたりダウンロードしたりできる機能です。
StorageをAndroidで利用するにはアプリのbuild.gradle
に次の依存関係を追加します。
Storageへの操作はFirebaseStorage
インスタンス越しに行います。FirebaseStorage
インスタンスはFirebaseStorage.getInstance()
で取得することができます。
リファレンス
Storageにファイルをアップロード/ダウンロードするために、Google Cloud Storageのバケットへのリファレンス(参照)を取得します。
FirebaseのWebコンソールにログイン、プロジェクトのStorageを選択し、「ファイル」タブ内のgs://<your-project-id>
の部分をクリップボードにコピーしてください。
リファレンスの取得にはStorageReference
インスタンスのgetReferenceFromUrl("gs://<your-project-id>")
メソッドを利用します。gs://
の部分には先ほどWebコンソールで確認したURIをペーストしてください。
リファレンスを取得できたら、いよいよファイルを読み書きするために対象のファイルへのリファレンスを作成します。次の例は/images/sample.jpg
にファイルを書き込むために、そこへの参照を作成しています。
.child()
メソッドを連結することで、任意の深さの階層を表現することができます。これはこれまでの連載で見てきたRealtime Databaseと同じ作法なので、直感的にわかりやすいのではないでしょうか。
アップロード
Storageのリファレンスの扱いについて理解したところでいよいよファイルをアップロードしてみましょう。
アップロード方法はいくつかあるのですが、ここでは最も標準的と思われるInputStream
を利用した例を解説します。まずは次のコードをご覧ください。
Storageへのリファレンスを取得しstorageRef.child("images").child("sample.jpg")
で/images/sample.jpg
に対してファイルをアップロードする準備をしています。それからnew FileInputStream(new File("path/to/images/rivers.jpg"))
で端末に保存されたファイルをInputStream
としてオープンしています。あとはtarget.putStream(inputStream)
にそのストリームを渡してアップロードしています。
アップロードの成功と失敗はそれぞれaddOnSuccessListener()
とaddOnFailureListener()
にOnSuccessListener
とOnFailureListener
リスナを渡してコールバックしてもらいます。
Webコンソールを確認して、次のようにアップロードされたファイルを確認できれば成功です。
InputStream
を使う以外にもandroid.net.Uri
を使う方法などもあるので、詳しくはUpload Files on Androidのドキュメントをご参照ください。
ダウンロード
ダウンロードもリファレンスの取得まではまったく同じです。次の例ではサーバ上の/images/sample.jpg
のリファレンスを取得し、端末ローカルの一時ファイルにダウンロードしています。
File.createTempFile("images", "jpg")
でファイルをダウンロードする先の一時ファイルを作成し、fileRef.getFile(localFile)
でファイルをダウンロードしています。
成功と失敗のコールバックはアップロード時と同様です。ログにDownload succeeded!
とファイルのバイト数が表示されれば成功です。
ダウンロードもいくつか方法があるので、詳しくはDownload Files on Androidのドキュメントをご参照ください。
削除
ファイルの削除もこれまで同様ファイルへのリファレンス経由で行います。次のようにリファレンスからdelete()
メソッドを呼び出すだけです。成功と失敗コールバックもこれまで同様です。
Remote Config
Remote ConfigはA/Bテストを簡単に実現するための仕組みです。
たとえば「50%のユーザには別の設定値を提供する」といったシンプルな使い方のほか、「特定の国の特定のOSのユーザのみ商品をディスカウントする」といったような複雑なユーザセグメンテーションにも利用することができます。
今回はユーザによって画面の背景色を変える例を見てみましょう。
Webコンソールでの設定
まずはサーバ上にシンプルなキーと値のペアを定義します。Remote Configでは設定値をサーバに持ち、クライアントから適宜取得することでA/Bテストや動的な値の変更を可能にします。
WebコンソールからRemote Configを選択し「最初のパラメータを追加」を選択します。
「パラメーターキー」にcolor
、「デフォルト値」にwhite
を設定します。
「変更を公開」を選択します。
確認ダイアログで「変更を公開」を選択します。
コンソールでの準備はいったん終了です。
Android Studioでの作業
次にAndroidのコードからRemote Configを利用します。
Remote ConfigをAndroidで利用するには、アプリのbuild.gradle
に次の依存関係を追加します。
続いてアプリのres
ディレクトリ以下にxml
というディレクトリを作成し、remote_config_defaults.xml
というXMLファイルを作成します。中身は次のとおりです。
これはクライアントサイドにおける初期値として利用します。Remote Configではサーバサイドに設定値を持ちますが、初回起動時やインターネットに接続できない場合等にこのローカルの設定を利用するのです。
したがってkey
には先ほどWebコンソールで設定したのとまったく同じcolor
を設定する必要があります。value
もまずはサーバサイドと同じwhite
で問題ありません。
それではコードを書いていきます。Activityに次のようなコードを追加してください。
まずはじめに、背景色を変更するためにActivityのフィールドにView
を定義し、findViewById()
で探しておきます。
次の行のFirebaseRemoteConfigSettings
はRemote Configの設定用クラスです。Remote Configは、サーバから設定値を取得する際に1時間あたり5回までしかリクエストできないという制限があります。setDeveloperModeEnabled(BuildConfig.DEBUG)
することで、この設定を緩和しています。開発時は忘れないようにしましょう。
次にFirebaseRemoteConfig.getInstance()
でRemote Configのインスタンスを取得し、setConfigSettings(remoteConfigSettings)
で先ほどの設定を適用します。
次にremoteConfig.setDefaults(R.xml.remote_config_defaults)
で最初に定義したremote_config_defaults.xml
をデフォルト値として指定します。これでもしサーバと通信できなくても初期値が利用できるので、アプリが立ち上がらないといった問題がありません。
最終行のfetch()
メソッドはこのあと作成します。
サーバから情報を取得
それではサーバから情報を取得するコードを書いていきます。次のようなfetch()
メソッドを作成してください。
まずremoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()
で開発モードか否かを判定しています。開発モードは前述のsetDeveloperModeEnabled(BuildConfig.DEBUG)
で設定したもので、それによってキャッシュ時間を変えています。Remote Configはデフォルトでサーバの設定値を12時間キャッシュするので、開発時は便宜上それを少なくする必要があるからです。
次にremoteConfig.fetch(cacheExpiration)
でキャッシュ時間を指定しつつ、サーバから設定値を取得しています。成功と失敗コールバックはこれまで同様addOnSuccessListener()
とaddOnFailureListener()
で取得します。
成功時のonSuccess()
内のremoteConfig.activateFetched()
の部分に注目してください。ここでサーバから取得した設定を有効化しています。
設定値はremoteConfig.getString()
で取得します。getString()
の部分はgetBoolean()
, getLogn()
, getDouble()
などよく使う型は用意されています。container.setBackgroundColor(Color.parseColor(colorName))
で取得した値を元に背景色を設定しています。
ちなみにremoteConfig.getString()
の部分はアプリを起動直後など、サーバと通信する前でもエラーなく実行することができます。最初に用意したremote_config_defaults.xml
はこのための初期値なのです。
サーバサイドで設定値を変更
アプリをビルドして立ち上げると、単に真っ白の背景色の画面が表示されると思います。これはサーバサイドの値とクライアントサイドの値がいずれもwhite
であるからです。
ではWebコンソールからcolor
のデフォルト値をred
などに変更して「変更を公開」し、アプリを立ち上げ直してみてください。背景色が見事赤色に変更されれば成功です。
このようにRemote Configでは設定値をサーバサイドに持つことができるので、アプリを再リリースしなくても変更を動的に反映できるほか、たとえサーバサイドと通信できなくても問題なくアプリを動作させることができる優れた仕組みなのです。
A/Bテストしてみよう
前述のとおり、Remote ConfigではA/Bテストを簡単に行うことができます。
Webコンソールから先ほど定義したcolor
パラメータを選択し「条件の値を追加」を選択します。
「新しい条件を定義」を選択します。
「名前」にA_B_Testing
とつけて「適用する条件」をユーザー(ランダム%)
とし、50%
と入力して「条件を作成」を選択します。
デフォルト値とそれ以外で値を変えることで50%の割合で異なった値を取得することができます。
なお、ここからさらに「新しい条件」を追加することもできます。たとえばユーザがAndroidならwhite
、iOSならblack
といった具合です。
もし複数の条件が両方マッチする場合、条件が先にマッチした順に値が決められます。たとえば「アメリカのユーザならば」という条件と「Anndroidユーザならば」という条件が両方定義されており、「アメリカのユーザ」という条件が先に定義されていた場合はこちらの設定値がクライアントに返されます。
Tips
サーバから設定を取得するタイミング
Remote Configでは任意のタイミングでサーバから設定を取得し、任意のタイミングでそれを有効化することができますが、現実問題としてアプリを利用中に突然A/Bテストの設定が変わって画面レイアウトが変更されるのは実用的とは言えないでしょう。
筆者のおすすめは、スプラッシュ画面で設定を取得する方法です。スプラッシュ画面表示中に設定の取得が完了すればそのまま設定を適用して表示し、万一ネットワーク不良等で設定の取得が完了しなかった場合はそのままバックエンドでリトライさせながら設定だけ取得し、反映は次回の起動に持ち越す方法です。これによりユーザにできるだけ不自然でない体験を提供することができます。
A/Bテストの効果測定
A/Bテストは出し分けるのみならず効果測定してはじめて意味があります。現状Remote Config自身には効果を計測するためのツールは付属していないようなので、Analyticsのユーザープロパティを利用するのがおすすめです。ユーザープロパティの使い方は今回のAnalyticsの節をご覧ください。
まとめ
いかがだったでしょうか。今回は新しくなったFirebaseの数多の機能の中から3つだけピックアップしてご紹介しましたが、その多機能さと可能性に圧倒されたのではないでしょうか。Firebaseにはこの他にも魅力的な新機能が数えきれないほどあります。
次回は今回に続いて、新しくなったFirebaseの機能から注目の機能をいくつか取り上げ、コード例を交えながら解説したいと思います。どうぞお楽しみに。