Proguard makes reflection with the R class in andr

2019-04-29 05:35发布

I have activated proguard in my project since I am trying to release this on Google Play. Even though proguard-android.txt has

-keepclassmembers class **.R$* {
public static <fields>;

}

which means it should not obfuscate the R.raw class that I need, I find that when running this code

import headwayEnt.Blackhole_Darksun.R;

private static final String RES_PATH = "headwayEnt.Blackhole_Darksun.R";

public static int getFileHandle(String fileName, String path) {
    String fullPath = RES_PATH + '$' + path;
    if (subClass == null) {
        Class<headwayEnt.Blackhole_Darksun.R> c = null;     
        try {
            c = (Class<R>)Class.forName(RES_PATH);
        } catch(ClassNotFoundException e) {
            e.printStackTrace();
        } catch(ClassCastException e) {
            e.printStackTrace();
        }
        subClass = c.getDeclaredClasses();
    }
    int fileHandle = 0;
    try {
        int i = 0;
        System.out.println("fullPath: " + fullPath + " subclass len: " +
                subClass.length);
        for (; i < subClass.length; ++i) {
            String name = subClass[i].getName();
            if (subClass[i].getName().equals(fullPath)) {
                break;
            }
        }
        System.out.println("found i: " + i);
        Field[] f = subClass[i].getDeclaredFields();
        for (i = 0; i < f.length; ++i) {
            if (f[i].getName().equals(fileName)) {
                break;
            }
        }

        try {
            fileHandle = f[i].getInt(null);
        } catch(IllegalAccessException e) {

        }
    } catch (RuntimeException e) {
        System.out.println("Could not find filename: " + fileName + 
                " with path: " + path);
        throw e;
    }
    return fileHandle;
}

with path raw for example and a filename from there I get an ArrayIndexOutOfBoundsException at line

Field[] f = subClass[i].getDeclaredFields();

since subClass.length is 0.

This thing works just fine if not obfuscating so I figured that the problem is with proguard.

I tried playing with different ways to make it not obfuscate the R classes like this:

-keep public class headwayEnt.HotshotEngine.Resource.ENG_Resource { *; }
-keep class headwayEnt.HotshotEngine.** { *; }
-keep class **.R$*
-keep public class headwayEnt.Blackhole_Darksun.R { *; }
-keep public class headwayEnt.Blackhole_Darksun_Full.R { *; }
-repackageclasses ''
-keep public class **.R {
  public *;
}
-keep public class **.R$* {
  public *;
}

and still doesn't work.

I must mention that all of my code is in a library (headwayEnt.Blackhole_Darksun) and that I reference that library in headwayEnt.Blackhole_Darksun_Full. Basically I am building two versions from the same code, one for full version and one for the free demo. All this obfuscation happens in the application, not in the referenced library (just to be clear).

1条回答
来,给爷笑一个
2楼-- · 2019-04-29 06:07

This should work:

-keepattributes InnerClasses

-keep class **.R
-keep class **.R$* {
    <fields>;
}

The InnerClasses attribute is necessary to get anything from Class$getDeclaredClasses(). The -keep options are necessary to keep the relevant classes and fields, with their original names.

查看更多
登录 后发表回答