【问题标题】:ProGuard on Android + reflection = NoSuchFieldExceptionAndroid 上的 ProGuard + 反射 = NoSuchFieldException
【发布时间】:2014-11-18 12:46:21
【问题描述】:

我叫 Matthew,在使用 ProGuard 后,我在 Android 上的反射遇到了一些麻烦。

我在 libgdx 中编写游戏,我需要动态获取 String,我有这样的东西:

package com.PACKAGE;

    public class CLASS extends ANOTHER_CLASS{

        (...)

    private static void load(String fieldName) {
        Field field;
        String fileName;
        try {
            field = SOME_CLASS.class.getField(fieldName);
            fileName = (String) field.get(null);
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

         SOME_CLASS.SOME_METHOD.load(fileName);

    }

(...)

    private STH get(String fieldName) {
        Field field;
        String fileName;
        try {
            field = SOME_CLASS.class.getField(fieldName);
            fileName = (String) field.get(null);
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

         return SOME_CLASS.SOME_METHOD.get(fileName);

    }

(...)

}

在我导出发布 apk(编译正常)并运行游戏后,我得到 NoSuchFieldException:

java.lang.RuntimeException: java.lang.NoSuchFieldException: FIELD_NAME

我需要在proguard-project.txt 中添加什么来处理这个问题?这不起作用,我不知道该怎么办。

-keepclassmembers class com.PACKAGE.CLASS { 
    String fileName;
}

类看起来像:

package com.ANOTHER_PACKAGE;
public class SOME_CLASS {
    public static final String fieldName1 = "string I want";
    public static final String fieldName2 = "string I want";
    public static final String fieldName3 = "string I want";
}

更新:

感谢@Selvin,答案是

-keepclassmembers class ANOTHER_PACKAGE.SOME_CLASS { 
    public static final <fields>; 
}

project-proguard.txt。现在它完美地工作了:)

【问题讨论】:

  • 首先为什么需要对此进行反思。第二,不应该是-keepclassmembers class com.PACKAGE.SOME_CLASS
  • 我需要反思以避免编写一堆代码,但也许这不是一个好主意。 SOME_CLASS 在另一个包中,我需要获取更多字符串字段,所以我需要编写所有可以通过反射使用的字符串? -keepclassmembers class com.ANOTHER_PACKAGE.CLASS { String fileName1;字符串文件名2;字符串文件名3; }
  • 所以 SOME_CLASS 来自 libgdx ?文件名是静态的吗?你知道field.get(null) 是给静态成员的吗? (我知道错误不在这里但是)您需要传递 SOME_CLASS 的实例而不是 null 来获取非静态字段...
  • 不是来自,但是当你用干净的 Java 编写时,我在“核心”部分使用它,而不是在“Android”部分。是的,我尝试得到的所有字符串都是静态的。

标签: java android reflection libgdx proguard


【解决方案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);
}

参考:Proguard and reflection in Android

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    相关资源
    最近更新 更多