question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missing Android consumer proguard rules

See original GitHub issue

Describe the bug We started using shrinking/obfuscation for our java code by setting minifyEnabled true in our build.gradle. We build release builds for testing with the command shown here via ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release. In your docs you mention adding your proguard file shown here, but that doesn’t seem to be enough to test on minified builds, and either our the app will crash in tests or Detox will log errors and tests will fail.

First, we were experiencing immediate crashes when running tests from Exceptions relating to missing classes. There is an existing issue with Android Instrumentation testing in general when minified, so Slack made a plugin called Keeper to address this for now. The short explanation is that Detox relies on some dependencies in the main app apk like Kotlin and React-Native that the test apk is then not able to find at runtime. They are being removed from the main apk during the shrinking process because the main app is not using those classes. This plugin analyzes test code and adds Proguard rules for the main app for classes the test apk relies on. That’s a separate issue, but just noting as it’s not mentioned in your docs as potential watch-out.

That fixed some crashes, but your library also uses reflection in a number of your classes, and the compiler cannot know what classes you’re trying to use dynamically, so they could get removed or obfuscated. We then need additional proguard rules that don’t seem to be in your proguard-rules-app.pro file. For example, we were using react-native 0.63.2 and Detox 17.6.1, and we see several errors like this when running tests on minified builds:

E Detox   : Can't set up RN UIModule listener
E Detox   : org.joor.ReflectException: java.lang.NoSuchFieldException: mOperationsQueue
E Detox   : 	at org.joor.Reflect.field0(Reflect.java:310)
E Detox   : 	at org.joor.Reflect.field(Reflect.java:282)
E Detox   : 	at com.wix.detox.reactnative.idlingresources.UIModuleIdlingResource.isIdleNow(UIModuleIdlingResource.java:84)
E Detox   : 	at androidx.test.espresso.base.IdlingResourceRegistry.allResourcesAreIdle(IdlingResourceRegistry.java:268)
E Detox   : 	at androidx.test.espresso.base.IdlingResourceRegistry$6.isIdleNow(IdlingResourceRegistry.java:302)
E Detox   : 	at androidx.test.espresso.base.UiControllerImpl.loopMainThreadUntilIdle(UiControllerImpl.java:453)
E Detox   : 	at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:275)
E Detox   : 	at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:272)
E Detox   : 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E Detox   : 	at android.os.Handler.handleCallback(Handler.java:790)
E Detox   : 	at android.os.Handler.dispatchMessage(Handler.java:99)
E Detox   : 	at android.os.Looper.loop(Looper.java:164)
E Detox   : 	at android.app.ActivityThread.main(ActivityThread.java:6494)
E Detox   : 	at java.lang.reflect.Method.invoke(Native Method)
E Detox   : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
E Detox   : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
E Detox   : Caused by: java.lang.NoSuchFieldException: mOperationsQueue
E Detox   : 	at java.lang.Class.getField(Class.java:1601)
E Detox   : 	at org.joor.Reflect.field0(Reflect.java:295)
E Detox   : 	... 15 more

I was able to fix some of these just by adding Proguard rules to our main app to just keep all of certain packages as I didn’t know all the classes you might use reflection on.

-keep class com.facebook.react.modules.** { *; }
-keep class com.facebook.react.animated.** { *; }
-keep class com.facebook.react.uimanager.** { *; }

However, today we tried upgrading to 17.10.3 as there are new features and that led to a new crash:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: to.hover.android.app, PID: 26450
    org.joor.ReflectException: org.joor.ReflectException: java.lang.NoSuchFieldException: mTasks
        at org.joor.Reflect.field(Reflect.java:286)
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.pendingTasks(SerialExecutorReflected.kt:14)
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.hasPendingTasks(SerialExecutorReflected.kt:9)
        at com.wix.detox.reactnative.idlingresources.AsyncStorageIdlingResource$idleCheckTaskImpl$1.run(AsyncStorageIdlingResource.kt:39)
        at com.reactnativecommunity.asyncstorage.AsyncStorageModule$g$a.run(AsyncStorageModule.java:1)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: org.joor.ReflectException: java.lang.NoSuchFieldException: mTasks
        at org.joor.Reflect.field0(Reflect.java:310)
        at org.joor.Reflect.field(Reflect.java:282)
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.pendingTasks(SerialExecutorReflected.kt:14) 
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.hasPendingTasks(SerialExecutorReflected.kt:9) 
        at com.wix.detox.reactnative.idlingresources.AsyncStorageIdlingResource$idleCheckTaskImpl$1.run(AsyncStorageIdlingResource.kt:39) 
        at com.reactnativecommunity.asyncstorage.AsyncStorageModule$g$a.run(AsyncStorageModule.java:1) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
        at java.lang.Thread.run(Thread.java:764) 
     Caused by: java.lang.NoSuchFieldException: mTasks
        at java.lang.Class.getField(Class.java:1601)
        at org.joor.Reflect.field0(Reflect.java:295)
        at org.joor.Reflect.field(Reflect.java:282) 
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.pendingTasks(SerialExecutorReflected.kt:14) 
        at com.wix.detox.reactnative.idlingresources.SerialExecutorReflected.hasPendingTasks(SerialExecutorReflected.kt:9) 
        at com.wix.detox.reactnative.idlingresources.AsyncStorageIdlingResource$idleCheckTaskImpl$1.run(AsyncStorageIdlingResource.kt:39) 
        at com.reactnativecommunity.asyncstorage.AsyncStorageModule$g$a.run(AsyncStorageModule.java:1) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
        at java.lang.Thread.run(Thread.java:764) 

It appears that another class AsyncStorageIdlingResource was added that uses reflection on the com.reactnativecommunity.asyncstorage.AsyncStorageModule class from another library we use.

My ask then is can you provide the necessary proguard rules for any case in which you use reflection? It’s important for us to be able to test on minified builds, and it’s difficult and unsustainable for us to look through your code and figure our these rules ourselves and things could still break when you add something new with reflection in between upgrades, like happened with us. These rules can just be included in your proguard-rules-app.pro file or at least suggestions for rules in your docs. Thank you.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:5

github_iconTop GitHub Comments

2reactions
noomorphcommented, Oct 23, 2020
1reaction
d4vidicommented, Dec 9, 2020

So this is turning out to be quite an eye opener – indeed, we were not properly compliant with obfuscating apps! I will have that worked out asap. Thank you!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Android's Built-in ProGuard Rules: The Missing Guide
In this post we'll cover what they all are, what's inside 'em, and what you can do with this knowledge!
Read more >
Android Studio consumerProguardFiles for the library doesn't ...
Run proguard on the app. Let the consumer (application) know, which classes of the library are to be kept. Here's the library build.gradle:...
Read more >
Troubleshooting ProGuard issues on Android - Medium
When ProGuard removes too much. In some cases ProGuard can't know that a class or method is being used, such as when it's...
Read more >
proguard rules get lost when running assembleRelease ...
Enable minify for release builds with the default proguard rule getDefaultProguardFile('proguard-android.txt') . Run ./gradlew clean assembleRelease and check ...
Read more >
Configuring ProGuard | CodePath Android Cliffnotes
Before you start adding any ProGuard rules, you should also check whether any of the libraries you use already come packaged with a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found