Comment créer le SDK Android avec des API masquées et internes disponibles?

85

Je souhaite reconstruire le SDK Android (ou plutôt uniquement le fichier android.jar) pour inclure des API cachées et internes.

Je n'ai trouvé aucune documentation ou discussion sur la manière de procéder. J'ai un environnement de construction Ubuntu CyanogenMod déjà configuré qui est capable de construire cm7.

Maintenant, j'ai lu que make SDK construira le SDK mais je souhaite créer un SDK qui inclut des méthodes et des champs marqués comme masqués à l'aide de @hide. Est-ce possible?

Ce que je veux faire, c'est apporter des modifications à une application qui utilise une API cachée et afin de la reconstruire, je voudrais utiliser le SDK modifié.

Thomas Hofmann
la source
2
@Hidden cache juste le javadoc, toutes ces méthodes sont toujours disponibles
Blundell
12
@hide les supprime des fichiers de classe.
Thomas Hofmann
Je sais que je pourrais utiliser la réflexion mais je veux changer une application existante qui utilise une API cachée sans refelction et je ne veux pas changer tout le code existant pour utiliser refelction.
Thomas Hofmann
4
Je pense que vous pouvez supprimer l' @Hiddenétiquette de l'API à laquelle vous souhaitez accéder, puis exécuter make update-apiet make SDKcréer votre propre SDK.
dreamtale

Réponses:

68

C'est ce que je fais toujours pour utiliser les API cachées.

  1. Créez le référentiel ou téléchargez les jars à partir de https://sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong
  2. copier / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar (mieux vaut le renommer comme quelque chose comme framework_all.jar)
  3. configurez le chemin de construction de votre projet -> bibliothèques -> ajoutez ces fichiers JAR externes. Dans Order and Export, déplacez-le vers le haut et avant android.jar
Longue
la source
Cela a fonctionné pour moi aussi! maintenant je peux continuer avec la tâche réelle, merci pour cela
CurlyPaul
IMHO, c'est le plus simple et le plus rapide.
Patrick Cho
N'y a-t-il pas un moyen de marquer cela comme la bonne réponse?
Chris Browet
2
cette méthode fonctionne-t-elle avec tous les appareils ou ne fonctionne-t-elle qu'avec l'appareil ciblé?
Hải Phong
Pour définir l'ordre des bibliothèques dans Android Studio, vous devez modifier le .imlfichier du module et amener les bibliothèques souhaitées <orderEntry>avant le SDK Android . Malheureusement, cette technique n'est pas persistante car le fichier sera écrasé une fois que le bouton gradle-sync est enfoncé.
waqaslam
44

J'ai fait quelques recherches à ce sujet et ma conclusion est simplement la suivante: cela ne peut se faire sans pas mal de travail. Lisez le reste de cette réponse pour plus de détails sur ce que j'ai trouvé.


android.jarest en fait composé de l '"api publique" de framework.jaret core.jarqui se trouve system/frameworks/sur l'appareil. android.jarest une sorte de ce que j'appellerais l'en-tête de la bibliothèque Java, toutes les implémentations dans le code d'octet réel sont juste un throw new RuntimeException("stub");, cela vous permet de construire contre android.jar(par exemple dans Eclipse), mais l'exécution doit être effectuée sur un périphérique ou un émulateur.

L'API publique du SDK Android est définie par des classes / méthodes / champs qui ne sont pas précédés de l' @{hide}annotation javadoc. C'est-à-dire que tout ce qui n'est pas annoté est inclus dans le SDK.

android.jarest construit à partir des sources situées dans out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediateslesquelles elle-même est générée par l'outil DroidDoc situé dans build/tools/droiddoc.

DroidDoc est l'outil (probablement adapté de javadoc ou utilisant javadoc) qui génère la documentation du SDK Android. En tant qu'effet secondaire, et probablement parce qu'il analyse déjà tout le javadoc, il crache également les stubs Android qui sont ensuite compilés dans le android.jarqui est distribué dans le SDK.

Donc, pour inclure les éléments cachés, vous pouvez, si vous ne souhaitez inclure que des parties spécifiques, supprimez simplement l' @hideannotation et reconstruisez le SDK.

