I’m trying to make sense of the madness that is android versioning / multidexing / etc because currently my app is broken.
So for various reasons I have decided to only support android 5.0 (API 21 / LOLLIPOP …argh! why are there 3 names for it!?) and onward. I know there are lot’s of 4.x devices out there, but i’ve decided that if it simplifies the problem(s) I have (5.0 was the first ART / dex2oat implementation) then I’m prepared to ignore pre 5.0 users for now.
All my questions are in the context of getting a react-native application to work when deployed from the app store.
Currently, in my module/build.gradle
file I have changed the default react-native settings to:
android {
compileSdkVersion 25
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com..."
minSdkVersion 21
targetSdkVersion 25
Other than that I’ve not knowingly messed about with any of the other settings. Proguard rules and minification settings are unchanged.
My app has a few dependencies such as react-native-maps which comfortably put me over the (seemingly insane) 64k method limit. Ok, so why have I reach this level? Well, looking at the method count of the dependencies in my APK I see the major culprits:
- com.google.android.gms: ~18k methods
- com.facebook: ~13k methods
- android: ~34k methods
This puts me ~65K methods already! And that’s with just 1 dependency (react-native-maps) taken into account. The remainder of my deps put this over 147k methods (over double the limit). And looking a bit deeper into the android package is see that most of the methods are in the support package.
Q1: What is a support package? And why are there 4 of them in a react-native app totalling some ~20k methods??? How does anyone build even a trivial react-native app without having to turn on multidex?
Q2: I need to add multiDexEnabled true
to my module/build.gradle
file (as well as dexOptions -> jumboMode -> true
)… right?
Ok, so multidex enabled, and that’s all I need to do because I’m targeting API 21. I don’t need to add compile 'com.android.support:multidex:1.0.1'
to my dependencies and I don’t need to call MultiDex.install(this)
; because:
“Therefore, if your minSdkVersion is 21 or higher, you do not need the multidex support library”
(see https://developer.android.com/studio/build/multidex.html).
Ok, so I try and run my app locally on a physical android 6 device using react-native run-android --variant=release
which should give me the same app as when I release to the app store. And it appears to work. Cool.
So, next lets do a build and submit it to the play store and have a look at the Pre-launch report… which shows my app crashed on 4 out or 7 compatible devices (and wasn’t tested on 7 other v4.4 devices understandably):
Pixel Android 7.1 English Native crash of /system/bin/dex2oat
Galaxy S6 Android 5.1 English java.lang.NoClassDefFoundError: Failed resolution of: Lcom/crashlytics/android/Crashlytics;
The first error is completely un-understandable (for me) right now. But the seconds one is more interesting in this context:
05-17 05:29:51.998: E/AndroidRuntime(12656): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.crashlytics.android.Crashlytics" on path: DexPathList[[zip file "/data/app/com.myappname-1/base.apk"],nativeLibraryDirectories=[/data/app/com.myappname-1/lib/arm, /vendor/lib, /system/lib]]
05-17 05:29:51.998: E/AndroidRuntime(12656): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
I have a dependency on react-native-fabric which internally pulls in this crashlytics jar. It works when I run locally (in both debug AND release modes), and according to the google Pre-launch report it also works on some other devices (Pixel with Android 7.1, Pixel with Android O and a Galaxy S7 Edge with Android 6.0). So what’s going on? Is the class there or not?
So I took a look inside my APK and found 135 dex files (135!? how is that possible?). And then used dexdump
to see if my missing class is actually there… which it is:
`Class descriptor : 'Lcom/crashlytics/android/Crashlytics;’`
Q3: So what does this mean? Some devices just don’t read all the .dex files?
I also tested the released APK on an android 5.0 device and also got the crashlytics error.
Does anyone have the slightest clue as to what's going on.
(Did I mention how much I hate Android right now?)