¿Cómo creo el SDK de Android con API internas y ocultas disponibles?

85

Quiero reconstruir el SDK de Android (o más bien solo el android.jar) para incluir API ocultas e internas.

No pude encontrar ninguna documentación o discusión sobre cómo hacer esto. Tengo un entorno de compilación Ubuntu CyanogenMod ya configurado que puede compilar cm7.

Ahora, leí que make SDK creará el SDK, pero quiero crear un SDK que incluya métodos y campos marcados como ocultos con @hide. es posible?

Lo que quiero hacer es realizar cambios en una aplicación que usa una API oculta y para reconstruirla me gustaría usar el SDK modificado.

Thomas Hofmann
fuente
2
@Hidden solo oculta el javadoc, todos estos métodos aún están disponibles
Blundell
12
@hide los elimina de los archivos de clase.
Thomas Hofmann
Sé que podría usar la reflexión, pero quiero cambiar una aplicación existente que usa una API oculta sin refelcción y no quiero cambiar todo el código existente para usar refelction.
Thomas Hofmann
4
Creo que puede eliminar la @Hiddenetiqueta de la API a la que desea acceder, luego ejecutar make update-apiy make SDKconstruir su propio SDK.
Dreamtale

Respuestas:

68

Esto es lo que siempre hago para usar una API oculta.

  1. Cree el repositorio o descargue los archivos jar desde https://sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong
  2. copiar / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar (mejor renombrarlo como algo como framework_all.jar)
  3. configure la ruta de construcción de su proyecto -> bibliotecas -> agregue estos frascos externos. En Order and Export, muévalo hacia arriba y antes de android.jar
Largo
fuente
¡Esto también funcionó para mí! ahora puedo continuar con la tarea real, gracias por esto
CurlyPaul
En mi humilde opinión, este es el más fácil y el más rápido.
Patrick Cho
¿No hay alguna forma de marcar esto como la respuesta adecuada?
Chris Browet
2
¿Este método funciona con todos los dispositivos o solo funciona con el dispositivo de destino?
Hải Phong
Para definir el orden de las bibliotecas en Android Studio, debe modificar el .imlarchivo del módulo y traer las bibliotecas deseadas <orderEntry>antes del SDK de Android . Desafortunadamente, esta técnica no es persistente ya que el archivo se sobrescribirá una vez que se presione el botón Gradle-Sync.
waqaslam
44

He investigado un poco sobre esto y mi conclusión es sencilla: esto no se puede hacer sin bastante trabajo. Lea el resto de esta respuesta para obtener detalles sobre lo que he encontrado.


android.jaren realidad está compuesto por la "API pública" de framework.jary core.jarque se encuentra en system/frameworks/el dispositivo. android.jares una especie de lo que yo llamaría el encabezado de la biblioteca de Java, todas las implementaciones en el código de bytes real son solo una throw new RuntimeException("stub");, esto le permite construir contraandroid.jar (por ejemplo, en Eclipse), pero la ejecución debe realizarse en un dispositivo o emulador.

La API pública del SDK de Android se define mediante clases / métodos / campos que no tienen como prefijo la @{hide}anotación javadoc. Es decir todo lo que no es anotado está incluido en el SDK.

android.jarse construye a partir de las fuentes ubicadas en las out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediatesque se genera la herramienta DroidDoc ubicada enbuild/tools/droiddoc .

DroidDoc es la herramienta (probablemente adaptada de javadoc o usando javadoc) que genera la documentación real del SDK de Android. Como efecto secundario, y probablemente porque ya está analizando todo el javadoc, también arroja los stubs de Android que luego se compilan en elandroid.jar que se distribuye en el SDK.

Entonces, para incluir las cosas que están ocultas, podría, si solo desea incluir partes específicas, simplemente elimine el @hide anotación y reconstruya el SDK.

