在Android上使用ProGuard和反射= NoSuchFieldException。

3

我叫马修,使用ProGuard后在Android上反射方面遇到了一些问题。

我正在使用libgdx编写游戏,并需要动态获取字符串,我的代码如下:

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中。现在它完美地工作了 :)

1
首先,为什么您需要反射来完成这项任务呢?其次,它不应该是-keepclassmembers class com.PACKAGE.SOME_CLASS吗? - Selvin
我需要使用反射来避免编写大量代码,但这可能不是一个好主意。SOME_CLASS在另一个包中,并且有更多的String字段需要获取,所以我需要编写所有这些字段,以便可以通过反射使用它们?-keepclassmembers class com.ANOTHER_PACKAGE.CLASS { String fileName1; String fileName2; String fileName3; } - miecio
所以SOME_CLASS是来自libgdx的吗?fileName是静态的吗?你知道field.get(null)是用于静态成员的吗?(我知道错误不在这里,但是)你需要传递SOME_CLASS的实例而不是null来获取非静态字段... - Selvin
不是从“Android”部分,而是在编写干净的Java时,我在“核心”部分中使用它。是的,我尝试获取的所有字符串都是静态的。 - miecio
1个回答

0

在你的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 和 Android 中的反射


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接