Cependant, si vous souhaitez inclure toutes les parties cachées, les choses deviennent beaucoup plus compliquées. Vous pouvez modifier DroidDoc (la source appropriée est dans build/tools/droiddoc/src/Stubs.java) de sorte que rien ne soit détecté comme caché. C'est assez trivial et j'ai essayé cela, mais les stubs qui sont ensuite générés ne se compilent pas du tout.

Ma conclusion à présent est que ce n’est tout simplement pas possible. Les stubs générés si vous supprimez la partie de DroidDoc qui détecte les annotations cachées, ne sont tout simplement pas compilables et nécessiteraient un peu de travail pour se compiler correctement.

Ma réponse à vos questions est donc: non, cela ne peut pas être fait sans beaucoup de travail. Pardon.


Une note latérale sur l' mkstubsoutil. mkstubssont utilisés lorsque vous construisez un module complémentaire SDK , c'est-à-dire les modules complémentaires que vous pouvez trouver dans le gestionnaire Android SDK des fournisseurs, par exemple Samsung qui vous fournit une API supplémentaire pour des éléments spécifiques aux téléphones Samsung. mkstubsfait à peu près la même chose que le processus de génération de stubs DroidDoc, mais il n'utilise pas d' @hideannotations, il utilise un .defsfichier décrivant les packages / classes / champs à inclure ou à exclure de votre addon SDK.

Cependant, tout cela n'a aucun rapport avec la question, car la version du SDK Android n'utilise pas l' mkstubsoutil. (Malheureusement.)

Bjarke Freund-Hansen
la source
J'ai jeté un coup d'œil aussi. Outre Droiddoc, il existe un outil appelé mkstubs dans / development / tools / mkstubs. Il est appelé pendant la construction et pour autant que je l'ai vu, il modifiera les fichiers de classe en les stubing. Dans build / core / tasks / sdk-addon.mk, il y a le code suivant: define stub-addon-jar $ (appelez stub-addon-jar-file, $ (1)): $ (1) | mkstubs $ (info Stubbing addon jar using $ (PRODUCT_SDK_ADDON_STUB_DEFS)) $ (hide) java -jar $ (call module-installed-files, mkstubs) $ (if $ (hide) ,, - v) \ "$$ <" "$$ @" @ $ (PRODUCT_SDK_ADDON_STUB_DEFS) endef
Thomas Hofmann
Malheureusement, je ne suis pas dans ce genre de choses, mais moi aussi, il semble que tout dépend d'une variable appelée hide. Je n'ai pas trouvé où ça se passe. Si vous recherchez $ (hide) dans les autres fichiers de construction, vous verrez que beaucoup dépend de cette valeur. Cela semble également affecter la façon dont les bibliothèques C sont construites.
Thomas Hofmann
@ThomasHofmann: Au départ, j'ai également été confus par l'outil mkstubs. Ce que j'ai appris, c'est que mkstubs n'est utilisé que lorsque vous créez un addon sdk (fournisseur), pas lorsque vous construisez simplement le sdk normal. Cependant, mkstubs fait à peu près la même chose que DroidDoc, sauf qu'il n'utilise pas d' @hideannotations, il utilise "juste" un .defsfichier décrivant les packages / classes / champs à inclure dans l'API de l'addon.
Bjarke Freund-Hansen
2
@ThomasHofmann: À propos $(hide), vous vous confondez. $(hide)est simplement un préfixe dans les makefiles pour masquer la ligne de commande réelle du programme en cours d'exécution, rien de plus, et il est utilisé un peu partout partout. Cela n'a rien à voir avec le SDK Android ou l' @hideannotation dans le code source.
Bjarke Freund-Hansen
comment je peux vérifier ce chemin ci-dessus / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
31

Nous pourrions reconstruire les fichiers * .jar à partir de la plate-forme Android.

Tout d'abord, connectez ADB à votre appareil. Puis exécutez:

adb pull /system/framework/core.jar .
adb pull /system/framework/framework.jar .

Le core.jarcontient les bibliothèques Java standard ( java.*) et le framework.jarcontient les bibliothèques Android ( android.*). Ce n'est pas encore utilisable, car les fichiers réels sont au format DEX et non au format JAR.

Nous pourrions convertir ces * .jars au format DEX en vrais JAR à l'aide d'outils tels que dex2jar :

dex2jar core.jar
dex2jar framework.jar

