Cosa significa @hide nel codice sorgente di Android?


120

Per il Activitycodice sorgente , riga 3898 (vicino alla fine):

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

Cosa @hidesignifica?

Ho scoperto che public class ChildActivity extends Activity { ... }non posso usare / vedere Activity.isResumed(). È normale? Come posso accedervi?

Risposte:


182

Android ha due tipi di API che non sono accessibili tramite SDK.

Il primo si trova nel pacchetto com.android.internal. Il secondo tipo di API è una raccolta di classi e metodi contrassegnati con l' attributo @hide Javadoc .

A partire da Android 9 (livello API 28), Google introduce nuove restrizioni sull'utilizzo di interfacce non SDK , sia direttamente, tramite reflection, sia tramite JNI. Queste restrizioni vengono applicate ogni volta che un'app fa riferimento a un'interfaccia non SDK o tenta di ottenere il relativo handle utilizzando la reflection o JNI.

Ma prima del livello API 28, era ancora possibile accedere ai metodi nascosti tramite la riflessione Java. L' @hideattributo è solo una parte di Javadoc (anche droiddoc), quindi @hidesignifica semplicemente che il metodo / classe / campo è escluso dai documenti dell'API.

Ad esempio, il checkUidPermission()metodo in ActivityManager.javautilizza @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;
}

Tuttavia, possiamo chiamarlo per riflessione:

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
ciao @StarPinkER posso concedere il permesso "android.permission.CHANGE_COMPONENT_ENABLED_STATE" utilizzando l'API nascosta o interna o tramite reflaction?
Hardik

1
Controlla prima questa risposta . Questa autorizzazione è un'autorizzazione di firma / sistema. Nella maggior parte dei casi, non puoi ottenere questa autorizzazione a meno che non si tratti di applicazioni di sistema. Ciò significa che devi modificare Android Source per accettare la tua app o rendere la tua app un'app di sistema e firmarla. Tuttavia, non sarai in grado di farlo a meno che tu non stia creando il tuo sistema Android. Reflection può gestire il "nascondersi" ma non può modificare la logica del sistema di sicurezza Android. Puoi immaginare come possiamo facilmente attaccare un dispositivo Android se siamo in grado di farlo. @Hardik
StarPinkER

2
Grazie per la risposta, ma penso che ci siano due problemi nella risposta, correggimi se sbaglio. Ottengo l'errore classnotfound se provo a trovarlo con "ActivityManager" invece di "android.app.ActivityManager" e "m.invoke (c", sembra che dovrebbe essere "m.invoke (null", per i metodi statici e "m. invoke (o, ", dove o è un oggetto di tipo c, per i metodi dinamici.
Ci

3
Solo una nota sulla riflessione: poiché questi metodi / campi non fanno parte dell'SDK ufficiale, non vi è alcuna garanzia che saranno presenti in qualsiasi futura revisione di Android.
sstn

2
Se l'annotazione rimuove solo il metodo dalla documentazione, perché non posso ancora usarlo nel codice?
Javier Delgado

25
  1. @hideviene utilizzato per cose che devono essere visibili per vari motivi ma non fanno parte dell'API pubblicata. Non saranno inclusi nella documentazione quando estrae automagicamente l'API dalla sorgente.

  2. Hai ragione, non puoi ignorarlo. Questo è normale, in base alla progettazione, poiché è contrassegnato come final. Dovresti essere in grado di usarlo , anche se un editor potrebbe non mostrartelo come una delle scelte in qualunque senso intellettuale utilizzi perché è contrassegnato con @hide, e dovresti prendere nota del punto 3 di seguito.

  3. Si dovrebbe non utilizzare affatto dal momento che non fa parte delle API e gli sviluppatori in grado di rimuovere ogni volta che lo desiderano. Sarebbero anche nei loro diritti, se fossero sadicamente inclini, a sostituirlo con una funzione che bloccasse il dispositivo su cui girava (anche se forse non in senso stretto legale).


Oh sì ... lo è final ovvio che non posso ignorarlo. Scusa se è stato un mio errore: x
midnite

Vuoi dire, è publicin tutte le classi durante la fase di sviluppo. Ma si comporta come privateo /*package*/per utenti come noi?
mezzanotte

Hmm ... Questo è solo un commento. capisco i suoi significati. Ma cosa e dove applicare questo comportamento a livello di codice?
mezzanotte

1
Perché è pubblico, non posso davvero commentare. Forse l'implementazione del codice Activityè distribuita in molte classi e tutte devono accedere a questo membro. La linea di fondo è che è pubblico ma non fa parte dell'API, il che significa che lo usi a tuo rischio.
paxdiablo

1
@midnite, Eclipse ha il proprio compilatore Java che è senza dubbio integrato con il materiale intellisense. Suggerirei che se lo compilassi con Java SDK, si compilerebbe bene. Non che io lo stia suggerendo ovviamente, vedi punto 3.
paxdiablo

4

Il @hide annotazione significa che questa interfaccia non fa parte dell'API pubblica e non deve essere utilizzata nel codice. I metodi sono solo per uso interno dell'AOSP.

Google ha effettivamente iniziato a limitare l'utilizzo di interfacce non sdk . Ciò include le interfacce contrassegnate con@hide

I metodi sono classificati in quattro elenchi:

  • whitelist: l'SDK
  • light-greylist: metodi / campi non SDK ancora accessibili.
  • dark-greylist:
    • Per le app il cui SDK di destinazione è inferiore al livello API 28: è consentito ogni utilizzo di un'interfaccia dark greylist.
    • Per le app il cui SDK di destinazione è livello API 28 o superiore: stesso comportamento della lista nera
  • blacklist: limitato indipendentemente dall'SDK di destinazione. La piattaforma si comporterà come se l'interfaccia fosse assente. Ad esempio, lancerà NoSuchMethodError / NoSuchFieldException ogni volta che l'app tenta di usarlo e non lo includerà quando l'app desidera conoscere l'elenco di campi / metodi di una particolare classe.

Gli elenchi possono essere trovati qui: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.