Sin embargo, si desea incluir todas las partes ocultas, las cosas se complican mucho más. Puede modificar DroidDoc (la fuente relevante está enbuild/tools/droiddoc/src/Stubs.java ) de modo que no se detecte nada como oculto. Esto es bastante trivial y lo he intentado, sin embargo, los stubs que luego se generan no se compilan en absoluto.

Mi conclusión a estas alturas es que esto simplemente no es factible. Los stubs generados si elimina la parte de DroidDoc que detecta anotaciones ocultas, simplemente no son compilables y requerirían bastante trabajo para compilarse correctamente.

Entonces, mi respuesta a sus preguntas es: No, esto no se puede hacer sin hacer mucho trabajo. Lo siento.


Una nota al margen sobre la mkstubsherramienta. mkstubsse utilizan cuando crea un complemento de SDK , es decir, los complementos que puede encontrar en el administrador de SDK de Android de los proveedores, por ejemplo, Samsung le proporciona una API adicional para cosas específicas de los teléfonos Samsung. mkstubshace lo mismo que el proceso de generación de stubs de DroidDoc, sin embargo, no usa @hideanotaciones, usa un .defsarchivo que describe qué paquetes / clases / campos incluir o excluir de su complemento SDK.

Sin embargo, todo esto es irrelevante para la pregunta, ya que la compilación del SDK de Android no usa la mkstubsherramienta. (Desafortunadamente.)

Bjarke Freund-Hansen
fuente
Yo también eché un vistazo. Además de Droiddoc, existe una herramienta llamada mkstubs en / development / tools / mkstubs. Se llama durante la compilación y, por lo que he visto, modificará los archivos de clase eliminando cosas de ellos. En build / core / tasks / sdk-addon.mk hay el siguiente código: define stub-addon-jar $ (llamada stub-addon-jar-file, $ (1)): $ (1) | mkstubs $ (info Stubbing addon jar usando $ (PRODUCT_SDK_ADDON_STUB_DEFS)) $ (hide) java -jar $ (llame a module-installed-files, mkstubs) $ (if $ (hide) ,, - v) \ "$$ <" "$$ @" @ $ (PRODUCT_SDK_ADDON_STUB_DEFS) endef
Thomas Hofmann
Desafortunadamente, no estoy en esto, pero también me parece que todo depende de una variable llamada hide. Sin embargo, no he encontrado dónde se establece. Si busca $ (hide) en los otros archivos de compilación, verá que mucho depende de este valor. También parece afectar la forma en que se construyen las bibliotecas de C.
Thomas Hofmann
@ThomasHofmann: Al principio también me confundió la herramienta mkstubs. Lo que he aprendido es que mkstubs solo se usa cuando está construyendo un complemento sdk (de proveedor), no cuando simplemente construye el sdk normal. Sin embargo, mkstubs hace lo mismo que DroidDoc, excepto que no usa @hideanotaciones, "simplemente" usa un .defsarchivo que describe qué paquetes / clases / campos se incluirán en la API del complemento.
Bjarke Freund-Hansen
2
@ThomasHofmann: Acerca de $(hide), te estás confundiendo. $(hide)es simplemente un prefijo en los archivos MAKE para ocultar la línea de comandos real del programa que se está ejecutando, nada más, y se usa en casi todas partes. No tiene nada que ver con el SDK de Android o la @hideanotación en el código fuente.
Bjarke Freund-Hansen
¿Cómo puedo verificar esta ruta anterior? / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
31

Podríamos reconstruir los archivos * .jar desde la plataforma Android.

Primero, conecte ADB a su dispositivo. Entonces corre:

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

El core.jarcontienen las bibliotecas estándar de Java ( java.*) y la framework.jarcontienen las bibliotecas Android ( android.*). Esto aún no se puede utilizar, ya que los archivos reales están en formato DEX, no en formato JAR.

Podríamos convertir estos archivos * .jar con formato DEX en archivos JAR reales utilizando herramientas como dex2jar :

dex2jar core.jar
dex2jar framework.jar

