【问题标题】:What does @hide mean in the Android source code?Android 源代码中的@hide 是什么意思?
【发布时间】:2013-06-06 18:44:50
【问题描述】:

对于Activity source code,第 3898 行(靠近底部):

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

@hide 是什么意思?

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

【问题讨论】:

    标签: android android-activity android-source


    【解决方案1】:

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

    第一个位于包com.android.internal 中。第二种 API 类型是用@hide Javadoc attribute 标记的类和方法的集合。

    从 Android 9(API 级别 28)开始,Google 引入了new restrictions on the use of non-SDK interfaces,无论是直接、通过反射还是通过 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});
    

    【讨论】:

    • 你好 @StarPinkER 我可以使用隐藏或内部 api 或通过反射授予“android.permission.CHANGE_COMPONENT_ENABLED_STATE”权限吗?
    • 首先检查this answer。此权限是签名/系统权限。在大多数情况下,除非是系统应用程序,否则您无法获得此权限。这意味着您需要修改 Android Source 以接受您的应用程序或使您的应用程序成为系统应用程序并对其进行签名。但是,除非您正在制作自己的 Android 系统,否则您将无法做到这一点。反射可以处理“隐藏”,但它不能改变 Android 安全系统的逻辑。您可以想象,如果我们能够做到这一点,我们将如何轻松攻击 Android 设备。 @Hardik
    • 感谢您的回答,但我认为答案有两个问题,如果我错了,请纠正我。如果尝试通过“ActivityManager”而不是“android.app.ActivityManager”和“m.invoke(c”) 来查找它,我会收到 classnotfound 错误,对于静态方法和“m.invoke(null”) 似乎应该是“m.invoke(null”)。 invoke(o,",其中 o 是 c 类型的对象,用于动态方法。对不起我的波兰语语法:)
    • 关于反射的说明:由于这些方法/字段不是官方 SDK 的一部分,因此无法保证它们会出现在任何未来的 Android 版本中。
    • 如果注解只是从文档中移除了方法,为什么我还不能在代码中使用呢?
    【解决方案2】:
    1. @hide 用于出于各种原因需要可见但已发布 API 的一部分。当它自动从源中提取 API 时,它们不会包含在文档中。

    2. 你是对的,你不能覆盖它。这是正常的,这是设计使然,因为它被标记为final。您应该能够使用它,尽管编辑器可能不会将它作为它使用的任何智能感知的选择之一显示给您,因为它标有@hide,您应该注意第 3 点下面。

    3. 您根本不应该使用它,因为它不是 API 的一部分,开发人员可以随时将其删除。他们甚至可以在他们的权利范围内,如果他们有虐待倾向的话,可以将它替换为一个阻止它运行的设备的功能(尽管可能不是严格的法律意义上的)。

    【讨论】:

    • 哦,是的...它是final,当然我不能覆盖它。对不起,这是我的错误:x
    • 你的意思是,在开发阶段所有类都是public。但它对我们这样的用户来说就像private/*package*/
    • 嗯...这只是一个评论。我理解它的含义。但是在代码级别执行此行为的内容和位置是什么?
    • 为什么它是公开的,我无法评论。也许实现Activity 的代码分布在很多类中,它们都需要访问这个成员。底线是,它公开的,但不是 API 的一部分,这意味着您使用它需要您自担风险。
    • @midnite,Eclipse 有它自己的 Java 编译器,毫无疑问,它与 intellisense 的东西集成在一起。我建议如果您使用 Java SDK 编译它,它会编译得很好。当然不是我建议这样做,请参阅第 3 点。
    【解决方案3】:

    @hide 注释表示此接口不是公共 API 的一部分,不应在您的代码中使用。这些方法仅供 AOSP 内部使用。

    Google 实际上已经开始restrict the usage of non-sdk interfaces。这包括标有@hide的接口

    方法分为四个列表:

    • 白名单:SDK
    • light-greylist:仍可访问的非 SDK 方法/字段。
    • 深灰名单:
    • 对于目标 SDK 低于 API 级别 28 的应用:允许每次使用深灰名单接口。
    • 对于目标 SDK 为 API 级别 28 或更高级别的应用:与黑名单行为相同
    • 黑名单:不受目标 SDK 限制。平台的行为就像没有接口一样。例如,它会抛出 每当应用程序尝试执行 NoSuchMethodError/NoSuchFieldException 使用它,当应用想知道它的列表时不会包含它 特定类的字段/方法。

    名单可以在here找到

    【讨论】:

    • 列表好像没有
    猜你喜欢
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多