Ensuite, récupérez ces fichiers en utilisant "Ajouter des fichiers JAR externes ..." (en supposant que vous utilisez Eclipse ADT)

  • faites un clic droit sur Project → Properties → Java Build Path → Libraries → Add External JARs... → (Choisissez le core-dex2jar.jaret framework-dex2jar.jard'en haut).

Cela vous permettra d'utiliser les API internes et certaines API Java 7. (D'après ce que je peux voir, l'APK généré ne contient aucun code réel des JAR.)

KennyTM
la source
Merci beaucoup, j'ai essayé de nombreuses façons dont seules vos méthodes fonctionnent pour moi.
SalutonMondo
7
Il est important de noter que cette méthode fonctionne toujours avec ICS et les systèmes ultérieurs, mais nécessite plus de jonglage. Les fichiers concernés sont /system/framework/core.odex, /system/framework/framework.odexet probablement plus. Ceux-ci peuvent être déodexés ( java -jar baksmali-2.0.3.jar -d system.framework -x system.framework/core.odex -o core) et réodexés ( java -jar smali-2.0.3.jar -x -o core.dex core), et seulement après cela dex2jar core.dexfait son travail.
Alex Cohn
impossible de trouver core.jar dans marshmallow
mehmet6parmak
avez-vous une idée pour le noyau et le framework jar dans android p?
Prabhakaran
comment je peux vérifier ce chemin ci-dessus / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
17

Pour Lollipop, le flux est un peu différent:

  1. Obtenez /system/framework/arm/boot.oat à partir de l'appareil Lollipop

  2. Utilisez 'java -jar oat2dex.jar boot boot.oat'

  3. Vous obtiendrez deux dossiers: dex et odex. Allez dans dex et créez 'java -jar dex2jar.jar framework.dex'
  4. Renommez le framework.jar résultant en .zip, extrayez et trouvez les classes dont vous avez besoin
  5. Accédez à [sdk_path] / plates-formes / [target_platform] et extrayez android.jar (renommez-le d'abord en zip).
  6. Copiez les fichiers du framework extrait vers android.jar extraits. Puis compressez en zip et renommez en .jar :)

ps: vous devez probablement répéter les étapes 4 à 6 pour 'framework_classes2.dex'

déviant
la source
Pour l'étape 3, je ne trouve pas le dex2jar.jar à ce lien ... J'ai essayé beaucoup de choses et je n'arrive pas à comprendre. Y a-t-il un lien vers cela quelque part? Se trouve-t-il dans mon SDK Android? Je ne peux pas le trouver.
Dwebtron
Ouais, ça va à un projet github, et peut-être que c'est moi, mais je ne trouve AUCUN fichier se terminant par ".jar" là-bas ...
Dwebtron
1
voir la section 'releases'
deviant
2
Il semble donc que les versions récentes de dex2jar aient changé le format du téléchargement. Décompressez simplement le téléchargement et au lieu de 'java -jar ...' exécutez simplement le script 'd2j-dex2jar.sh' ou 'd2j-dex2jar.bat', selon votre plate-forme, directement sur le fichier framework.dex
CalumMcCall
1
J'ai copié les deux fichiers jar dans le fichier android.jar, maintenant le studio Android me dit Erreur: l'exécution a échoué pour la tâche ': app: processDebugResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command' D: \ Program \ Android \ android-sdk \ build-tools \ 19.1.0 \ aapt.exe ' 'terminé avec une valeur de sortie différente de zéro 1
wutzebaer
16

Vous pouvez télécharger les modifications android.jarà utiliser comme API masquées à partir de ce référentiel . Suivez les instructions.

Anggrayudi H
la source
4
Cette réponse devrait être davantage votée car c'est la solution la plus simple. Les gens, si vous cherchez une solution, sachez que d'autres personnes l'ont déjà fait et ont placé une solution dans ce dépôt github. Utilisez-le et profitez-en! ))
Mixaz
1
Lorsque j'utilise android.jar pour l'API 28, j'obtiens une erreur avec robolectric. A soulevé un problème github.com/anggrayudi/android-hidden-api/issues/62 et merci pour votre pot @Anggrayudi
Prabhakaran
J'ai également fait la même chose pour Android 10, cela ne fonctionne pas pour moi plutôt que j'ai téléchargé à partir d'un autre contributeur github.com/aeab13/android-jar-with-hidden-api . Je suis en mesure d'accéder classe HDMICEC et de construire, mais les codes sont toujours confonds lien .code android.googlesource.com/platform/frameworks/base/+/4e90fcd/...
Babbin Tandukar
15

DroidCon 2011

Ici, Erik Hellman de Sony Ericson explique comment accéder aux API Android cachées:

http://vimeo.com/30180393 (le lien Hmm ne semble pas fonctionner).

Aller à la page web droidcon Jour 2 défiler vers le bas à l' aide des API cachés 10h15 et vous pouvez le regarder là - bas.

Les liens meurent!

J'ai trouvé celui-ci: http://skillsmatter.com/podcast/os-mobile-server/hidden-api je ne sais pas combien de temps il sera en place

Les API officielles du SDK Android sont généralement suffisantes pour la plupart des applications normales. Cependant, il existe parfois des situations dans lesquelles un développeur a besoin d'accéder aux services système internes, aux API et aux ressources qui ne sont pas publiées dans les API officielles. Heureusement, ces API sont toujours disponibles grâce à des astuces intelligentes et peuvent souvent être utiles lors du développement de nouvelles solutions innovantes sur Android. Dans cette session, vous apprendrez comment accéder et utiliser ces API cachées et protégées, les limites de leur utilisation et quelques conseils et astuces sur la façon de les utiliser de manière sûre et contrôlée sur plusieurs appareils de fournisseurs et versions d'Android. Le public verra plusieurs démos avancées que vous ne pouvez normalement pas faire avec Android. Attendez-vous à une session assez avancée avec de nombreuses informations sur les composants internes de la plate-forme Android.

Blundell
la source
1
C'est intéressant mais malheureusement cela ne répond pas à ma question. Je demandais un moyen de reconstruire le SDK avec des éléments cachés inclus.
Thomas Hofmann
Il semble que j'ai trouvé un autre moyen de réaliser ce que je veux. Je vais le décrire demain.
Thomas Hofmann
J'ai découvert que si vous souhaitez compiler la source d'un projet qui utilise une API cachée dans ADT, vous pouvez effectuer les opérations suivantes: 1) Créer un projet Android pour la source. 2) Supprimez le conteneur de chemin de classe Android du chemin de construction 3) Définissez une bibliothèque utilisateur (cochez également la case de la bibliothèque système) qui inclut les fichiers JAR d'une version ASOP ROM, par exemple cm7). Les fichiers JAR que vous utilisez dépendent de ce que vous devez référencer. framework-immediates en fera probablement partie.
Thomas Hofmann
4) Lorsque le projet est maintenant construit, les classes de la bibliothèque utilisateur ne seront pas incluses dans l'APK en cours de création. L'API cachée est visible et tout se compilera très bien.
Thomas Hofmann
@Blundell: Pouvez-vous mettre à jour les liens… ils sont morts!
zombie
12

