Problems Running Expo Client From Source

Background

I am trying to work on this pull request to sort out an issue with GCM registration IDs on Android. I’m following the README in the repo to try to build a standalone app to test the code change I’ve made, and check if it causes any side effects. Unfortunately I am unable to successfully build a standalone app following the instructions in the repo.

Environment

I am using Node v7.10.1 alongside NPM v4.2.0. I am using Android Studio v2.3.3 to build the app, and have installed NDK r10e as instructed. I followed the setup instructions precisely, and then followed the instructions under Android under Standalone Apps.

Issues Encountered

When I attempt to build a signed APK, the build itself does not complete successfully. The end of the console trace looks like this:

Warning: 
No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2045-03-12) or after any future revocation date.
spawn zipalign ENOENT
jarsigner: java.io.FileNotFoundException: shell.apk (No such file or directory)
Process exited with non-zero code: 1
cp: shell.apk: No such file or directory
[14:35:01] 'android-shell-app' errored after 9.85 min
[14:35:01] Error: Process exited with non-zero code: 1
    at ChildProcess.child.on (/Users/joshua/Projects/LendOne/Expo/xdl/node_modules/@expo/spawn-async/build/spawnAsync.js:39:21)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at maybeClose (internal/child_process.js:927:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)

When I try to build an APK without signing, again following the instructions in the README, the APK builds successfully. I install it to my test device by running adb install /tmp/shell-debug.apk, and I encounter the “Unfortunately, LendOne Development has stopped” error on the device itself. The trace from the device log looks like this:

E/AndroidRuntime(26180): FATAL EXCEPTION: main
E/AndroidRuntime(26180): Process: one.lend.develop.app, PID: 26180
E/AndroidRuntime(26180): java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;
E/AndroidRuntime(26180):     at com.google.firebase.FirebaseApp.<clinit>(Unknown Source)
E/AndroidRuntime(26180):     at com.google.firebase.provider.FirebaseInitProvider.onCreate(Unknown Source)
E/AndroidRuntime(26180):     at android.content.ContentProvider.attachInfo(ContentProvider.java:1702)
E/AndroidRuntime(26180):     at android.content.ContentProvider.attachInfo(ContentProvider.java:1665)
E/AndroidRuntime(26180):     at com.google.firebase.provider.FirebaseInitProvider.attachInfo(Unknown Source)
E/AndroidRuntime(26180):     at android.app.ActivityThread.installProvider(ActivityThread.java:5417)
E/AndroidRuntime(26180):     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4988)
E/AndroidRuntime(26180):     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4923)
E/AndroidRuntime(26180):     at android.app.ActivityThread.access$1500(ActivityThread.java:144)
E/AndroidRuntime(26180):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1424)
E/AndroidRuntime(26180):     at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(26180):     at android.os.Looper.loop(Looper.java:155)
E/AndroidRuntime(26180):     at android.app.ActivityThread.main(ActivityThread.java:5696)
E/AndroidRuntime(26180):     at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(26180):     at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime(26180):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
E/AndroidRuntime(26180):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
E/AndroidRuntime(26180): Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.util.ArrayMap" on path: DexPathList[[zip file "/data/app/one.lend.develop.app-1/base.apk"],nativeLibraryDirectories=[/data/app/one.lend.develop.app-1/lib/arm, /vendor/lib, /system/lib]]
E/AndroidRuntime(26180):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
E/AndroidRuntime(26180):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
E/AndroidRuntime(26180):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
E/AndroidRuntime(26180):     ... 17 more
E/AndroidRuntime(26180):     Suppressed: java.lang.ClassNotFoundException: android.support.v4.util.ArrayMap
E/AndroidRuntime(26180):         at java.lang.Class.classForName(Native Method)
E/AndroidRuntime(26180):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
E/AndroidRuntime(26180):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
E/AndroidRuntime(26180):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
E/AndroidRuntime(26180):         ... 18 more
E/AndroidRuntime(26180):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
E/ActivityManager(  656): App crashed! Process: one.lend.develop.app

