React nativeのAndroid特有のトラブルシューティングについてのお話です。Android 4.4でこういうのが出ました。
This app has been build with an incorrect configuration. Please configure your build for VectorDrawableCompat.
スタックトレースから原因を推測してみる
JSのスタックトレース的には
- ReactSwitchManager.java
- SwitchCompat.java
あたりを通っているので、どうやら <Switch>
コンポーネントがやらかしているらしいことまでは分かります。今回のケースでもSwitchを使っていましたし、Switchをコメントアウトしたらエラーが出なくなりました。
JSのスタックトレース的には
JSじゃないですねそうですね
Android開発の経験則から原因を推測してみる
実はスタックトレースを追わなくても、Android開発に慣れ親しんだエンジニアであれば次の2つのキーワードで察しが付いたりします。
- Android 4.4(5.0未満)
- VectorDrawableCompat
VectorDrawableはAndroidでSVGライクなベクターイメージを扱うための機能なのですが、導入されたのはAndroid 5.0からです。それ以下のバージョン向けにはSupport Library(JSでいうPolyfill)が用意されていますが、これもオプトイン方式なので、デフォルトでは有効になっていません。
このSupport Library版VectorDrawableがVectorDrawableCompatです。これを有効にすることで、エラーが解消されます。
そんなわけで、この問題は完全にJava側の方法論でしか解決できないやつでした。Android StudioでLogCatを見てみると、もう少し詳しいスタックトレースが見れます。
直し方
それでは直し方です。できたらAndroid Studioをご用意ください。無ければVS Codeとかでもいいです。
1. build.gradleに設定を追記
app内のbuild.gradleに vectorDrawables.useSupportLibrary = true
を書いてください。VectorDrawableCompatが使えるようになります。
android {
// 省略
defaultConfig {
// 省略
vectorDrawables.useSupportLibrary = true
}
2. 魔法のフラグをオンにする
VectorDrawableCompatを使う場合、本来であれば適切に app:srcCompat
や
ImageView#setImageResource
を利用するなどの措置が必要になりますが、今回のように公式提供のNative Componentsが相手ではそうもいきません。
そんなときのために、少しパフォーマンスを犠牲にするものの、VectorDrawableCompatに関する問題を雑に解決するためのフラグがあります。
public class MainActivity extends ReactActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
上記のように、staticブロックで AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
を実行しておくと、このstaticが生存している間は全ての画像読み込みが「VectorDrawableの可能性あり」と判断されて、様々な判定の対象となります(なのでパフォーマンスが犠牲になるのです)。
3. 解決
私の手元ではこれで無事にSwitchが表示されるようになりました。
もうちょっと正統派の解決策も見つけられそうな気がしなくもないですが、ひとまずこれが手っ取り早いと思います。
最後に
こういうJSer殺しな罠があるのはどうかと思う・・・・
追記:2018.3.29
再発した・・・機種依存の可能性ありますね・・・・