Essayez de regarder ceci :

L'objectif ultime de ces articles est de donner aux développeurs la puissance des API internes et cachées sans recourir à la réflexion. Si vous effectuez toutes les étapes décrites dans les prochaines parties, vous pourrez utiliser les API internes et masquées comme s'il s'agissait d'API publiques ouvertes. Il n'y aura pas besoin de réflexion.

Mais si vous utilisez ces API non publiques, vous devez être conscient que votre application court de grands risques. Fondamentalement, il n'y a aucune garantie que les API ne seront pas interrompues lors de la prochaine mise à jour du système d'exploitation Android. Il n'y a même aucune garantie d'un comportement cohérent entre les appareils de différents fournisseurs. Vous êtes complètement seul.

Vous pouvez suivre trois scénarios:

  1. Activer les API internes et masquées (scénario A)
  2. Activer uniquement l' API masquée (scénario B)
  3. Activer uniquement l' API interne (scénario C)

Le scénario A est une somme de B et C. Le scénario B est le plus simple (ne nécessite aucune modification du plugin ADT eclipse).

Scénario A : lire les parties 1 , 2 , 3 , 4 , 5

Scénario B : lire les parties 1 , 2 , 3 , 5

Scénario C : lire les parties 1 , 2 , 3 , 4 , 5

