Proguard and Reflection in Android

Proguard and reflection in Android

SOLVED

For others that are having this problem you need to add the following to proguard.cnf

-keep public class * extends com.yoursite.android.yourappname.YourClassName

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
public <init>(android.content.Context);
}

The first keep tells proguard to not obfuscate class names that extend YourClassName

The second one says to keep the constructor name (<init> means constructor) un-obfuscated that has a single argument of Context and extends YourClassName

In addition, for android developers that are using the onClick attribute in you XML layouts file you will also need to add the name of the function in your proguard.cnf file.

-keepclassmembers class * {
public void myClickHandler(android.view.View);
}

This says keep all methods named myClickHandler with a single argument View in all classes. You could further constrain this by using the extends keyword like above.

hope this helps.

Keep classes that use reflection Android Proguard

This did the trick for me.

# Bottom Navigation Helper
-keep class android.support.design.internal.BottomNavigationItemView{ *; }
-keep class android.support.design.internal.BottomNavigationMenuView{ *; }

Can I use Reflection with ProGuard obfuscated classes?

ProGuard documentation mentions the following:

It is generally impossible to compute which classes have to be
preserved (with their original names), since the class names might be
read from a configuration file, for instance. You therefore have to
specify them in your ProGuard configuration, with the same simple
-keep options.

However, there are SOME cases in which ProGuard automatically handles Reflection. Those are the following: (please refer to the documentation for the most recent list)

  • Class.forName("SomeClass") SomeClass.class
  • SomeClass.class.getField("someField")
  • SomeClass.class.getDeclaredField("someField")
  • SomeClass.class.getMethod("someMethod", new Class[] {})
  • SomeClass.class.getMethod("someMethod", new Class[] { A.class })
  • SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
  • SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
  • SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
  • SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
  • AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
  • AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
  • AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")

So, in my case, my error was that I was getting the class using getClass().
The following line did work great.

aMethod = MainActivity.class.getDeclaredMethod("myMethodName", SomeParameter.class);

How to keep java.lang.reflect when use proGuard?

The reasons behind getting runtime exceptions may vary depending on the code that you implemented.
One of the reasons behind getting the exception may be relying on field/classes/method names in your code using reflection - ProGuard renames your classes while obfuscating so in order to have them accessible after the obfuscation, they need to be prevented explicitly from the obfuscation.

-keep app.package.FancyClass { *; } 

If it is the library itself that crashes the obfuscated app then I suggest finding the exact place and explicitly keeping the classes that the class where the exception occurs depends on.

The easiest case might be to keep the entire library:

-keep com.stone.pile.** { *; } 

but you can very often configure ProGuard to be more aggressive than that. Nevertheless it's a good starting point.

I think -keep java.lang.reflect.** rule does not help much here. The root cause is in the code that relies on class internals that need to be excluded from the obfuscation.

Locate the vulnerable code and try to keep the classes/methods/internals accessed via reflection.

EDIT:
It would be of great help if you pasted the class file with the place where the exception is thrown pointed. The exception message would also add up to the context. Can you do that please?

How to get class package after obfuscation for use in reflection with Proguard on Android

I found elegant solution. I store string constant into environment variable with value of needed class package. I can access any needed obfuscated data via static string key of environment variable. Even class name itself was obfuscated I would get always needed data. It is easy to access this data from any module in application since it is in environment variable.

static {
System.setProperty(Const.NEEDED_PACKAGE, NeededClass.class.getPackage()).getName());
}

Android Proguard/R8 reflection error: NoSuchFieldException

For anybody else who may have this problem in the future, turns out I needed to clean, rebuild, then invalidate cache and restart.

How to keep java.lang.reflect when use proGuard

Reflection will need to have absolute path the the classes and its respective methods. So, you need to tell proguard to leave the stuff you need alone. You can describe this in your proguard-rules.pro file.
Example:

-keep public class fully_qualified_classname
-keepclassmembers public class fully_qualified_classname {
# will ignore all methods
public <methods>;
public static final String static_instance_variable_if_any;
}


Related Topics



Leave a reply



Submit