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。这里有些东西不对吗?谢谢!

解决方法

the ScaleGestureDetector source code所示:

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

UnsupportedAppUsage意味着如果您的targetSdkVersion大于28(Build.VERSION_CODES.P,则根本无法访问mMinSpan,即使通过{ {3}}。正如该页面所提到的,尝试访问这些非SDK字段时应该使用NoSuchFieldException

当然,再看Restrictions on non-SDK interfaces

mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();

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

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