Zorb
la source
3
J'ai déjà lu cette entrée de blog. Il mentionne ceci: "1) Android est un projet open source. Nous pouvons télécharger le code source et personnaliser le système de construction afin qu'il n'exclut pas les classes internes et cachées d'Android.jar. C'est un moyen difficile." Malheureusement, cela n'entre pas dans les détails.
Thomas Hofmann
3
Accédez à la dernière partie du billet de blog ( devmaze.wordpress.com/2011/01/19/… ), il y a un lien ( github.com/inazaruk/android-sdk/tree/master/platforms ) vers Android pré-construit API avec toutes les API cachées et internes.
Bob le
1
Les liens indiqués ne sont pas accessibles, nécessitent la permission de l'auteur
SHAHS
comment puis-je vérifier ce chemin ci-dessus / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
1

Une fois, j'ai écrit des scripts Groovy pour extraire les fichiers java d'une extraction de dépôt à partir de http://source.android.com/ , puis les compiler sans avoir besoin d'une chaîne d'outils complète pour compiler toutes les sources Android, y compris les autres étapes nécessaires ( emballage, génération de ressources, etc.).

Ils peuvent être trouvés ici:

https://github.com/thoutbeckers/CollectAndroid

Mais pour sûr, cela nécessitera une mise à jour pour tout ce qui suit Gingerbread, principalement en définissant les bons répertoires dans "rootdirs" dans le fichier de configuration (CollectConfig.groovy).

À l'époque, je l'utilisais régulièrement pour le développement avec toutes les API et sources cachées (également problématiques à l'époque) disponibles.

Comme mentionné ailleurs, com / android / internal / ** sera toujours masqué dans les versions récentes d'ADT en raison de la règle d'accès ajoutée.

thoutbeckers
la source
comment puis-je vérifier ce chemin ci-dessus / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
J'ai archivé ce repo depuis sa dernière mise à jour pour Gingerbread . Vous devrez malheureusement trouver une autre approche.
thoutbeckers
1

La réponse de Long a fonctionné pour moi, mais il me manquait encore certaines classes dont j'avais besoin, en particulier android.provider.Telephony. J'ai pu l'ajouter comme ceci:

  1. Extrayez le fichier framework.jar

    mkdir /tmp/framework
    cp framework.jar /tmp
    cd /tmp/framework
    jar xvf ../framework.jar
    mv android classes
    
  2. Construisez le référentiel Android, qui créera le répertoire out / target / common / obj / JAVA_LIBRARIES

  3. Trouvez où se trouvent les classes manquantes

    $ cd /path/to/out/target/common/obj/JAVA_LIBRARIES
    $ find . | grep "/Telephony.class"
    ./telephony-common_intermediates/classes/android/provider/Telephony.class
    ./android_stubs_current_intermediates/classes/android/provider/Telephony.class
    
  4. Ajoutez les nouvelles classes et reconstruisez le fichier JAR du framework

    cd /tmp/framework
    cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes .
    cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates/classes .
    cd classes
    jar cvf ../framework.jar .
    

Ou vous pouvez simplement être paresseux et inclure toutes les classes dans un fichier jar géant:

cd /tmp/framework
cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/*/classes .
cd classes
jar cvf ../framework.jar .
bmaupin
la source
out / target / common / obj / JAVA_LIBRARIES comment trouver ce chemin?
Bunny
@Bunny J'ai mis à jour ma réponse avec plus de détails. Mais il semble que la réponse ici pourrait être plus simple: stackoverflow.com/a/32626155/399105
bmaupin
merci pour votre réponse @bmaupin ..cpouvez-vous s'il vous plaît m'aider comment je peux trouver ce chemin / target / common / obj / JAVA_LIBRARIES pour obtenir le framework jar ... je suis vraiment coincé ... je ne suis pas en mesure de trouver ce chemin ou il manque quelque chose ... s'il vous plaît guide
Bunny
0

Je ne peux pas faire de commentaire mais c'est essentiellement un commentaire à l' excellente réponse de @ KennyTM ( https://stackoverflow.com/a/13550030/2923406 ):

Si vous vous trouvez avec l'erreur suivante dans Eclipse:

The type com.android.internal.util.Predicate cannot be resolved. It is indirectly referenced from required .class   files

(autrement dit, android.internal. * n'est pas disponible)

Ensuite, une solution possible est d'appliquer la même méthode pour /system/framework/framework2.jar. En utilisant l'émulateur Android pour SDK19, j'ai ce fichier jar supplémentaire. Sur mon HTC One, il y a même un framework3.jar.

Rolf
la source
comment puis-je vérifier ce chemin ci-dessus / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny