起因
今早,群友在问,为什么我反射隐藏导航栏,在debug模式可以但是release模式就失效?
看到这个问题,这我遇到过,上回我想实现一个功能。百度以后,一粘,结果用不了。
查看源码以后发现 谷歌将源码里的变量名给改了,所以一部分版本能用,新版本手机用不了。
链接: juejin.cn/post/704186…
所以第一反应,就是查看源码,看看变量名有没有变。
源码
Android API 26
Spinner
ListPopupWindow
一切正常,那会不会是新版本,谷歌有改动呢???
Android API 31
Spinner
果然!多出了一个注释!!! 翻译一下
大概意思就是不让随便使用,所以 为什么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 |