React NativeのSVGを使うライブラリをAndroidで動かすときにエラー

はじめに

最近、React Nativeの開発を積極的にしています。 その折り、ちょっとしたグラフを書きたくなったのでreact-native-chart-kitというライブラリを使っていました。

www.npmjs.com

iOSでは問題なく動いていたのに、いざAndroidで動かそうとすると動かなかった(しかも実機のみ!)ので、 備忘録として対処を残しておきます。

利用準備

READMEに記載の通り、npmかyarnでライブラリをインストールすることで使うことができます。 なお、react-native-svgが入っていないと動かないので、こちらのライブラリも必要でした。

$ yarn add react-native-svg // 必要であれば
$ yarn add react-native-chart-kit

あとはExampleに記載の通り実装することでバーチャートやパイチャートなどを描画できます。

f:id:horsewin:20190724111701p:plain
こういうやつ

発生した事象

iOS

こちらではシミュレータ、実機いずれも問題なく動きます。

Android

こちらで死にました。。。React Nativeではどちらもテストが必要なのが辛いですね。。。 また、Androidでも下記の通り、挙動が変わります。

動作状況 結果
Android Emulator OK
USBからAPKを転送 OK
APKをインストール NG

単純に実機だとうごかないのではなく、USBデバッグの段階では動くというのが今回いやらしかったです;; NGというのは「[アプリ名]が停止しました」というアラートが出てアプリが落ちた状態を指しています。

原因

adb logcatをしてログを確認すると下記の通り、Exceptionが吐かれていました。 ライブラリ内のNoSuchFieldExceptionとか知らんよーーってなりましたw

07-23 23:00:50.149 10915 10915 E AndroidRuntime: FATAL EXCEPTION: main
07-23 23:00:50.149 10915 10915 E AndroidRuntime: Process: xxxx.xxxx.xxxx, PID: xxxxxx
07-23 23:00:50.149 10915 10915 E AndroidRuntime: java.lang.IllegalStateException: java.lang.NoSuchFieldException: fill
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.v.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.c()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.X.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.v.b()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.c()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.v.b()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.c()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.v.b()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.c()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.j.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.v.b()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.C.a()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.C.j()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.horcrux.svg.C.onDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:17122)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16104)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:17125)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16104)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:17125)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16104)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16099)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:17125)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16104)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16099)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16099)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16099)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.draw(View.java:16888)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at com.facebook.react.views.view.h.dispatchDraw()
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16099)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.149 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.View.updateDisplayListIfDirty(View.java:16067)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:656)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:662)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:770)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2800)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2608)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2215)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1250)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6311)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.Choreographer.doCallbacks(Choreographer.java:683)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.Choreographer.doFrame(Choreographer.java:619)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.os.Handler.handleCallback(Handler.java:751)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:95)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:241)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6217)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
07-23 23:00:50.150 10915 10915 E AndroidRuntime: Caused by: java.lang.NoSuchFieldException: fill
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        at java.lang.Class.getField(Class.java:1549)
07-23 23:00:50.150 10915 10915 E AndroidRuntime:        ... 101 more
07-23 23:00:50.166   756   850 E JavaDumper:FW:  utils.c(248): mkdir (/data/crashdata) failed. File exists

修正内容

困ったときはコミュニティやGoogle様に聞くことが肝心で同じように困った人がやはりいました。下記によるとProguardファイル(proguard.pro)に下記を書くとよいようです。ようするにExceptionの原因となっている、「com.horcrux.svg」パッケージへのリフレクション時の参照時にNo such Fieldといわれているので、参照名と参照プログラムを残すような処理になります。

-keep public class com.horcrux.svg.** {*;} 

github.com

まとめ

相変わらず、React Nativeを書くときはネイティブを触るときのデバッグや各ネイティブ向けの設定が必要だなと痛感しました。