36

我刚刚使用了 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(...);
}
4

3 回答 3

61

解决了

对于遇到此问题的其他人,您需要将以下内容添加到 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 不要混淆扩展 YourClassName 的类名

第二个说保持构造函数名称(<init>表示构造函数)不混淆,它有一个参数Context和扩展YourClassName

此外,对于在 XML 布局文件中使用 onClick 属性的 Android 开发人员,您还需要在 proguard.cnf 文件中添加函数的名称。

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

这表示在所有类中保留所有以myClickHandler单个参数命名的方法。View您可以通过使用类似上面的 extends 关键字来进一步限制这一点。

希望这可以帮助。

于 2010-12-16T03:41:28.347 回答
18

对于单击修复,您不必列出每个方法名称。你可以做:

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

它找到所有具有 View 作为参数的方法。

于 2010-12-16T16:34:12.230 回答
0

因为编译过程会移除不使用的方法,所以即使在编译过程中使用反射调用构造方法也会被移除。

您可以在项目的 usage.txt 中看到编译过程中删除的方法。

所以你应该将构造函数方法保存在 proguard 文件中。

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
 public <init>(android.content.Context);
}
于 2019-04-09T03:27:06.207 回答