首页 > 解决方案 > Android ProGuard 中的 NoSuchFieldException

问题描述

我尝试使用反射在 android.view.ScaleGestureDetector 中获取字段 mminSapn

    ScaleGestureDetector  sgd = new ScaleGestureDetector(view.getContext(), sl);
    try {
        Field field = sgd.getClass().getDeclaredField("mMinSpan");
        field.setAccessible(true);
        field.set(sgd,1);
    } catch (Exception e) {
        e.printStackTrace();
    }

但它总是有NoSuchFieldException,我发现它可能是由ProGuard引起的。所以我编辑了我的 proguard-rules.pro,添加了一些代码:

-keepclassmembers class android.view.ScaleGestureDetector {
private  <fields>;
}

或者

-keepclassmembers class android.view.ScaleGestureDetector {
 private *;
}

它仍然有 NoSuchFieldException。这里有什么不对吗?谢谢!

标签: javaandroidproguardscale

解决方案


源代码所示ScaleGestureDetector

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768938)
private int mMinSpan;

UnsupportedAppUsage意味着如果你有一个targetSdkVersion大于 28 的值(Build.VERSION_CODES.P你根本无法访问mMinSpan,即使通过非 SDK 接口的限制所解释的反射也是如此。正如该页面所提到的,NoSuchFieldException在尝试访问这些非 SDK 字段时需要a .

当然,再次查看源代码

mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();

并且API 29 中公共 API 的一部分(恰好当您无法通过反射访问该字段时)。因此,您可以在 API 28 或更低版本上运行基于反射的代码,并在 API 29 或更高版本上使用公共 API:getScaledMinimumScalingSpan()

ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
in minSpan = viewConfiguration.getScaledMinimumScalingSpan();

推荐阅读