Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard and reflection in Android

I have just used proguard, but classes I am trying to instantiate via reflection are not working.

I have an interface

Algorithm 

I pass classes like this

AlgorithmFactory.SomeClassThatExtendsAlgorithmImpl.class 

The class is instantiated like this

public ArrayList<Algorithm> getAlgorithms(Context cnx) { ArrayList<Algorithm> list = new ArrayList<Algorithm>();  for(Class<? extends Algorithm> alg: algorithms) {      try {         Constructor<? extends Algorithm> c = alg.getConstructor(Context.class);         list.add(c.newInstance(cnx));     } catch (IllegalArgumentException e) {         Log.e(TAG, "IllegalArgumentException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } catch (InvocationTargetException e) {         Log.e(TAG, "InvocationTargetException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } catch (InstantiationException e) {         Log.e(TAG, "InstantiationException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } catch (IllegalAccessException e) {         Log.e(TAG, "IllegalAccessException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } catch (SecurityException e) {         Log.e(TAG, "SecurityException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } catch (NoSuchMethodException e) {         Log.e(TAG, "NoSuchMethodException", e);         throw new IllegalStateException("There was a problem creating the Algorithm class");     } } return list; } 

Here is my proguard.cnf

-optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*  -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class com.android.vending.licensing.ILicensingService   -keepclasseswithmembernames class * {     native <methods>; }  -keepclasseswithmembernames class * {     public <init>(android.content.Context, android.util.AttributeSet); }  -keepclasseswithmembernames class * {     public <init>(android.content.Context, android.util.AttributeSet, int); }  -keepclassmembers enum * {     public static **[] values();     public static ** valueOf(java.lang.String); }  -keep class * implements android.os.Parcelable {   public static final android.os.Parcelable$Creator *; }  -assumenosideeffects class android.util.Log {     public static *** d(...);     public static *** v(...);     public static *** i(...);     public static *** w(...);     public static *** e(...); } 
like image 493
jax Avatar asked Dec 15 '10 06:12

jax


People also ask

What is the use of ProGuard in Android?

ProGuard is a tool to help minify, obfuscate, and optimize your code. It is not only especially useful for reducing the overall size of your Android application as well as removing unused classes and methods that contribute towards the intrinsic 64k method limit of Android applications.

What is reflection Android?

Reflection allows programmatic access to information about the fields, methods and constructors of loaded classes, and the use of reflected fields, methods, and constructors to operate on their underlying counterparts, within encapsulation and security restrictions.

Does reflection work in Android?

Android supports reflection. Once you've got a prototype running, you can benchmark and determine your bottlenecks. If its reflection, then consider trying to cache interfaces and such to make it a one-off cost, rather than continually resolving the same interfaces from the same instances repeatedly.

What is difference between R8 and ProGuard?

R8 has more Kotlin support than that of Proguard. R8 is having a faster processing time than Proguard which reduces build time. R8 gives better output results than Proguard. R8 reduces the app size by 10 % whereas Proguard reduces app size by 8.5 %.


2 Answers

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.

like image 52
jax Avatar answered Oct 01 '22 02:10

jax


For the on click fix you don't have to list each method name. You can do:

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

which find all methods that have a View as parameter.

like image 40
Amir Raminfar Avatar answered Oct 01 '22 01:10

Amir Raminfar