为什么我的反射不能用了?

693 阅读2分钟

起因

今早,群友在问,为什么我反射隐藏导航栏,在debug模式可以但是release模式就失效?

image.png

微信图片_20220112103200.png

看到这个问题,这我遇到过,上回我想实现一个功能。百度以后,一粘,结果用不了。
查看源码以后发现 谷歌将源码里的变量名给改了,所以一部分版本能用,新版本手机用不了。
链接: juejin.cn/post/704186…

所以第一反应,就是查看源码,看看变量名有没有变。

源码

Android API 26

Spinner
image.png

ListPopupWindow
image.png

一切正常,那会不会是新版本,谷歌有改动呢???

Android API 31

Spinner
image.png

果然!多出了一个注释!!! 翻译一下

image.png

大概意思就是不让随便使用,所以 为什么release模式就失效的问题原因找到了。

寻根究底

那么这个注释到底是什么意思,是在哪个版本加入的呢?我翻了翻,谷歌官网。

官网地址:developer.android.google.cn/guide/app-c…

在文档中找到了,谷歌在Android 9开始,就逐步给framework层一些开挂调用方式,做限制,比如:反射、JNI等

针对非 SDK 接口的限制

从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。如需详细了解有关此限制的决定,请参阅通过减少非 SDK 接口的使用来提高稳定性

调用这些限制的方法,类,可能会报错,或者闪退,需要注意一下。

访问方式结果
Dalvik 指令引用某个字段抛出 NoSuchFieldError
Dalvik 指令引用某个方法抛出 NoSuchMethodError
通过 Class.getDeclaredField() 或 Class.getField() 进行反射抛出 NoSuchFieldException
通过 Class.getDeclaredMethod()Class.getMethod() 进行反射抛出 NoSuchMethodException
通过 Class.getDeclaredFields()Class.getFields() 进行反射结果中未获取到非 SDK 成员
通过 Class.getDeclaredMethods()Class.getMethods() 进行反射结果中未获取到非 SDK 成员
通过 env->GetFieldID() 进行 JNI 调用返回 NULL,抛出 NoSuchFieldError
通过 env->GetMethodID() 进行 JNI 调用返回 NULL,抛出 NoSuchMethodError

补充

image.png