Question

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(...);
}
Was it helpful?

Solution

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.

OTHER TIPS

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.

Because Compilation process will remove the method which is not used ,so the constructor method will be remove even if you use reflection to call during the compilation process.

You could see the method which is be removed during compilation process in the the usage.txt in your project.

So you should keep the constructor method in proguard file.

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
 public <init>(android.content.Context);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top