Que signifie @hide dans le code source Android?

120

Pour le Activitycode source , ligne 3898 (près du bas):

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

Que veut @hidedire?

J'ai trouvé que je public class ChildActivity extends Activity { ... }ne peux pas utiliser / voir Activity.isResumed(). Est-ce normal? Comment puis-je y accéder?

midnite
la source

Réponses:

182

Android dispose de deux types d'API qui ne sont pas accessibles via le SDK.

Le premier est situé dans le package com.android.internal. Le deuxième type d'API est une collection de classes et de méthodes marquées avec l' attribut @hide Javadoc .

À partir d'Android 9 (niveau d'API 28), Google introduit de nouvelles restrictions sur l'utilisation d'interfaces non SDK , que ce soit directement, via réflexion ou via JNI. Ces restrictions sont appliquées chaque fois qu'une application fait référence à une interface non SDK ou tente d'obtenir son handle à l'aide de la réflexion ou de JNI.

Mais avant le niveau d'API 28, les méthodes cachées étaient toujours accessibles via la réflexion Java. L' @hideattribut fait simplement partie de Javadoc (droiddoc également), donc cela @hidesignifie simplement que la méthode / classe / champ est exclue de la documentation de l'API.

Par exemple, la checkUidPermission()méthode ActivityManager.javautilise @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;
}

Cependant, nous pouvons l'appeler par réflexion:

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
la source
1
bonjour @StarPinkER puis-je accorder l'autorisation "android.permission.CHANGE_COMPONENT_ENABLED_STATE" en utilisant une API cachée ou interne ou par reflaction?
Hardik
1
Vérifiez d'abord cette réponse . Cette autorisation est une autorisation de signature / système. Dans la plupart des cas, vous ne pouvez pas obtenir cette autorisation sauf s'il s'agit d'applications système. Cela signifie que vous devez modifier Android Source pour accepter votre application ou faire de votre application une application système et la signer. Cependant, vous ne pourrez pas le faire à moins que vous ne créiez votre propre système Android. La réflexion peut gérer le «masquage» mais ne peut pas changer la logique du système de sécurité Android. Vous pouvez imaginer comment nous pouvons facilement attaquer un appareil Android si nous sommes capables de le faire. @Hardik
StarPinkER
2
Merci pour la réponse, mais je pense qu'il y a deux problèmes dans la réponse, corrigez-moi si je me trompe. J'obtiens une erreur classnotfound si j'essaie de le trouver par "ActivityManager" au lieu de "android.app.ActivityManager" et "m.invoke (c", semble devoir être "m.invoke (null", pour les méthodes statiques et "m. invoke (o, ", où o est un objet de type c, pour les méthodes dynamiques. Désolé pour ma grammaire polonaise :)
lindenrovio
3
Juste une note concernant la réflexion: comme ces méthodes / champs ne font pas partie du SDK officiel, il n'y a aucune garantie qu'ils seront présents dans toute future révision Android.
sstn
2
Si l'annotation supprime uniquement la méthode de la documentation, pourquoi ne puis-je toujours pas l'utiliser dans le code?
Javier Delgado
25
  1. @hideest utilisé pour des éléments qui doivent être visibles pour diverses raisons mais qui ne font pas partie de l'API publiée. Ils ne seront pas inclus dans la documentation lors de l'extraction automatique de l'API de la source.

  2. Vous avez raison, vous ne pouvez pas passer outre. C'est normal, c'est par conception, car il est marqué comme final. Vous devriez pouvoir l' utiliser , bien qu'un éditeur puisse ne pas vous l'afficher comme l'un des choix dans l'intellisense qu'il utilise car il est marqué par @hide, et vous devriez prendre note du point 3 ci-dessous.

  3. Vous ne devez pas du tout l' utiliser car il ne fait pas partie de l'API et les développeurs peuvent le supprimer quand ils le souhaitent. Ils seraient même dans leurs droits, s'ils avaient une tendance sadique, à le remplacer par une fonction qui assemble l'appareil sur lequel il fonctionne (mais peut-être pas au sens juridique strict).

paxdiablo
la source
Oh oui ... c'est finalbien sûr que je ne peux pas le remplacer. Désolé c'est mon erreur: x
midnite
Voulez-vous dire, c'est publicdans toutes les classes pendant la phase de développement. Mais il agit comme privateou /*package*/pour des utilisateurs comme nous?
midnite
Hmm ... C'est juste un commentaire. je comprends ses significations. Mais quoi et où appliquer ce comportement au niveau du code?
midnite
1
Pourquoi c'est public, je ne peux pas vraiment commenter. Peut-être que l'implémentation du code Activityest répartie sur de nombreuses classes et qu'elles ont toutes besoin d'accéder à ce membre. En bout de ligne, il est public mais ne fait pas partie de l'API, ce qui signifie que vous l'utilisez à vos propres risques.
paxdiablo
1
@midnite, Eclipse a son propre compilateur Java qui est sans aucun doute intégré à l'intellisense. Je suggérerais que si vous compiliez ceci avec le SDK Java, il se compilerait très bien. Non pas que je suggère cela bien sûr, voir le point 3.
paxdiablo
4

L' @hideannotation signifie que cette interface ne fait pas partie de l'API publique et ne doit pas être utilisée dans votre code. Les méthodes sont uniquement destinées à un usage interne de l'AOSP.

Google a en fait commencé à restreindre l'utilisation d'interfaces non SDK . Cela inclut les interfaces marquées avec@hide

Les méthodes sont classées en quatre listes:

  • whitelist: le SDK
  • light-greylist: méthodes / champs non SDK qui sont toujours accessibles.
  • liste grise foncée:
    • Pour les applications dont le SDK cible est inférieur au niveau d'API 28: chaque utilisation d'une interface de liste grise foncée est autorisée.
    • Pour les applications dont le SDK cible est de niveau API 28 ou supérieur: même comportement que la liste noire
  • liste noire: restreinte quel que soit le SDK cible. La plateforme se comportera comme si l'interface était absente. Par exemple, il lancera NoSuchMethodError / NoSuchFieldException chaque fois que l'application tente de l'utiliser, et ne l'inclura pas lorsque l'application souhaite connaître la liste des champs / méthodes d'une classe particulière.

Les listes peuvent être trouvées ici: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

leonardkraemer
la source