I then tried opening the produced android-shell-app directory in Android Studio, and running the app on my device from Android Studio instead. That builds the APK and installs it on my device just fine, and the app opens and displays a white screen for slightly longer, before it too shows the “Unfortunately, LendOne Development has stopped” error. The trace from the device logs is different:

E/AndroidRuntime( 3830): FATAL EXCEPTION: main
E/AndroidRuntime( 3830): Process: one.lend.develop.app, PID: 3830
E/AndroidRuntime( 3830): java.lang.RuntimeException: Unable to instantiate application host.exp.exponent.ExponentApplication: java.lang.ClassNotFoundException: Didn't find class "host.exp.exponent.ExponentApplication" on path: DexPathList[[zip file "/data/app/one.lend.develop.app-1/base.apk"],nativeLibraryDirectories=[/data/app/one.lend.develop.app-1/lib/arm, /vendor/lib, /system/lib]]
E/AndroidRuntime( 3830):     at android.app.LoadedApk.makeApplication(LoadedApk.java:601)
E/AndroidRuntime( 3830):     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4915)
E/AndroidRuntime( 3830):     at android.app.ActivityThread.access$1500(ActivityThread.java:144)
E/AndroidRuntime( 3830):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1424)
E/AndroidRuntime( 3830):     at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 3830):     at android.os.Looper.loop(Looper.java:155)
E/AndroidRuntime( 3830):     at android.app.ActivityThread.main(ActivityThread.java:5696)
E/AndroidRuntime( 3830):     at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 3830):     at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 3830):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
E/AndroidRuntime( 3830):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
E/AndroidRuntime( 3830): Caused by: java.lang.ClassNotFoundException: Didn't find class "host.exp.exponent.ExponentApplication" on path: DexPathList[[zip file "/data/app/one.lend.develop.app-1/base.apk"],nativeLibraryDirectories=[/data/app/one.lend.develop.app-1/lib/arm, /vendor/lib, /system/lib]]
E/AndroidRuntime( 3830):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
E/AndroidRuntime( 3830):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
E/AndroidRuntime( 3830):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
E/AndroidRuntime( 3830):     at android.app.Instrumentation.newApplication(Instrumentation.java:986)
E/AndroidRuntime( 3830):     at android.app.LoadedApk.makeApplication(LoadedApk.java:587)
E/AndroidRuntime( 3830):     ... 10 more
E/AndroidRuntime( 3830):     Suppressed: java.lang.NoClassDefFoundError: host.exp.exponent.ExponentApplication
E/AndroidRuntime( 3830):         at dalvik.system.DexFile.defineClassNative(Native Method)
E/AndroidRuntime( 3830):         at dalvik.system.DexFile.defineClass(DexFile.java:226)
E/AndroidRuntime( 3830):         at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
E/AndroidRuntime( 3830):         at dalvik.system.DexPathList.findClass(DexPathList.java:321)
E/AndroidRuntime( 3830):         at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
E/AndroidRuntime( 3830):         ... 14 more
E/AndroidRuntime( 3830):     Suppressed: java.lang.ClassNotFoundException: host.exp.exponent.ExponentApplication
E/AndroidRuntime( 3830):         at java.lang.Class.classForName(Native Method)
E/AndroidRuntime( 3830):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
E/AndroidRuntime( 3830):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
E/AndroidRuntime( 3830):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
E/AndroidRuntime( 3830):         ... 13 more
E/AndroidRuntime( 3830):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

Any help to get my development environment for the Expo Client set up would be much appreciated, I simply want to test my changes in that PR and be able to test any changes I make in the future. Many thanks in advance!

Can you try using a simulator running Android 7? Sometimes debug builds have multidex issues on old Android OSes

Thanks for the tip! This works absolutely fine in a simulator, which is great news. I’ll add a comment to the PR when I’ve completed my testing (push notifications doesn’t work in a Genymotion simulator), but it seems to be passing the GCM sender ID through just fine.

It might be worth adding to the README that this doesn’t seem to work correctly for Android <6.

I managed to get this working on an Android 7 device, which to be frank I should have thought of doing earlier! I’ve updated my PR, which should in theory be ready to merge unless there are further points you would like me to address. Many thanks for your assistance!

Thank you for the PR!