Proguard makes reflection with the R class in android application no longer work

久未见 提交于 2019-12-07 02:13:32

问题


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:


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.



来源:https://stackoverflow.com/questions/13923815/proguard-makes-reflection-with-the-r-class-in-android-application-no-longer-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!