Was genau macht die @hide Annotation von Android?

7

Viele interne APIs in Android sind mit @hide gekennzeichnet. Was genau macht das?

Eine andere Antwort sagt, dass es nur versteckt die Methoden von Javadoc, aber Sie können Reflektion verwenden, um auf sie zuzugreifen.

Das macht aber keinen Sinn - wenn sie nur vor Javadoc versteckt sind, dann brauchen Sie keine Reflexion, um auf sie zuzugreifen. Tatsächlich habe ich festgestellt, dass ich es nicht tue. Ich kann immer noch einige @hide -Methoden aufrufen (vielleicht nur statische?) Und die App kompiliert und läuft gut, soweit ich das beurteilen kann. Ich erhalte nur einen Flusenfehler:

Beachten Sie, dass der obige Code immer noch in Ordnung ist.

Es interessiert mich nicht, ob die API geändert werden kann, daher bin ich froh, die private API verwenden zu können, aber kann jemand dieses Verhalten erklären? Auch wenn es eine Möglichkeit gibt, den Flop von Fall zu Fall zu deaktivieren, wäre das hilfreich.

    
Timmmm 09.08.2015, 19:48
quelle

2 Antworten

15
  

Was genau macht das?

Es steuert, was in android.jar ist, gegen das Sie kompilieren.

Wenn Sie compileSdkVersion 19 in Ihrer build.gradle -Datei haben, passiert wirklich, dass $ANDROID_SDK/platforms/android-19/android.jar Ihrem Klassenpfad für die Kompilierung hinzugefügt wird.

Diese JAR wird als Teil der Kompilierung von Android selbst erstellt. Die Android-Framework-Klassen werden analysiert und eine Kopie davon erstellt. Diese Kopie:

  • Entfernt alle mit @hide

  • markierten Klassen, Methoden, Felder usw.
  • Enthält Stub-Implementierungen aller verbleibenden Methoden (wörtlich throw new RuntimeException("Stub!") , das letzte Mal, als ich nachgesehen habe)

  • Behält die JavaDoc-Kommentare für alles verbleibende

  • bei

Die JavaDocs sind aus diesem Quellbaum aufgebaut (weshalb die JavaDocs keine versteckten Methoden anzeigen), und die SDK-Edition der Framework-JAR wird aus dieser Quellstruktur kompiliert.

  

aber Sie können die Reflektion verwenden, um auf sie zuzugreifen

Dies liegt daran, dass die real -Rahmen-JAR in runtime in Ihrem Klassenpfad zur Laufzeit enthalten ist, der von der eigentlichen Quelle für die Framework-Klassen kompiliert wurde. Es enthält alles, was mit @hide markiert wurde und aus dem JAR-Framework für die Kompilierungszeit entfernt wurde.

  

Ich kann immer noch einige @hide Methoden aufrufen (vielleicht nur statische?) und die App kompiliert und läuft soweit ich weiß. Ich erhalte nur einen Flusenfehler

Wie Karakuri bemerkt hat, sieht das sicher wie ein Kompilierfehler für mich aus. Wenn ich den Code in einem compileSdkVersion 22 -Projekt ausprobiere, erhalte ich einen Kompilierungsfehler. Und wenn ich renne, bekomme ich:

%Vor%

Sie können jetzt gegen Methoden kompilieren, die früher mit @hide markiert waren, weil sie in einem späteren Android SDK nicht verborgen waren, und Ihr compileSdkVersion ist auf dieser API-Ebene oder höher . Die Verwendung dieser Methoden auf API-Ebenen vor dem offiziellen Hinzufügen zum SDK ist riskant.

  

Es ist mir egal, ob die API geändert werden kann

Sie sollten dies tun, es sei denn, Sie erstellen nur ein Gerät, auf dem Sie die Firmware einschließlich aller Betriebssystemaktualisierungen steuern. Und in diesem Fall bauen Sie wahrscheinlich Ihre eigene Firmware auf, und Sie können Ihre eigene SDK-Framework-JAR über Ihre Android-Fork erstellen, in der Sie @hide von den Dingen entfernen, die Sie wirklich verwenden möchten.

  

Auch wenn es eine Möglichkeit gibt, den Lint von Fall zu Fall zu deaktivieren, wäre das hilfreich.

Nach dem, was ich von Ihrem Screenshot und meinem PC sehe, ist das ein Kompilierfehler von der IDE. Sie können Kompilierungsfehler nicht deaktivieren.

    
CommonsWare 09.08.2015, 20:09
quelle
3

Irgendwie verwendet Google die @hide Annotation, um die Klassen und Methoden, die nicht Teil des öffentlichen SDK sein sollen, aus dem kompilierten android Framework zu entfernen, das Sie herunterladen und mit dem Sie Ihren Code kompilieren. (Ich kenne die Einzelheiten nicht, wie das funktioniert, also frag nicht.) Deshalb kann deine IDE deinen Code nicht gegen sie kompilieren - sie existieren buchstäblich nicht. Allerdings enthält das Android-Framework jar auf einem tatsächlichen Gerät diese Klassen und Methoden, weshalb sie zur Laufzeit über Reflektion aufgerufen werden können.

Was Sie in Ihrem Beitrag angezeigt haben, ist kein Flusenfehler, das ist ein Kompilierungsfehler. Es kann die Methode nicht auflösen, was bedeutet, dass es sich nicht um einen gültigen Methodenaufruf handelt.

    
Karakuri 09.08.2015 19:58
quelle

Tags und Links