FlipperでAndroidアプリのデバッグをする

## はじめに
恥ずかしながら今更Flipperの存在を知ったもののQiitaに記事がなかったので軽くまとめておきます。
今回試せたのはAndroidの方だけでiOSの方は試せていないのでどなたかやってみてください:bow:

## Flipperとは？
Facebook社が開発しているAndroid, iOS両方に対応しているデバッグツールです。
以前はSonarという名前だったようです。

[公式サイト](https://fbflipper.com/)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/45debfac-1906-c734-ef21-431ba04a6fb9.png)

## でもStethoありましたよね？
と思っていたらそのことに関する[Stetho Guidance](https://fbflipper.com/docs/stetho.html)というページが有りました。
原文を読んだ感じ、StethoはAndroidツールだったしChrome開発ツールはWeb向けだったので、アプリ開発に特化した体験を提供するにあたり専用のツールを作ったようです。
また、別にStethoが使えなくなるというわけでもなさそうですのでひと安心です。

### 何が違うの？
* StethoはAndroidのみしか対応していなかった、FlipperはiOSにも対応している
* プラグインで機能が拡張可能
* 今のところSQLiteの中身を見れるのはStethoだけっぽい(2019/02/08現在)
* chrome://inspect でウインドウを都度開かなくて良いのが地味に助かる

## 出来ること
### Logs
ログ種別が色分けされて見やすいですが、正直AndroidStudioの方で充分そう。

### LayoutInspector
ViewHierarchyが見られます
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/e35e3020-e747-8ef7-f00a-36c02350fe35.png)

### Network
OkHttpClientのInterceptorにFlipperOkhttpInterceptorを渡すことで、アプリからの通信内容が見られます。
この辺りもStethoで出来ていたことですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/51a1587c-c7fb-a83d-965e-6bdfb34d96b8.png)

### Sandbox
予め設定をしておく事によってFlipper経由で入力した値を取得できるようになる模様、iOSは未対応。
RemoteConfig的な解釈でいますが、もっとよく理解したら追記します。

### SharedPreferences
SharedPreferencesの状態を取得、変更履歴の表示（イベントが発生するとChangelogが更新される）出来る上に、値の書き換えまで出来ます。
iOSの方はUserDefaultっぽいですね。
StethoよりUIは使いやすくなっているものの、SharedPreferencesのファイル名をプラグインの追加時に渡さねばならず、なんでも覗けたStethoのほうが便利だった気が:thinking: 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/7128ca2e-4ab2-186c-f8be-00acced268c6.png)

### LeakCanary
LeakCanaryで検出されたリークが自動的に表示されるようです。

### CrashReportPlugin
アプリがクラッシュするとFlipperに通知が表示され"Open in Logs"ボタンを押すとLogsの方で該当箇所が開かれるようです。
α版のようなので動作は怪しそう…
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/6a6157ed-0622-143c-6d4a-26a04d705eba.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/a558f7d4-5f4d-bebf-5aaa-655ae205db2b.png)


## 導入方法
[Getting Started](https://fbflipper.com/docs/getting-started.html)に沿っています。
### Mac側
ダウンロードします。

### Android側
今回はdebugビルドのみ有効にしたいものとします。

大まかな流れとしては
1. app/src/debugフォルダを作成する
2. その配下にDebugAppというクラスを作成する
3. AndroidManifestも作成し、デバッグビルド時のApplicationクラスを上書きする

手順は[デバッグ時のみStetho, LeakCanary, StrictModeを入れる](https://qiita.com/takahirom/items/2cbf307c49048016f5b7)を参考にしています。

```groovy:app/build.gradle
repositories {
  jcenter()
}

dependencies {
    debugImplementation 'com.facebook.flipper:flipper:0.15.0'
    debugImplementation 'com.facebook.soloader:soloader:0.6.0'
}
```

ちなみにいつも忘れて5分くらいハマるのですが、debugディレクトリ側で定義するクラスから継承するために大元のAppクラスは`open class`にしておく必要があります。
また、ここでは試しにLayoutInspectorとSharedPreferencesのプラグインを有効にしています。

```kotlin:path/to/debug/src/DebugApp.kt
class DebugApp : App() {

    override fun onCreate() {
        super.onCreate()
        initFlipper()
    }

    private fun initFlipper() {
        SoLoader.init(
            this,
            false
        )
        if (FlipperUtils.shouldEnableFlipper(this)) {
            AndroidFlipperClient.getInstance(this).apply {
                addPlugin(
                    InspectorFlipperPlugin(
                        this@DebugApp,
                        DescriptorMapping.withDefaults()
                    )
                )
                addPlugin(
                    SharedPreferencesFlipperPlugin(
                        this@DebugApp,
                        PrefsConst.FILE_NAME
                    )
                )
            }.start()
        }
    }
}
```
デバッグビルド用のAndroidManifest.xmlにINTERNETとACCESS_WIFI_STATEのパーミッションを追加します。
更に公式のドキュメントで推奨されていたのでFlipperDiagnosticActivityも定義しています。

```xml:app/src/debug/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:name=".DebugApp"
        tools:replace="android:name">
        <activity android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
            android:exported="true"/>
    </application>

</manifest>
```

ここまで設定したらあとはdebugビルドするだけで動くはずです。

## おわりに
全体的にStethoよりもUIは見やすいものの、DBの中身を覗けないのでSQLiteを使っているなら今の所Stethoは外せないかなという印象でした。
とはいえ、[Issueは上がっている](https://github.com/facebook/flipper/issues/33)のと、プラグイン開発も出来るようなのでそのへんの課題が解決されるのは時間の問題かもしれません。

現時点ではデバッグビルド時のみ有効にする設定にしておけば本番コードへの影響も無い[^1]ので、Stethoと併用して様子見がベターかなという結論です。

興味を持った方は、最新の情報を得るためにも[公式サイト](https://fbflipper.com/)を見るのをおすすめします。
この記事の内容はきっとすぐに陳腐化します、するはず、してくれ。

[^1]: ただしOkHttpを使うとなると話が別です、現状no-opのパッケージも無いので一工夫が必要。