Android
reactnative

Android 4.4以下でReact NativeのSwitchが動かない場合の対処

More than 1 year has passed since last update.

React nativeのAndroid特有のトラブルシューティングについてのお話です。Android 4.4でこういうのが出ました。

device-2018-02-13-040940.png


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を見てみると、もう少し詳しいスタックトレースが見れます。

スクリーンショット 2018-02-13 4.17.07.png


直し方

それでは直し方です。できたらAndroid Studioをご用意ください。無ければVS Codeとかでもいいです。


1. build.gradleに設定を追記

app内のbuild.gradleに vectorDrawables.useSupportLibrary = true を書いてください。VectorDrawableCompatが使えるようになります。


android/app/build.gradle

android {

// 省略
defaultConfig {
// 省略
vectorDrawables.useSupportLibrary = true
}


2. 魔法のフラグをオンにする

VectorDrawableCompatを使う場合、本来であれば適切に app:srcCompat

ImageView#setImageResource を利用するなどの措置
が必要になりますが、今回のように公式提供のNative Componentsが相手ではそうもいきません。

そんなときのために、少しパフォーマンスを犠牲にするものの、VectorDrawableCompatに関する問題を雑に解決するためのフラグがあります。


android/app/src/main/java/com.yourapp.MainActivity


public class MainActivity extends ReactActivity {

static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}


上記のように、staticブロックで AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); を実行しておくと、このstaticが生存している間は全ての画像読み込みが「VectorDrawableの可能性あり」と判断されて、様々な判定の対象となります(なのでパフォーマンスが犠牲になるのです)。


3. 解決

私の手元ではこれで無事にSwitchが表示されるようになりました。

もうちょっと正統派の解決策も見つけられそうな気がしなくもないですが、ひとまずこれが手っ取り早いと思います。


最後に

こういうJSer殺しな罠があるのはどうかと思う・・・・


追記:2018.3.29

再発した・・・機種依存の可能性ありますね・・・・