在Android源代码中,@hide是什么意思?

135

对于Activity源代码,第3898行(接近底部):

/**
 * @hide
 */
public final boolean isResumed() {
    return mResumed;
}

@hide 是什么意思?

我发现我的 public class ChildActivity extends Activity { ... } 无法使用/查看 Activity.isResumed()。这正常吗?如何访问它?

3个回答

200

Android有两种类型的API无法通过SDK访问。

第一种位于包com.android.internal中。第二种API类型是一组标记有@hide Javadoc属性的类和方法。

从Android 9(API级别28)开始,Google对非SDK接口的使用引入了新限制,无论是直接、反射还是JNI。这些限制在应用程序引用非SDK接口或尝试使用反射或JNI获取其句柄时应用。

但在API级别28之前,隐藏的方法仍然可以通过Java反射访问。 @hide属性只是Javadoc(droiddoc也是如此)的一部分,因此@hide只是简单地表示该方法/类/字段被排除在API文档之外。

例如,ActivityManager.java中的checkUidPermission()方法使用@hide

/** @hide */
public static int checkUidPermission(String permission, int uid) {
    try {
        return AppGlobals.getPackageManager()
                .checkUidPermission(permission, uid);
    } catch (RemoteException e) {
        // Should never happen, but if it does... deny!
        Slog.e(TAG, "PackageManager is dead?!?", e);
    }
    return PackageManager.PERMISSION_DENIED;
}

然而,我们可以通过反射来调用它:

Class c;
c = Class.forName("android.app.ActivityManager");
Method m = c.getMethod("checkUidPermission", new Class[] {String.class, int.class});
Object o = m.invoke(null, new Object[]{"android.permission.READ_CONTACTS", 10010});

1
你好 @StarPinkER,我能否使用隐藏或内部API或反射来授予“android.permission.CHANGE_COMPONENT_ENABLED_STATE”权限? - Hardik
1
首先查看此答案。这个权限是一个签名/系统权限。在大多数情况下,除非是系统应用程序,否则您无法获得此权限。这意味着您需要修改Android源代码以接受您的应用程序或使您的应用程序成为系统应用程序并对其进行签名。但是,除非您正在制作自己的Android系统,否则您将无法执行此操作。反射可以处理“隐藏”,但它无法更改Android安全系统的逻辑。如果我们能够做到这一点,您可以想象我们如何轻松攻击Android设备。@Hardik - StarPinkER
2
谢谢你的回答,但我认为回答中有两个问题,如果我错了,请纠正。如果尝试使用“ActivityManager”而不是“android.app.ActivityManager”查找它,则会出现类未找到错误,并且对于静态方法,“m.invoke(c,”似乎应该是“m.invoke(null,”,对于动态方法,“m.invoke(o,”,其中o是类型为c的对象。对我的波兰语语法感到抱歉 :) - lindenrovio
3
关于反射(reflection)的一点说明:由于这些方法/字段不是官方SDK的组成部分,所以不能保证它们会出现在任何未来的Android版本中。 - sstn
2
如果注释只是从文档中删除了方法,为什么我不能在代码中继续使用它呢? - Javier Delgado
显示剩余4条评论

27
  1. @hide 用于需要出于各种原因可见但不是发布API的一部分。它们在自动从源代码提取API时不会包含在文档中。

  2. 你说得对,你无法覆盖它。这是正常情况,这是设计上的问题,因为它被标记为final。尽管编辑器可能由于被标记为@hide而不显示它作为智能感知中的选择之一,但应该可以使用它,并且您应该注意下面的第3点。

  3. 您根本就不应该使用它,因为它不是API的一部分,开发人员可以随时删除它。如果他们遭受了虐待倾向,甚至可以用使设备变砖的功能替换它(虽然从严格的法律意义上来说可能不行)。


哦,是的……它是 final,当然我不能覆盖它。抱歉,那是我的错误 :x - midnite
你的意思是,在开发阶段它是在所有类中“public”可见的。但对于像我们这样的用户来说,它的行为就像是“private”或“/package/”? - midnite
嗯...那只是一条注释。我理解它的意思。但在代码层面上,要在哪里实现这种行为呢? - midnite
1
我不能真正评论为什么它是公共的。也许实现“Activity”的代码分布在许多类中,它们都需要访问此成员。底线是,它是公共的,但不是API的一部分,这意味着您使用它时要自担风险。 - paxdiablo
1
@midnite,Eclipse有自己的Java编译器,毫无疑问与智能感知工具集成。我建议您使用Java SDK进行编译,这样它就可以正常编译。当然,我并不是在建议您这样做,请参见第3点。 - paxdiablo
显示剩余2条评论

5
@hide 注解表示该接口不是公共 API 的一部分,不应在代码中使用。这些方法仅供 AOSP 内部使用。
Google 实际上已经开始限制非 SDK 接口的使用。这包括标记有 @hide 的接口。
这些方法被分为四个列表:
  • 白名单:SDK
  • 浅灰名单:仍然可以访问非 SDK 方法/字段。
  • 深灰名单:
  • 针对目标 SDK 低于 API 级别 28 的应用程序:允许使用深灰名单接口。
  • 针对目标 SDK 为 API 级别 28 或更高版本的应用程序:与黑名单相同的行为
  • 黑名单:无论目标 SDK 如何都受到限制。平台将表现得好像接口不存在。例如,每当应用程序尝试使用它时,它将抛出 NoSuchMethodError/NoSuchFieldException,并且在应用程序想要知道特定类的字段/方法列表时,不会包括它。

这些列表可以在这里找到


似乎列表不存在。 - Ofek Ron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接