Proguard и размышления в Android

Я только что использовал proguard, но классы, которые я пытаюсь создать через отражение, не работают.

У меня есть интерфейс

Algorithm

Пропускаю такие классы

AlgorithmFactory.SomeClassThatExtendsAlgorithmImpl.class

Класс создается таким образом

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;
}

Вот мой 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(...);
}

Ответ 1

решаемые

Для других, у которых возникает эта проблема, вам нужно добавить следующее в proguard.cnf

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

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

Первый файл keep сообщает proguard о том, что он не обфускает имена классов, которые расширяют ваше имяClassName

Второй говорит, чтобы сохранить имя конструктора (<init> означает конструктор) un-obfuscated, который имеет единственный аргумент Context и расширяет YourClassName

Кроме того, для разработчиков Android, которые используют атрибут onClick в вашем файле макетов XML, вам также нужно будет добавить имя функции в файл proguard.cnf.

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

Это говорит, что все методы с именем myClickHandler имеют один аргумент View во всех классах. Вы можете ограничить это, используя ключевое слово extends, как указано выше.

надеюсь, что это поможет.

Ответ 2

Для исправления по щелчку вам не нужно указывать имя каждого метода. Вы можете сделать:

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

который находит все методы, которые имеют параметр View as.

Ответ 3

Поскольку процесс компиляции удалит метод, который не используется, метод конструктора будет удален, даже если вы используете отражение для вызова во время процесса компиляции.

Вы можете увидеть метод, который будет удален во время процесса компиляции, в файле use.txt в вашем проекте.

Поэтому вы должны оставить метод конструктора в файле proguard.

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