the source code before compile&proguard :
public class IntentSession extends BaseIntentSession {
@Override
public void onResume() {
super
Most of the time, the website/github of your library provides the necessary proguard rules like retrolamda:
-dontwarn java.lang.invoke.*
-dontwarn **$$Lambda$*
Proguarding is a trail-error story. Check your logging to see which library, class or component causes a problem and add them carefully to the rules :).
Your error NoSuchMethod specifically:
Your code is probably calling something like myClass.getMethod, trying to find some method dynamically. Since ProGuard can't always detect this automatically, you have to keep the missing method in using the appropriate -keep option:
-keepclassmembers class mypackage.MyClass { void myMethod(); }
after re-check carefully, i concluded it probably not a bug of proguard, only gradle.
first, i let the source code using general interface coding style :
mExecutor.exec(getIntent(), new MyInterface() {
@Override
public void execute() {
finish();
}
});
then i clean the build cache and rebuild :
./gradlew clean
./gradlew :app:assembleRelease
I perform the output release app and make it reach the problematic code, it work without crash.
this time i turn to method references :
mExecutor.exec(getIntent(), this::finish);
but i didn't clean the build cache before re-building :
./gradlew :app:assembleRelease
now re-perform with the crash happen :
05-22 11:35:33.870 D/AndroidRuntime( 631): Shutting down VM
05-22 11:35:37.470 E/AndroidRuntime( 631): FATAL EXCEPTION: main
05-22 11:35:37.470 E/AndroidRuntime( 631): Process: com.cmrobot.assistant, PID: 631
05-22 11:35:37.470 E/AndroidRuntime( 631): java.lang.NoSuchMethodError: com.session.a.finish
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.b.executeDone(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:99)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.e(BaseIntentExecutor.java:76)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:67)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.VolumeChangeExecutor.b(VolumeChangeExecutor.java:28)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.a.a(LowerVolumeExecutor.java:63)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.d(BaseIntentExecutor.java:44)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.b.run(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.handleCallback(Handler.java:733)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.dispatchMessage(Handler.java:95)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Looper.loop(Looper.java:136)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.app.ActivityThread.main(ActivityThread.java:5001)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invokeNative(Native Method)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invoke(Method.java:515)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
05-22 11:35:37.470 E/AndroidRuntime( 631): at dalvik.system.NativeStart.main(Native Method)
in order to confirm it is the build cache reason, i clean then re-build on the changed code basically :
./gradlew clean
./gradlew :app:assembleRelease
that crash gone in the afterword app.
i attempt to create a demonstrating project to prove this problem, but that project doesn't popup the crash, only in my productive project.
Working through these bugs that -keep
doesn't fix is a REAL pain and the only way I've ever made headway on them is by following this strategy:
E.G.
Verify that this is an optimization issue or not
-dontoptimize
instead of the -optimizations
string rebuild and test!method/*, !code/*, !class/*, !field/*
until you determine which exclusion makes the issue go away!method/*
, go from it to !method/marking/*
and then if that works too try !method/marking/final
. If that works, then you've found the minimum exclusion)This could very well be a bug in the Proguard rules of one of the libs you're using or in the version of Proguard you're using itself (I've seen both) so try to update both as well.
This happens when a class is looking for, or directly invoking a method of a given argument via reflection in runtime. Proguard can't warn you about this, because there is no link between the obfuscated class and the consumer class in compile time. You can have something like
public class AbstractbaseSomething{
public abstract void doStuff();
}
public class iDoStuff{
public void letsGo(Object o){
Method method = o.getClass().getDeclaredMethod("doStuff");
// do stuff with the method
}
}
Since the method is referenced used a string with the name, proguard does not detect it, and in runtime, you get a crash. the only solution is, assuming you can't modify the code, is to avoid obfuscating the method and class.
(You can check a more realistic example in Ormlite-Android)