Co oznacza @hide w kodzie źródłowym Androida?

120

W przypadku Activitykodu źródłowego wiersz 3898 (blisko dołu):

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

Co to @hideznaczy?

Znalazłem, że public class ChildActivity extends Activity { ... }nie mogę użyć / zobaczyć Activity.isResumed(). Czy to normalne? Jak mogę uzyskać do niego dostęp?

północ
źródło

Odpowiedzi:

182

Android ma dwa typy interfejsów API, które nie są dostępne za pośrednictwem zestawu SDK.

Pierwsza znajduje się w opakowaniu com.android.internal. Drugi typ interfejsu API to kolekcja klas i metod, które są oznaczone atrybutem @hide Javadoc .

Począwszy od Androida 9 (poziom API 28), Google wprowadza nowe ograniczenia w używaniu interfejsów innych niż SDK , czy to bezpośrednio, przez odbicie, czy przez JNI. Te ograniczenia są stosowane za każdym razem, gdy aplikacja odwołuje się do interfejsu innego niż SDK lub próbuje uzyskać jego uchwyt przy użyciu odbicia lub JNI.

Ale przed poziomem API 28 dostęp do ukrytych metod był nadal możliwy przez odbicie w Javie. @hideCecha jest tylko część Javadoc (droiddoc również), a więc @hidepo prostu oznacza metodę / klasa / pole są wyłączone z Dokumenty API.

Na przykład checkUidPermission()metoda w ActivityManager.javaużyciu @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;
}

Możemy to jednak nazwać refleksją:

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
źródło
1
witaj @StarPinkER czy mogę przyznać zezwolenie „android.permission.CHANGE_COMPONENT_ENABLED_STATE” przy użyciu ukrytego lub wewnętrznego interfejsu API lub przez odbicie?
Hardik,
1
Najpierw sprawdź tę odpowiedź . To uprawnienie jest uprawnieniem do podpisu / systemu. W większości przypadków nie możesz uzyskać tego uprawnienia, chyba że są to aplikacje systemowe. Oznacza to, że musisz zmodyfikować źródło Androida, aby zaakceptować swoją aplikację lub uczynić ją aplikacją systemową i podpisać ją. Jednak nie będziesz w stanie tego zrobić, chyba że utworzysz własny system Android. Refleksja radzi sobie z „ukrywaniem”, ale nie może zmienić logiki systemu bezpieczeństwa Android. Możesz sobie wyobrazić, jak możemy łatwo zaatakować urządzenie z Androidem, jeśli jesteśmy w stanie to zrobić. @Hardik
StarPinkER,
2
Dziękuję za odpowiedź, ale myślę, że są dwa problemy z odpowiedzią, popraw mnie, jeśli się mylę. Jeśli próbuję znaleźć go za pomocą „ActivityManager” zamiast „android.app.ActivityManager” i „m.invoke (c”, pojawia się „m.invoke (null”, dla metod statycznych) i „m. invoke (o, ", gdzie o jest obiektem typu c, dla metod dynamicznych. Przepraszam za moją polską gramatykę :)
lindenrovio
3
Tylko uwaga dotycząca refleksji: ponieważ te metody / pola nie są częścią oficjalnego zestawu SDK, nie ma gwarancji, że będą obecne w jakiejkolwiek przyszłej wersji Androida.
sstn
2
Jeśli adnotacja usuwa tylko metodę z dokumentacji, dlaczego nie mogę jej nadal używać w kodzie?
Javier Delgado
25
  1. @hidejest używany do rzeczy, które muszą być widoczne z różnych powodów, ale nie są częścią opublikowanego interfejsu API. Nie zostaną uwzględnione w dokumentacji, gdy automagicznie wyodrębnia API ze źródła.

  2. Masz rację, nie możesz tego zmienić. Jest to normalne, to jest zgodne z projektem, ponieważ jest oznaczony jako final. Powinieneś być w stanie go użyć , chociaż redaktor może nie pokazać ci go jako jednej z opcji do wyboru w jakimkolwiek inteligencie, którego używa, ponieważ jest oznaczony @hide, i powinieneś zwrócić uwagę na punkt 3 poniżej.

  3. Należy nie używać go w ogóle, ponieważ nie jest częścią API i programiści mogą go usunąć, gdy chcą. Mieliby nawet prawo, gdyby mieli sadystyczną skłonność do zastąpienia go funkcją, która zepsuje urządzenie, na którym działa (choć może nie w ścisłym sensie prawnym).

paxdiablo
źródło
O tak ... to finaloczywiście nie mogę tego zmienić. Przepraszam, to mój błąd: x
midnite
Czy masz na myśli, że dotyczy to publicwszystkich klas na etapie rozwoju. Ale działa jak privatelub /*package*/dla użytkowników takich jak my?
północ
Hmm ... To tylko komentarz. rozumiem jego znaczenie. Ale co i gdzie wymusić to zachowanie na poziomie kodu?
północ
1
Dlaczego jest to publiczne, nie mogę naprawdę komentować. Być może implementujący kod Activityjest rozproszony na wiele klas i wszystkie muszą mieć dostęp do tego elementu członkowskiego. Podsumowując, jest publiczny, ale nie jest częścią API, co oznacza, że ​​używasz go na własne ryzyko.
paxdiablo
1
@midnite, Eclipse ma swój własny kompilator Javy, który bez wątpienia jest zintegrowany z inteligencją. Sugerowałbym, że gdybyś skompilował to za pomocą Java SDK, skompilowałoby się dobrze. Nie, żebym to sugerował, oczywiście, patrz punkt 3.
paxdiablo,
4

@hideAdnotacja oznacza, że interfejs ten nie jest częścią publicznych API i nie powinny być używane w kodzie. Metody są przeznaczone wyłącznie do użytku wewnętrznego AOSP.

W rzeczywistości Google zaczął ograniczać użycie interfejsów innych niż SDK . Obejmuje to interfejsy oznaczone@hide

Metody są podzielone na cztery listy:

  • biała lista: SDK
  • light-greylist: metody / pola inne niż SDK, które są nadal dostępne.
  • ciemnoszara lista:
    • W przypadku aplikacji, których docelowy pakiet SDK jest poniżej 28 poziomu interfejsu API: dozwolone jest każde użycie ciemnoszarego interfejsu.
    • W przypadku aplikacji, których docelowy pakiet SDK ma 28 lub wyższy poziom interfejsu API: to samo zachowanie, co czarna lista
  • czarna lista: ograniczona niezależnie od docelowego zestawu SDK. Platforma będzie się zachowywać tak, jakby nie było interfejsu. Na przykład wyrzuci NoSuchMethodError / NoSuchFieldException za każdym razem, gdy aplikacja będzie próbować go użyć, i nie będzie go uwzględniać, gdy aplikacja będzie chciała poznać listę pól / metod określonej klasy.

Listy można znaleźć tutaj: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

leonardkraemer
źródło