Luego, extraiga estos frascos con "Agregar archivos JAR externos ..." (suponiendo que esté usando Eclipse ADT)

  • haga clic derecho en Project → Properties → Java Build Path → Libraries → Add External JARs... → (Elija core-dex2jar.jary framework-dex2jar.jardesde arriba).

Esto le permitirá utilizar la API interna y algunas API de Java 7. (El APK generado, por lo que puedo ver, no contiene ningún código real de los JAR).

Kennytm
fuente
Muchas gracias, he probado muchas formas en las que solo tus métodos funcionan para mí.
SalutonMondo
7
Es importante tener en cuenta que este método todavía funciona con ICS y sistemas posteriores, pero requiere más malabarismos. Los archivos son relevantes /system/framework/core.odex, /system/framework/framework.odexy probablemente más. Estos pueden ser deodexados ( java -jar baksmali-2.0.3.jar -d system.framework -x system.framework/core.odex -o core) y reodexados ( java -jar smali-2.0.3.jar -x -o core.dex core), y solo después de eso dex2jar core.dexhace su trabajo.
Alex Cohn
no se puede encontrar core.jar en marshmallow
mehmet6parmak
¿tienes alguna idea para core & framework jar en android p?
Prabhakaran
¿Cómo puedo verificar esta ruta anterior? / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
17

Para Lollipop, el flujo es un poco diferente:

  1. Obtenga /system/framework/arm/boot.oat desde el dispositivo lollipop

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

  3. Obtendrá dos carpetas: dex y odex. Vaya a dex y haga 'java -jar dex2jar.jar framework.dex'
  4. Cambie el nombre del framework.jar resultante a .zip, extraiga y busque las clases que necesita
  5. Vaya a [sdk_path] / platform / [target_platform] y extraiga android.jar (primero cámbiele el nombre a zip).
  6. Copie los archivos del marco extraído al android.jar extraído. Luego comprime a zip y cambia el nombre a .jar :)

ps: probablemente necesite repetir los pasos 4-6 para 'framework_classes2.dex'

desviado
fuente
Para el paso 3, no puedo encontrar el dex2jar.jar en ese enlace ... He intentado muchas cosas y no puedo resolverlo. ¿Hay un vínculo a eso en alguna parte? ¿Está ubicado en mi SDK de Android? No lo encuentro.
Dwebtron
Sí, va a un proyecto de github, y tal vez soy yo, pero no puedo encontrar NINGÚN archivo que termine en ".jar" allí ...
Dwebtron
1
ver sección 'lanzamientos'
desviado
2
Así que parece que las versiones recientes de dex2jar han cambiado el formato de descarga. Simplemente descomprima la descarga y en lugar de 'java -jar ...' simplemente ejecute el script 'd2j-dex2jar.sh' o 'd2j-dex2jar.bat', dependiendo de su plataforma, directamente en el archivo framework.dex
CalumMcCall
1
He copiado ambos archivos jar en android.jar, ahora el estudio de Android me dice Error: Error de ejecución para la tarea ': app: processDebugResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Proceso 'comando' D: \ Program \ Android \ android-sdk \ build-tools \ 19.1.0 \ aapt.exe ' 'terminó con un valor de salida 1 distinto de cero
wutzebaer
16

Puede descargar la versión modificada android.jarpara usarla como API oculta desde este repositorio . Siga las instrucciones allí.

Anggrayudi H
fuente
4
Esta respuesta debería recibir más votos, ya que es la solución más simple. Gente, si está buscando una solución, sepa que otras personas ya lo hicieron y colocaron una solución en ese repositorio de github. ¡Úsalo y disfruta! ))
Mixaz
1
Mientras uso android.jar para API 28, recibo un error con robolectric. Se planteó un problema github.com/anggrayudi/android-hidden-api/issues/62 y gracias por su jar @Anggrayudi
Prabhakaran
También hice lo mismo para Android 10, no funciona para mí, sino que lo descargué de otro colaborador github.com/aeab13/android-jar-with-hidden-api . pude acceder a la clase hdmi-cec y compilarla, pero los códigos siguen siendo confusos .code link android.googlesource.com/platform/frameworks/base/+/4e90fcd/…
babbin tandukar hace
15

