如何在混淆后获取 class 包,以便在 Android 上使用 Proguard 进行反射

How to get class package after obfuscation for use in reflection with Proguard on Android

目前 class 名称未被混淆。我需要找到特定 class 的混淆包以用于反射。有什么想法吗?

我可以想到两种方法:

  1. /build/outputs/mapping.txt 中读取所需 class 的混淆包名称,然后将其写入文件(例如资产) 您可以在新的构建步骤中将其添加到 apk 中并在您的应用中读取。如果您不打算在您希望访问的那个之前(按字典顺序)添加新的 classes/packages,您甚至可以从 mapping.txt 中选择包名称并将其存储在某处的 String 字段中在应用程序中(但这是高度 unstable/undesirable)。

  2. 声明一个字段,其中包含对您希望通过反射访问的 class 的引用,在某个容易找到的地方(应用程序子 class 的名称和包是没有混淆,因为它们在清单中被引用,所以这将是一个很好的候选者)然后您只需使用该引用:

    public class YourApplication extends Application {
    
        //...
        public static Class<?> yourReflectiveClass = YourReflectiveClass.class;
    
    }
    

然后您访问该字段并根据需要使用它:

//...

Field[] appFields = YourApplication.class.getDeclaredFields();
Field classField = null;
for (Field f : appFields) {
     if (f.getType().equals(Class.class) {
         classField = f;
         break;
     }
}
if (classField != null) {
    Object classInstance = classField.get(null);
    if (classInstance instanceof Class) {
        Class<?> yourReflectiveClass = (Class) classInstance;
        // yourReflectiveClass.getPackage().getName()
    }
}

您可能需要更改 proguard-rules.pro 以将您的新字段保留在混淆变体中。 另请注意,这种(至少部分)破坏了混淆的目的。

我找到了优雅的解决方案。我将字符串常量存储到具有所需 class 包值的环境变量中。我可以通过环境变量的静态字符串键访问任何需要的混淆数据。甚至 class 名字本身也被混淆了,我总是会得到需要的数据。很容易从应用程序中的任何模块访问此数据,因为它在环境变量中。

static {
    System.setProperty(Const.NEEDED_PACKAGE, NeededClass.class.getPackage()).getName());
}