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 版本是根据这个源代码树编译的。

但是你可以使用反射来访问它们

这是因为,在 runtimereal 框架 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 属性究竟是做啥的?

Keras 的 ImageDataGenerator 中的剪切究竟是做啥的?

`ssh-keygen -A` 究竟是做啥的?

bind_param() 中的第一个参数究竟是做啥的?