サポート機能でアプリ開発をより効率的に!
こんにちは。Pairs Global事業部の@yuyakaidoです。
Eureka Native Advent Calendar 2017で3度目の登場です。
今回は少し趣向を変えて、グローバル版のPairsにて実装されている便利なサポート機能と、その裏側についてお伝えしたいと思います。
サポート機能とは
サポート機能とは、一言でいうと開発をスムーズに行うための機能です。
例えば、本番サーバーと開発サーバーの切り替えであったり、特定の状態を強制的に再現したり、といったものです。JakeWhartonさんが以下のリポジトリにて公開しているものに、Pairs特有の機能を付け足したようなものをイメージしていただければと思います。
サポート機能の紹介
Pairs Globalにて実装されているサポート機能をいくつか紹介したいと思います。
接続サーバーの変更機能
一般的にモバイルアプリの開発では、開発サーバーと本番サーバーが分かれていたり、開発サーバーが複数存在していたり、といったことが多いと思います。AndroidでAPI通信を行う際によく用いられるRetrofitはインスタンス生成時にベースURLを固定しますが、これを愚直に実装した場合、サーバーを変更する度に再ビルドといった手間が発生します。Fabric Betaなどの社内配布ツールを使っている場合も同様の手間が発生します。
そこで、Pairs Globalではこういった手間を軽減するために、アプリ起動時に接続サーバーを選択できるようにしており、1つのアプリで全てのサーバーへの接続が可能になっています。これにより今まで接続サーバーを変更する度に再ビルドしていた手間を削減することができました。
会員ステータスの変更機能
Pairsは会員ステータスが非常に多く、そのステータスによってアプリの挙動が変わります。従来は管理画面から自分の会員ステータスを更新した上で、アプリ上で挙動を確認するといった手順を踏んでいました。しかし、いくつもの会員ステータスを行き来しながら開発・確認を行うのはかなり大変な作業です。
そこで、管理画面の裏側で使われているAPIをアプリから呼び出すことで、管理画面の操作なしで自分の会員ステータスを変更できるようにしています。具体的には、開発版のアプリにて自分の会員ステータスを長押しすることでメニューが表示され、自由に会員ステータスを変更することができるようになっています。
自分にいいね!送信機能
Pairsではユーザー同士が互いにいいね!を送りますが、自分がいいね!をもらっている状態を再現するには一手間かかってしまいます。具体的には、管理画面から適当なユーザーで自分に対していいね!を送信する、といった操作が必要です。いいね!をもらっている状態はPairsにおいて非常に重要なものであり、普段の開発でも何度も検証しますが、従来の方法では非常に時間がかかってしまいます。
そこで、会員ステータスの変更機能と同様に管理画面のAPIを使って任意のユーザーから自分に対していいね!を送信できるようにしています。具体的には、開発版のアプリでユーザーを長押しすると以下のようなサポート機能が出現し、そこから自分に対していいね!を送信できるようにしています。他にも自分に足あとをつける機能や、自分に写真リクエストを送るといったことができるようになっています。
サポート機能の裏側
さて、ここまででサポート機能をいくつか紹介しましたが、ここからはサポート機能の裏側を紹介したいと思います。
サポート機能を実装する際に考慮しなければいけないこととしては以下の通りです。
- 本番ビルドにサポート用途のコードを混入させない
- if文で分岐してもいいですが、本番では絶対に通らないif文を残しておくのは無駄です
- 管理画面APIなどの情報は本番ビルドに入れたくない
- セキュリティ観点の話ですが、APKのデコンパイルによるAPI情報の漏洩防止が必要です
Pairs Global Androidでは上記を解決するためにDaggerを用いたDependency Injectionを行っています。DIというと、テストコードにおける用途がよく言及されますが、本番アプリと開発アプリのコードを分けるという用途でも有用です。
例えば、Pairsでは本番アプリにおいてスクリーンショット防止機能を入れていますが、開発用途でスクリーンショットを撮ることが良くあるため、開発アプリではスクリーンショットを有効にしています。このコードをサンプルに本番アプリと開発アプリで機能を分ける方法を紹介します。
まずは、以下のようなinterfaceを実装します。
interface ScreenshotProtectorType {
fun setup(window: Window)
}
開発用のクラスを実装します。
class DebugScreenshotProtector @Inject constructor() : ScreenshotProtectorType {
override fun setup(window: Window) {
// Do nothing in debug
}
}
本番用のクラスを実装します。
class ReleaseScreenshotProtector @Inject constructor() : ScreenshotProtectorType {
override fun setup(window: Window) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
}
開発用のModuleでは、開発用のクラスをprovideします。
@Provides
fun provideScreenshotProtector(): ScreenshotProtectorType {
return DebugScreenshotProtector()
}
本番用のModuleでは、本番用のクラスをprovideします。
@Provides
fun provideScreenshotProtector(): ScreenshotProtectorType {
return ReleaseScreenshotProtector()
}
このように開発用と本番用のModuleを分けておくことで、本番には開発用のコードを一切混ぜることなくサポート機能を実装することが可能です。
サポート機能の注意点
ここまででサポート機能とその裏側を解説しましたが、いかがでしたでしょうか?
自社でも取り入れたいと思っていただいた方が多いかと思いますが、あくまで今回紹介したのはサポート機能であり、実際のユーザーは正規のフローでアプリを使います。そのため、サポート機能に頼りすぎるべきは危険です。あくまで開発用途に留めるべきで、QAの際には正規のフローでテストを行うといったことが必要です。
まとめ
今回はPairs Globalにおけるサポート機能を紹介しました。
- サポート機能とは
- 開発をサポートするための便利機能
- サポート機能の紹介
- 接続サーバーの変更機能
- 会員ステータスの変更機能
- 自分にいいね!送信機能
- サポート機能の実装方法
- パフォーマンスやセキュリティ観点で、本番には開発用途のコードを混入させたくない
- Daggerを使ったDIで本番と開発のコードを分ける
- サポート機能の注意点
- サポート機能に頼りすぎは危ないよ!
- 用法・容量を守ってお使いください
この記事のようなサポート機能を作ったことで、普段の開発ではより機能開発そのものに時間を使えるようになっており、チーム内でのカジュアルな動作検証における手間も削減できています。