DroidCon 2011

Aquí Erik Hellman de Sony Ericson explica cómo acceder a las API ocultas de Android:

http://vimeo.com/30180393 (Hmm, el enlace no parece funcionar).

Ir a la Droidcon página web Día 2 abajo desplazarse a Utilización de las API Ocultos 10:15 y se puede ver allí.

¡Los enlaces están muriendo!

Encontré este: http://skillsmatter.com/podcast/os-mobile-server/hidden-api no sé cuánto tiempo estará activo

Las API oficiales del SDK de Android suelen ser suficientes para la mayoría de las aplicaciones normales. Sin embargo, a veces hay situaciones en las que un desarrollador necesita acceder a los servicios, API y recursos del sistema interno que no están publicados en las API oficiales. Afortunadamente, estas API todavía están disponibles a través de algunos trucos inteligentes y, a menudo, pueden ser útiles al desarrollar una solución nueva e innovadora sobre Android. En esta sesión, aprenderá cómo acceder y utilizar estas API ocultas y protegidas, las limitaciones de su uso y algunos trucos y consejos sobre cómo utilizarlas de forma segura y controlada en varios dispositivos de proveedores y versiones de Android. La audiencia verá varias demostraciones avanzadas que normalmente no puede hacer con Android. Espere una sesión bastante avanzada con muchos conocimientos sobre los aspectos internos de la plataforma Android.

Blundell
fuente
1
Es interesante, pero lamentablemente no responde a mi pregunta. Estaba pidiendo una forma de reconstruir realmente el SDK con cosas ocultas incluidas.
Thomas Hofmann
Parece que encontré otra forma de lograr lo que quiero. Lo describiré mañana.
Thomas Hofmann
Descubrí que si desea compilar la fuente de un proyecto que usa API oculta en ADT, puede hacer lo siguiente: 1) Crear un proyecto de Android para la fuente. 2) Elimine el contenedor de la ruta de clases de Android de la ruta de compilación 3) Defina una biblioteca de usuario (también marque la casilla de verificación de la biblioteca del sistema) que incluya archivos JAR de una compilación de ROM ASOP, por ejemplo, cm7). Los archivos JAR que use dependen de lo que necesite hacer referencia. framework-inmediates probablemente será parte de él.
Thomas Hofmann
4) Cuando el proyecto esté ahora construido, las clases de la biblioteca de usuario no se incluirán en el APK que se está creando. La API oculta es visible y todo se compilará bien.
Thomas Hofmann
@Blundell: ¿Pueden actualizar los enlaces? ¡Están muertos!
zombi
12

Intenta mirar esto :

El objetivo final de estos artículos es brindar a los desarrolladores el poder de las API internas y ocultas sin usar la reflexión. Si completa todos los pasos descritos en las siguientes partes, podrá utilizar las API internas y ocultas como si fueran API públicas abiertas. No habrá necesidad de reflexionar.

Pero si está utilizando estas API no públicas, debe tener en cuenta que su aplicación corre un gran riesgo. Básicamente, no hay garantías de que las API no se rompan con la próxima actualización del sistema operativo Android. Incluso no hay garantías sobre un comportamiento consistente en dispositivos de diferentes proveedores. Estás completamente por tu cuenta.

Hay tres escenarios que puede querer seguir:

  1. Habilite las API internas y ocultas (escenario A)
  2. Habilite solo API oculta (escenario B)
  3. Habilitar solo API interna (escenario C)

El escenario A es una suma de B y C. El escenario B es el más fácil (no requiere modificaciones en el complemento ADT de eclipse).

Escenario A : lea las partes 1 , 2 , 3 , 4 , 5

Escenario B : lea las partes 1 , 2 , 3 , 5

