在Android ProGuard中的NoSuchFieldException。

huangapple go评论193阅读模式
英文:

NoSuchFieldException in Android ProGuard

问题

我尝试使用反射来获取 Android 中的 android.view.ScaleGestureDetector 类中的 mMinSpan 字段。

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。这里有什么地方不对吗?谢谢!

英文:

I try to use reflection to get field mMinSapn in android.view.ScaleGestureDetector

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

but it always has NoSuchFieldException, I find that it may be caused by ProGuard.
So I edit my proguard-rules.pro,add some code:

-keepclassmembers class android.view.ScaleGestureDetector {
private  &lt;fields&gt;;
}

or

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

it still has NoSuchFieldException.Something here is not right? Thank you!

答案1

得分: 3

如在 [`ScaleGestureDetector` 源代码](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/ScaleGestureDetector.java;l=147) 中所示:

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

UnsupportedAppUsage 表示,如果您的 targetSdkVersion 大于 28(即 Build.VERSION_CODES.P),您将无法访问 mMinSpan,即使通过反射也不行,正如非 SDK 接口的限制所解释的那样。正如该页面所述,尝试访问这些非 SDK 字段时将会引发 NoSuchFieldException

当然,再次查看源代码

mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();

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

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

<details>
<summary>英文:</summary>

As seen in [the `ScaleGestureDetector` source code](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/ScaleGestureDetector.java;l=147):

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


The `UnsupportedAppUsage` means that if you have a `targetSdkVersion` greater than 28 (the `Build.VERSION_CODES.P`, you cannot access `mMinSpan` at all, even via reflection as explained by the [Restrictions on non-SDK interfaces][1]. As that page mentions, a `NoSuchFieldException` is expected when trying to access these non-SDK fields.

Of course, looking again [at the source code][2]:

mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();


And [`getScaledMinimumScalingSpan()`][3] **is** part of the public API in API 29 (exactly when you cannot access the field via reflection). Therefore you can run your reflection based code on API 28 or lower and use the public API on API 29 and higher:

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


  [1]: https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces
  [2]: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/ScaleGestureDetector.java;l=204
  [3]: https://developer.android.com/reference/android/view/ViewConfiguration#getScaledMinimumScalingSpan()

</details>



# 答案2
**得分**: 0

```plaintext
我从`compileSdkVersion` 30将`ScaleGestureDetector`类复制到了我的项目中。

与此同时,我改变了`mMinSpan`:

从:

    mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();

改为:

    mMinSpan = 0;
英文:

I copied the ScaleGestureDetector class into my project from compileSdkVersion 30.

At the same time, changed mMinSpan:

From:

mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();

To:

mMinSpan = 0;

huangapple
  • 本文由 发表于 2020年8月26日 13:52:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63591250.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定