Java Android 中的 Proguard 和反射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4447145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 17:36:49  来源:igfitidea点击:

Proguard and reflection in Android

javaandroidreflectionobfuscationproguard

提问by jax

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

我刚刚使用了 proguard,但是我试图通过反射实例化的类不起作用。

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

这是我的 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(...);
}

采纳答案by jax

SOLVED

解决了

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

对于遇到此问题的其他人,您需要将以下内容添加到 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

第一个 keep 告诉 proguard 不要混淆扩展 YourClassName 的类名

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

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

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

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

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

This says keep all methods named myClickHandlerwith a single argument Viewin all classes. You could further constrain this by using the extends keyword like above.

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

hope this helps.

希望这可以帮助。

回答by Amir Raminfar

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.

查找所有以 View 作为参数的方法。

回答by Drown Coder

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.

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

So you should keep the constructor method in proguard file.

因此,您应该将构造函数方法保留在 proguard 文件中。

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