Escenario C : lea las partes 1 , 2 , 3 , 4 , 5

Zorb
fuente
3
Ya leí esa entrada de blog. Menciona esto: "1) Android es un proyecto de código abierto. Podemos descargar el código fuente y personalizar el sistema de compilación para que no excluya las clases internas y ocultas de android.jar. Esta es una manera difícil". Desafortunadamente, no entra en detalles.
Thomas Hofmann
3
Vaya a la última parte de la publicación del blog ( devmaze.wordpress.com/2011/01/19/… ), hay un enlace ( github.com/inazaruk/android-sdk/tree/master/platforms ) para Android preconstruido API con todas las API internas y ocultas.
Bob
1
Los enlaces dados no son accesibles, requieren permiso del autor
SHAHS
¿Cómo puedo verificar esta ruta anterior? / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
1

Una vez escribí algunos scripts Groovy para extraer los archivos java de un pago de repositorio de http://source.android.com/ y luego compilarlos sin la necesidad de una cadena de herramientas completa para compilar todas las fuentes de Android, incluidos los otros pasos necesarios ( embalaje, generación de recursos, etc.).

Pueden ser encontrados aquí:

https://github.com/thoutbeckers/CollectAndroid

Pero seguro que será necesario actualizarlo para cualquier cosa posterior a Gingerbread, principalmente configurando los directorios correctos en "rootdirs" en el archivo de configuración (CollectConfig.groovy).

En ese momento, usé esto regularmente para el desarrollo con todas las API y fuentes ocultas (también problemáticas en ese momento) disponibles.

Como se mencionó en otra parte, com / android / internal / ** todavía estará oculto en las versiones recientes de ADT debido a la regla de acceso agregada.

thoutbeckers
fuente
¿Cómo puedo verificar esta ruta anterior? / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
Archivé ese repositorio desde que se actualizó por última vez para Gingerbread . Desafortunadamente, tendrás que encontrar otro enfoque.
thoutbeckers
1

La respuesta de Long funcionó para mí, pero todavía me faltaban algunas clases que necesitaba, en particular android.provider.Telephony. Pude agregarlo así:

  1. Extraiga el archivo framework.jar

    mkdir /tmp/framework
    cp framework.jar /tmp
    cd /tmp/framework
    jar xvf ../framework.jar
    mv android classes
    
  2. Construya el repositorio de Android, que creará el directorio out / target / common / obj / JAVA_LIBRARIES

  3. Encuentra dónde están las clases que faltan

    $ 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. Agregue las nuevas clases y reconstruya el archivo JAR del marco

    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 .
    

O simplemente puede ser perezoso e incluir todas las clases en un archivo jar gigante:

cd /tmp/framework
cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/*/classes .
cd classes
jar cvf ../framework.jar .
bmaupin
fuente
out / target / common / obj / JAVA_LIBRARIES ¿cómo encontrar esta ruta?
Bunny
@Bunny He actualizado mi respuesta con más detalles. Pero parece que la respuesta aquí podría ser más fácil: stackoverflow.com/a/32626155/399105
bmaupin
gracias por su respuesta @bmaupin ... ¿puede ayudarme a encontrar esta ruta / target / common / obj / JAVA_LIBRARIES para obtener framework jar ... realmente me quedé atascado ... no puedo encontrar esta ruta o falta algo ... por favor guía
Bunny
0

No puedo comentar, pero esto es básicamente un comentario para la excelente respuesta de @ KennyTM ( https://stackoverflow.com/a/13550030/2923406 ):

Si se encuentra con el siguiente error en Eclipse:

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

(es decir, android.internal. * no está disponible)

Entonces, una posible solución es aplicar el mismo método para /system/framework/framework2.jar. Usando el emulador de Android para SDK19 tengo este frasco adicional. En mi HTC One hay incluso un framework3.jar.

Rolf
fuente
¿Cómo puedo verificar esta ruta anterior? / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny