はじめに
Flipperを導入した際に、Networkプラグイン(OkHttpプラグイン)を入れた際にリリースビルドで失敗したので、その時の対応を書いていきます。
Flipperとは
Facebook製のデバッグツールで、iOS、Android両方に対応しています。
この記事はAndroidで使う際の話です。
公式
fliper-noop
flipper-noopはFlipper Interfaceの空実装が用意されているパッケージです。
no-op(no-operation)を利用することで、コンパイルを通しながらリリースビルドからFlipper本体のコードを除去することができます。
公式のドキュメントの例ではに沿ってセットアップします。
ドキュメントでは次のように、releaseImplementationでリリースビルド時にはno-opを使うようにしています。
dependencies {
debugImplementation 'com.facebook.flipper:flipper:0.26.0'
debugImplementation 'com.facebook.soloader:soloader:0.5.1'
releaseImplementation 'com.facebook.flipper:flipper-noop:0.26.0'
}
Networkプラグインの導入
Networkプラグインを入れていきます。
こちらも公式のドキュメントに沿ってやっていきます。
gradleでは debugImplementation
でプラグインを追加します。
dependencies {
debugImplementation 'com.facebook.flipper:flipper-network-plugin:0.26.0'
}
次にアプリケーションの実装でプラグインを使うようにします。
Application
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
client.addPlugin(networkFlipperPlugin);
そしてOkHttpのInterceptorを追加します。
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
new OkHttpClient.Builder()
.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin))
.build();
これでdebugビルドでは問題なく動作します。
プラグインはno-opが無い
リリースビルドでは Unresolved Reference
となり、プラグインの参照を解決できずビルドに失敗します。これはプラグインについてはno-opパッケージに空実装が用意されていないためです。
これについてはIssueで説明されています。メンテコストの観点からプラグインについてはno-opを提供しない方針のようです。
代替として、アプリ側の実装でdebugとreleaseのソースを分けてFlipper関連のコードをそこに集約する方法が推奨されています。
debugとreleaseでFliper関連コードを分ける
ビルドタイプに対応したディレクトリを切り、そこにFlipper関連のコードを集約していきます。
サンプルコードをこちらに置いています。
サンプルでは src/debug
, src/release
にそれぞれデバッグ、リリースビルド用のFlipper関連コード(FlipperInitializer.kt)を分けています。
src/debug/FlipperInitializer.kt
interface InitializationResult {
val okHttpClient: OkHttpClient
}
object FlipperInitializer {
fun initFlipper(context: Context): InitializationResult {
SoLoader.init(context, false)
val networkFlipperPlugin = NetworkFlipperPlugin()
if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(context)) {
val flipperClient = AndroidFlipperClient.getInstance(context)
flipperClient.addPlugin(networkFlipperPlugin)
flipperClient.start()
}
return object : InitializationResult {
override val okHttpClient: OkHttpClient
get() = OkHttpClient.Builder()
.addInterceptor(FlipperOkhttpInterceptor(networkFlipperPlugin))
.build()
}
}
}
リリースビルド用の方には空実装を用意します。
src/release/FlipperInitializer.kt
interface InitializationResult {
val okHttpClient: OkHttpClient
}
object FlipperInitializer {
fun initFlipper(context: Context): InitializationResult {
return object : InitializationResult {
override val okHttpClient: OkHttpClient
get() = OkHttpClient.Builder().build()
}
}
}
Flipperの初期化はFlipperInitializerを呼ぶように置き換えます。
src/main/TutorialApplication.kt
class TutorialApplication : Application() {
override fun onCreate() {
super.onCreate()
val initResult = FlipperInitializer.initFlipper(context = this)
Network.client = initResult.okHttpClient
}
}
これでリリースビルドも成功するようになりました。
最後に
FlipperはStethoに比べるとまだ情報が見つからりにくいですが、とても便利なので積極的に使っていきたいです。
Flipper導入のハンズオン資料を作ってみました