¿Qué significa @hide en el código fuente de Android?


120

Para el Activitycódigo fuente , línea 3898 (cerca de la parte inferior):

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

¿Qué @hidesignifica?

Encontré que public class ChildActivity extends Activity { ... }no puedo usar / ver Activity.isResumed(). ¿Esto es normal? ¿Cómo puedo acceder a ella?

Respuestas:


182

Android tiene dos tipos de API a las que no se puede acceder a través del SDK.

El primero se encuentra en el paquete com.android.internal. El segundo tipo de API es una colección de clases y métodos que están marcados con el atributo @hide Javadoc .

A partir de Android 9 (nivel de API 28), Google introduce nuevas restricciones sobre el uso de interfaces que no pertenecen al SDK , ya sea directamente, mediante reflexión o mediante JNI. Estas restricciones se aplican cada vez que una aplicación hace referencia a una interfaz que no es SDK o intenta obtener su identificador mediante la reflexión o JNI.

Pero antes del nivel de API 28, todavía se podía acceder a los métodos ocultos a través de la reflexión de Java. El @hideatributo es solo parte de Javadoc (droiddoc también), por lo que @hidesimplemente significa que el método / clase / campo está excluido de los documentos API.

Por ejemplo, el checkUidPermission()método en ActivityManager.javausos @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;
}

Sin embargo, podemos llamarlo por reflexión:

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
hola @StarPinkER ¿puedo otorgar permiso "android.permission.CHANGE_COMPONENT_ENABLED_STATE" usando una api oculta o interna o por reflacción?
Hardik

1
Verifique esta respuesta primero. Este permiso es un permiso de firma / sistema. En la mayoría de los casos, no puede obtener este permiso a menos que se trate de aplicaciones del sistema. Eso significa que necesita modificar Android Source para aceptar su aplicación o hacer de su aplicación una aplicación del sistema y firmarla. Sin embargo, no podrá hacer esto a menos que esté creando su propio sistema Android. Reflection puede manejar la "ocultación" pero no puede cambiar la lógica del sistema de seguridad de Android. Puedes imaginar cómo podemos atacar fácilmente un dispositivo Android si podemos hacer esto. @Hardik
StarPinkER

2
Gracias por la respuesta, pero creo que hay dos problemas en la respuesta, corrígeme si me equivoco. Recibo el error classnotfound si intento encontrarlo con "ActivityManager" en lugar de "android.app.ActivityManager" y "m.invoke (c," parece que debería ser "m.invoke (null," para métodos estáticos y "m. invoke (o, ", donde o es un objeto de tipo c, para métodos dinámicos. Lo siento por mi gramática polaca :)
lindenrovio

3
Solo una nota con respecto a la reflexión: como esos métodos / campos no forman parte del SDK oficial, no hay garantía de que estarán presentes en cualquier revisión futura de Android.
sstn

2
Si la anotación solo elimina el método de la documentación, ¿por qué no puedo seguir usándolo en el código?
Javier Delgado

25
  1. @hidese utiliza para elementos que deben ser visibles por diversas razones, pero que no forman parte de la API publicada. No se incluirán en la documentación cuando extraiga automáticamente la API de la fuente.

  2. Tienes razón, no puedes anularlo. Esto es normal, eso es por diseño, ya que está marcado como final. Debería poder usarlo , aunque es posible que un editor no se lo muestre como una de las opciones en cualquier intellisense que use porque está marcado con @hide, y debe tomar nota del punto 3 a continuación.

  3. Usted debe no utilizarla en absoluto, ya que no es parte de la API y los desarrolladores lo puede quitar siempre que lo deseen. Incluso estarían dentro de sus derechos, si tuvieran una inclinación sádica, reemplazarlo con una función que bloqueara el dispositivo en el que se ejecuta (aunque tal vez no en un sentido legal estricto).


Oh sí ... es finalpor supuesto que no puedo anularlo. Perdón, ese es mi error: x
midnite

¿Quiere decir que está publicen todas las clases durante la etapa de desarrollo? ¿Pero actúa como privateo /*package*/para usuarios como nosotros?
medianoche

Hmm ... Eso es solo un comentario. entiendo sus significados. Pero, ¿qué y dónde hacer cumplir este comportamiento a nivel de código?
medianoche

1
Por qué es público, realmente no puedo comentar. Tal vez la implementación del código Activityse distribuya en muchas clases y todas necesiten acceder a este miembro. En resumen, es público pero no forma parte de la API, lo que significa que lo usa bajo su propio riesgo.
paxdiablo

1
@midnite, Eclipse tiene su propio compilador de Java que sin duda está integrado con las cosas de intellisense. Sugeriría que si compilara esto con el SDK de Java, se compilaría bien. No es que esté sugiriendo esto, por supuesto, vea el punto 3.
paxdiablo

4

La @hideanotación significa que esta interfaz no es parte de la API pública y no debe usarse en su código. Los métodos son solo para uso interno del AOSP.

Google ha comenzado a restringir el uso de interfaces que no son SDK . Esto incluye interfaces marcadas con@hide

Los métodos se clasifican en cuatro listas:

  • lista blanca: el SDK
  • light-greylist: métodos / campos no SDK que aún son accesibles.
  • lista gris oscura:
    • Para aplicaciones cuyo SDK de destino está por debajo del nivel de API 28: se permite cada uso de una interfaz de lista gris oscura.
    • Para aplicaciones cuyo SDK de destino es API nivel 28 o superior: el mismo comportamiento que la lista negra
  • lista negra: restringida independientemente del SDK de destino. La plataforma se comportará como si la interfaz estuviera ausente. Por ejemplo, arrojará NoSuchMethodError / NoSuchFieldException siempre que la aplicación intente usarlo, y no lo incluirá cuando la aplicación quiera conocer la lista de campos / métodos de una clase en particular.

Las listas se pueden encontrar aquí: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.