Android的@hide注解究竟是做啥的?
Posted
技术标签:
【中文标题】Android的@hide注解究竟是做啥的?【英文标题】:What exactly does Android's @hide annotation do?Android的@hide注解究竟是做什么的? 【发布时间】:2015-11-01 16:44:13 【问题描述】:android 中的许多内部 API 都标记为 @hide
。 究竟是做什么的?
Another answer 表示它只对 Javadoc 隐藏方法,但您可以使用反射来访问它们。
这没有任何意义——如果它们只对 Javadoc 隐藏,那么您肯定不需要反射来访问它们。事实上,我发现我没有。我仍然可以调用一些@hide
方法(也许只是静态方法?),据我所知,该应用程序编译并运行良好。我只是收到一个 lint 错误:
请注意,上面的代码仍然可以正常编译。
我不关心 API 被更改的可能性,所以我很高兴使用私有 API,但是有人可以解释这种行为吗?此外,如果有任何方法可以根据具体情况禁用 lint,这将是有帮助的。
【问题讨论】:
【参考方案1】:这究竟是做什么的?
它控制您正在编译的android.jar
中的内容。
当您的build.gradle
文件中有compileSdkVersion 19
时,真正发生的是$ANDROID_SDK/platforms/android-19/android.jar
被添加到您的编译时类路径中。
该 JAR 是作为编译 Android 本身的一部分而创建的。分析 Android 框架类,并创建它们的副本。本副本:
去除所有标有@hide
的类、方法、字段等
拥有所有剩余方法的存根实现(字面意思是throw new RuntimeException("Stub!")
,我最后一次查看)
为剩下的所有内容保留 JavaDoc cmets
JavaDocs 是根据这个源代码树构建的(这就是 JavaDocs 不显示隐藏方法的原因),并且框架 JAR 的 SDK 版本是根据这个源代码树编译的。
但是你可以使用反射来访问它们
这是因为,在 runtime,real 框架 JAR 位于您的运行时类路径中,从框架类的真实源代码编译而来。它包含所有标记为 @hide
并从编译时框架 JAR 中删除的内容。
我仍然可以调用一些@hide 方法(也许只是静态方法?),据我所知,应用程序编译并运行良好。我只是收到一个 lint 错误
正如 Karakuri 所说,这对我来说确实像是一个编译错误。如果我在 compileSdkVersion 22
项目中尝试您的代码,我会收到编译错误。当我去运行它时,我得到:
/tmp/MyApplication/app/src/main/java/com/commonsware/myapplication/MainActivity.java
Error:(16, 23) error: cannot find symbol method isEmailAddress(String)
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Information:BUILD FAILED
现在,您可以针对以前标有 @hide
的方法进行编译,因为它们在后来的 Android SDK 中未隐藏,并且您的 compileSdkVersion
处于该 API 级别或更高级别.在正式添加到 SDK 之前在 API 级别上使用这些方法是有风险的。
我不关心 API 被更改的可能性
您应该这样做,除非您只为您控制固件的一台设备构建,包括所有操作系统更新。而且,在这种情况下,您可能正在构建自己的固件,因此您可以从您的 Android 分支构建自己的 SDK 框架 JAR,在其中从您想要真正使用的东西中删除 @hide
。
此外,如果有任何方法可以根据具体情况禁用 lint,这将是有帮助的。
根据我从您的屏幕截图和我的电脑中看到的情况,这是来自 IDE 的编译错误。您不能禁用编译错误。
【讨论】:
啊,感谢您提供的非常丰富的答案。尽管有错误,但我绝对可以构建它(在我看来它也像一个编译错误;我认为它是一个 lint,因为它仍然编译时出现 0 个错误)。我想我必须进行更多调查! @Timmmm:虽然我无法为您的案例重现您特定的“仍然允许构建的编译错误”,但我确实在尝试使用时遇到了同样的现象新的shouldShowRequestPermissionRationale()
方法添加到 MNC v2。它显示了在编辑器中看起来像是编译错误的世界,但实际构建很好。我已提交an issue about this。
在哪里可以找到使用“@hide”注释的方法?
@androiddeveloper:对不起,我不明白你的问题。
@CommonsWare 如果我自己添加“@hide”注释,则它不可用。如何在我自己的 android-library 模块中使用它?【参考方案2】:
Google 不知何故使用 @hide
注释从他编译的 Android 框架 jar 中去除他们不想成为公共 SDK 一部分的类和方法,您可以下载并使用这些 jar 来编译您的代码。 (我不知道它是如何工作的细节,所以不要问。)这就是为什么你的 IDE 不能针对它们编译你的代码——它们实际上是不存在的。但是,实际设备上的 android 框架 jar 确实包含这些类和方法,这就是为什么可以在运行时使用反射访问它们的原因。
您在帖子中显示的不是 lint 错误,而是编译错误。它无法解析该方法,这意味着它认为它不是一个有效的方法调用。
【讨论】:
以上是关于Android的@hide注解究竟是做啥的?的主要内容,如果未能解决你的问题,请参考以下文章
-XX:-TieredCompilation 究竟是做啥的?
AVFoundation 的 AVAssetWriterInput 期望MediaDataInRealTime 属性究竟是做啥的?