Como faço para construir o Android SDK com APIs ocultas e internas disponíveis?

86

Quero reconstruir o Android SDK (ou melhor, apenas o android.jar) para incluir APIs ocultas e internas.

Não consegui encontrar nenhuma documentação ou discussão sobre como fazer isso. Eu tenho um ambiente de construção Ubuntu CyanogenMod já configurado que é capaz de construir cm7.

Agora, eu li que make SDK irá construir o SDK, mas eu quero construir um SDK que inclui métodos e campos que são marcados como ocultos usando @hide. Isso é possível?

O que eu quero fazer é fazer alterações em um aplicativo que usa API oculta e, para reconstruí-lo, gostaria de usar o SDK modificado.

Thomas Hofmann
fonte
2
@Hidden apenas esconde o javadoc, todos esses métodos ainda estão disponíveis
Blundell
12
@hide os remove dos arquivos de classe.
Thomas Hofmann,
Eu sei que poderia usar reflexão, mas quero alterar um aplicativo existente que usa API oculta sem refelction e não quero alterar todo o código existente para usar refelction.
Thomas Hofmann,
4
Acho que você pode remover o @Hiddenrótulo da API que deseja acessar e, em seguida, executar make update-apie make SDKconstruir seu próprio SDK.
dreamtale,

Respostas:

69

Isso é o que sempre faço para usar a API oculta.

  1. Crie o repo ou baixe os jars em https://sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong
  2. copie / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar (melhor renomear como algo como framework_all.jar)
  3. configure o caminho de construção do seu projeto -> bibliotecas -> adicione estes jars externos. Em Order and Export, mova-o para cima e antes de android.jar
Grandes
fonte
Isso funcionou para mim também! agora posso continuar com a tarefa real, obrigado por isso
CurlyPaul
IMHO, este é o mais fácil e o mais rápido.
Patrick Cho
Não há uma maneira de marcar isso como a resposta adequada?
Chris Browet
2
este método funciona com todos os dispositivos ou funciona apenas com o dispositivo de destino?
Hải Phong
Para definir a ordem da biblioteca no android studio, você precisa alterar o .imlarquivo do módulo e trazer suas bibliotecas desejadas <orderEntry>antes do Android SDK . Infelizmente, essa técnica não é persistente, pois o arquivo será sobrescrito assim que o botão gradle-sync for pressionado.
waqaslam de
44

Eu fiz algumas investigações sobre isso e minha conclusão é simples: isso não pode ser feito sem um pouco de trabalho. Leia o restante desta resposta para obter detalhes sobre o que descobri.


android.jaré, na verdade, composto pela "API pública" de framework.jare core.jarque é encontrada no system/frameworks/dispositivo. android.jaré um tipo do que eu chamaria de cabeçalho da biblioteca Java, todas as implementações no código de bytes real são apenas um throw new RuntimeException("stub");, isso permite que você construa android.jar(por exemplo, no Eclipse), mas a execução deve ser realizada em um dispositivo ou emulador.

A API pública do Android SDK é definida por classes / métodos / campos que não são prefixados com a @{hide}anotação javadoc. Ou seja, tudo o que não é anotado está incluído no SDK.

android.jaré construído a partir de fontes localizadas nas out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediatesquais ele próprio é gerado pela ferramenta DroidDoc localizada em build/tools/droiddoc.

DroidDoc é a ferramenta (provavelmente adaptada do javadoc ou usando o javadoc) que gera a documentação real do Android SDK. Como efeito colateral, e provavelmente porque já está analisando todo o javadoc, ele também expele os stubs do Android que são compilados no android.jarque é distribuído no SDK.

Portanto, para incluir o que está oculto, você pode, se quiser incluir apenas partes específicas, apenas remover a @hideanotação e reconstruir o SDK.

No entanto, se você quiser incluir todas as partes ocultas, as coisas ficam muito mais complicadas. Você pode modificar o DroidDoc (a fonte relevante está em build/tools/droiddoc/src/Stubs.java) de forma que nada seja detectado como oculto. Isso é bastante trivial e eu tentei fazer isso, no entanto, os stubs que são gerados não compilam de todo.

Minha conclusão agora é que isso simplesmente não é viável. Os stubs gerados se você remover a parte do DroidDoc que detecta anotações ocultas, simplesmente não é compilável e exigiria um pouco de trabalho para compilar corretamente.

Portanto, minha resposta às suas perguntas é: Não, isso não pode ser feito sem muito trabalho. Desculpa.


Uma observação lateral sobre a mkstubsferramenta. mkstubssão usados ​​quando você constrói um complemento SDK , ou seja, os complementos que você pode encontrar no gerenciador do Android SDK de fornecedores, por exemplo, a Samsung fornecendo a você uma API adicional para coisas específicas para telefones Samsung. mkstubsfaz quase o mesmo que o processo de geração de stubs do DroidDoc; no entanto, não usa @hideanotações, ele usa um .defsarquivo que descreve quais pacotes / classes / campos incluir ou excluir do seu complemento SDK.

No entanto, tudo isso é irrelevante para a questão, já que o Android SDK build não usa a mkstubsferramenta. (Infelizmente.)

Bjarke Freund-Hansen
fonte
Eu também dei uma olhada. Além do Droiddoc, existe uma ferramenta chamada mkstubs em / development / tools / mkstubs. Ele é chamado durante a construção e, pelo que vi, ele modificará os arquivos de classe, retirando coisas deles. Em build / core / tasks / sdk-addon.mk existe o seguinte código: define stub-addon-jar $ (chame stub-addon-jar-file, $ (1)): $ (1) | mkstubs $ (info Stubbing addon jar usando $ (PRODUCT_SDK_ADDON_STUB_DEFS)) $ (ocultar) java -jar $ (chamar o módulo de arquivos instalados, mkstubs) $ (if $ (ocultar) ,, - v) \ "$$ <" "$$ @" @ $ (PRODUCT_SDK_ADDON_STUB_DEFS) endef
Thomas Hofmann
Infelizmente, eu não gosto dessas coisas, mas também parece que tudo depende de uma variável chamada hide. Eu não encontrei onde é definido. Se você pesquisar por $ (ocultar) nos outros arquivos de construção, verá que muito depende desse valor. Parece também afetar a maneira como os C libs são construídos.
Thomas Hofmann
@ThomasHofmann: Inicialmente, fiquei confuso com a ferramenta mkstubs também. O que aprendi é que mkstubs só é usado quando você está construindo um complemento SDK (do fornecedor), não quando você apenas constrói o SDK normal. No entanto, mkstubs faz quase o mesmo que DroidDoc, exceto que não usa @hideanotações, ele "apenas" usa um .defsarquivo que descreve quais pacotes / classes / campos devem ser incluídos na API do complemento.
Bjarke Freund-Hansen
2
@ThomasHofmann: Sobre $(hide), você está se confundindo. $(hide)é simplesmente um prefixo nos makefiles para ocultar a linha de comando real do programa sendo executado, nada mais, e é usado em quase todos os lugares. Não tem nada a ver com o Android SDK ou a @hideanotação no código-fonte.
Bjarke Freund-Hansen
como posso verificar este caminho acima / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
31

Podemos reconstruir os arquivos * .jar da plataforma Android.

Primeiro, conecte o ADB ao seu dispositivo. Então corra:

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

O core.jarcontém as bibliotecas Java padrão ( java.*) e framework.jarcontém as bibliotecas do Android ( android.*). Isso ainda não pode ser usado, pois os arquivos reais estão no formato DEX, não no formato JAR.

Poderíamos converter esses * .jars formatados em DEX em JARs reais usando ferramentas como dex2jar :

dex2jar core.jar
dex2jar framework.jar

Em seguida, coloque esses jars usando "Adicionar JARs externos ..." (presumindo que você esteja usando Eclipse ADT)

  • clique com o botão direito em Project → Properties → Java Build Path → Libraries → Add External JARs... → (Escolha core-dex2jar.jare framework-dex2jar.jaracima).

Isso permitirá que você use as APIs internas e algumas APIs Java 7. (O APK gerado, pelo que posso ver, não contém nenhum código real dos JARs.)

Kennytm
fonte
Muito obrigado, eu tentei muitas maneiras, apenas seus métodos funcionam para mim.
SalutonMondo
7
É importante observar que esse método ainda funciona com o ICS e sistemas posteriores, mas requer mais malabarismos. Os arquivos relevantes são /system/framework/core.odex, /system/framework/framework.odexe provavelmente mais. Eles podem ser desodexados ( java -jar baksmali-2.0.3.jar -d system.framework -x system.framework/core.odex -o core) e reodexados ( java -jar smali-2.0.3.jar -x -o core.dex core), e somente depois disso dex2jar core.dexfaz o seu trabalho.
Alex Cohn
incapaz de encontrar core.jar em marshmallow
mehmet6parmak
você tem alguma ideia para core & framework jar no android p?
Prabhakaran de
como posso verificar este caminho acima / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
18

Você pode baixar o modificado android.jarpara ser usado como APIs ocultas deste repositório . Siga as instruções aqui.

Anggrayudi H
fonte
4
Esta resposta deve ser votada mais a favor, pois é a solução mais simples. Gente, se você está procurando uma solução - saiba que outras pessoas já fizeram isso e colocaram uma solução para aquele repo do github. Use e divirta-se! ))
Mixaz
1
Ao usar android.jar para API 28, estou recebendo um erro com o robolectric. Levantou um problema github.com/anggrayudi/android-hidden-api/issues/62 e obrigado por seu jar @Anggrayudi
Prabhakaran
Eu também fiz o mesmo para o Android 10, ele não funciona para mim, em vez disso, fiz o download de outro contribuidor github.com/aeab13/android-jar-with-hidden-api . Consegui acessar a classe hdmi-cec e criá-la, mas os códigos ainda são confusos. link do código android.googlesource.com/platform/frameworks/base/+/4e90fcd/…
babbin tandukar
17

Para o Lollipop, o fluxo é um pouco diferente:

  1. Obtenha /system/framework/arm/boot.oat do dispositivo lollipop

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

  3. Você receberá duas pastas: dex e odex. Vá para dex e faça 'java -jar dex2jar.jar framework.dex'
  4. Renomeie framework.jar resultante para .zip, extraia e encontre as classes que você precisa
  5. Vá para [sdk_path] / plataformas / [target_platform] e extraia android.jar (primeiro renomeie-o para zip).
  6. Copie os arquivos da estrutura extraída para o android.jar extraído. Em seguida, comprima para compactar e renomeie para .jar :)

ps: provavelmente você precisa repetir os passos 4-6 para 'framework_classes2.dex'

divergente
fonte
Para a etapa 3, não consigo encontrar o dex2jar.jar nesse link .... Tentei várias coisas e não consigo descobrir. Existe um link para isso em algum lugar? Ele está localizado no meu Android SDK? Eu não consigo encontrar.
Dwebtron
Sim, vai para um projeto do github, e talvez seja eu, mas não consigo encontrar NENHUM arquivo terminando em ".jar" lá ...
Dwebtron
1
consulte a seção de 'lançamentos'
desviante
2
Portanto, parece que as versões recentes do dex2jar mudaram o formato do download. Basta descompactar o download e em vez de 'java -jar ...' apenas executar o script 'd2j-dex2jar.sh' ou 'd2j-dex2jar.bat', dependendo da sua plataforma, diretamente no arquivo framework.dex
CalumMcCall
1
Eu copiei os dois arquivos jar para o android.jar, agora o android studio me diz Erro: Falha na execução da tarefa ': 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 ' 'terminou com valor de saída diferente de zero 1
wutzebaer
15

DroidCon 2011

Aqui, Erik Hellman, da Sony Ericson, explica como acessar as APIs ocultas do Android:

http://vimeo.com/30180393 (Hmm, o link não parece funcionar).

Vá para a página da Web do DroidCon. Dia 2, role para baixo até Using Hidden APIs 10:15 e você pode assisti-lo lá.

Links estão morrendo!

Eu encontrei este: http://skillsmatter.com/podcast/os-mobile-server/hidden-api não sei quanto tempo vai ficar

As APIs oficiais no Android SDK geralmente são suficientes para a maioria dos aplicativos normais. No entanto, às vezes há situações em que um desenvolvedor precisa acessar os serviços internos do sistema, APIs e recursos que não são publicados nas APIs oficiais. Felizmente, essas APIs ainda estão disponíveis por meio de alguns truques inteligentes e muitas vezes podem ser úteis no desenvolvimento de soluções novas e inovadoras no Android. Nesta sessão, você aprenderá como acessar e usar essas APIs ocultas e protegidas, as limitações de seu uso e algumas dicas e truques sobre como usá-las de maneira segura e controlada em dispositivos de vários fornecedores e versões do Android. O público verá várias demonstrações avançadas que você normalmente não pode fazer com o Android. Espere uma sessão bastante avançada com muitos insights sobre as partes internas da plataforma Android.

Blundell
fonte
1
É interessante, mas infelizmente não responde à minha pergunta. Eu estava pedindo uma maneira de realmente reconstruir o SDK com coisas ocultas incluídas.
Thomas Hofmann,
Parece que encontrei outra maneira de conseguir o que desejo. Vou descrever isso amanhã.
Thomas Hofmann,
Descobri que se você deseja compilar o código-fonte de um projeto que usa API oculta no ADT, pode fazer o seguinte: 1) Criar um projeto Android para o código-fonte. 2) Remova o contêiner do classpath do Android do caminho de construção 3) Defina uma biblioteca de usuário (marque também a caixa de seleção da biblioteca do sistema) que inclui arquivos JAR de uma construção ASOP ROM, por exemplo, cm7). Os arquivos JAR usados ​​dependem do que você precisa fazer referência. o framework-imediates provavelmente fará parte dele.
Thomas Hofmann,
4) Quando o projeto for construído, as classes da biblioteca do usuário não serão incluídas no APK sendo criado. A API oculta está visível e tudo irá compilar perfeitamente.
Thomas Hofmann,
@Blundell: Você pode atualizar os links .. eles estão mortos!
zumbi de
12

Tente olhar para isto :

O objetivo final desses artigos é dar aos desenvolvedores o poder das APIs internas e ocultas sem usar reflexão. Se você concluir todas as etapas descritas nas próximas partes, poderá usar APIs internas e ocultas como se fossem APIs abertas ao público. Não haverá necessidade de reflexão.

Mas se você estiver usando essas APIs não públicas, deve estar ciente de que seu aplicativo corre um grande risco. Basicamente, não há garantias de que as APIs não serão quebradas com a próxima atualização do sistema operacional Android. Não há nem mesmo garantias sobre o comportamento consistente em dispositivos de diferentes fornecedores. Você está completamente sozinho.

Existem três cenários que você pode querer seguir:

  1. Habilite APIs internas e ocultas (cenário A)
  2. Habilite apenas API oculta (cenário B)
  3. Habilite apenas API interna (cenário C)

O cenário A é uma soma de B e C. O cenário B é o mais fácil (não requer modificações do plugin Eclipse ADT).

Cenário A : leia as partes 1 , 2 , 3 , 4 , 5

Cenário B : leia as partes 1 , 2 , 3 , 5

Cenário C : leia as partes 1 , 2 , 3 , 4 , 5

Zorb
fonte
3
Já li aquela entrada do blog. Ele menciona o seguinte: "1) O Android é um projeto de código aberto. Podemos baixar o código-fonte e personalizar o sistema de compilação para que não exclua classes internas e ocultas do android.jar. Este é um caminho difícil." Infelizmente, não entra em detalhes.
Thomas Hofmann de
3
Vá para a última parte da postagem do blog ( devmaze.wordpress.com/2011/01/19/… ), há um link ( github.com/inazaruk/android-sdk/tree/master/platforms ) para Android pré-construído APIs com todas as APIs ocultas e internas.
Bob,
1
Os links fornecidos não estão acessíveis, requerem permissão do autor
SHAHS
como posso verificar este caminho acima / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
1

Certa vez, escrevi alguns scripts do Groovy para extrair os arquivos java de uma verificação de repositório de http://source.android.com/ e, em seguida, compilá-los sem a necessidade de um conjunto de ferramentas completo para compilar todas as fontes do Android, incluindo as outras etapas necessárias ( embalagem, geração de recursos etc).

Eles podem ser achados aqui:

https://github.com/thoutbeckers/CollectAndroid

Mas com certeza isso precisará ser atualizado para qualquer coisa após o Gingerbread, principalmente definindo os diretórios corretos em "rootdirs" no arquivo de configuração (CollectConfig.groovy).

Na época, eu costumava usar isso regularmente para desenvolvimento com todas as APIs e fontes ocultas (também problemáticas na época) disponíveis.

Conforme mencionado em outro lugar, com / android / internal / ** ainda estará oculto nas versões recentes do ADT devido à regra de acesso anunciada.

thoutbeckers
fonte
como posso verificar este caminho acima / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny
Arquivei esse repositório desde que foi atualizado pela última vez para o Gingerbread . Você terá que encontrar outra abordagem, infelizmente.
thoutbeckers
1

A resposta de Long funcionou para mim, mas eu ainda estava perdendo algumas aulas de que precisava, em particular android.provider.Telephony. Consegui adicionar assim:

  1. Extraia o arquivo framework.jar

    mkdir /tmp/framework
    cp framework.jar /tmp
    cd /tmp/framework
    jar xvf ../framework.jar
    mv android classes
    
  2. Construir o repositório Android, que criará o diretório out / target / common / obj / JAVA_LIBRARIES

  3. Descubra onde estão as aulas que faltam

    $ 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. Adicione as novas classes e reconstrua o arquivo JAR da estrutura

    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 você pode ser preguiçoso e incluir todas as classes em um arquivo jar gigante:

cd /tmp/framework
cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/*/classes .
cd classes
jar cvf ../framework.jar .
bmaupin
fonte
out / target / common / obj / JAVA_LIBRARIES como encontrar este caminho?
Coelho
@Bunny Eu atualizei minha resposta com mais detalhes. Mas parece que a resposta aqui pode ser mais fácil: stackoverflow.com/a/32626155/399105
bmaupin
obrigado pela sua resposta @bmaupin .. você pode me ajudar como posso encontrar este caminho / target / common / obj / JAVA_LIBRARIES para obter o jar do framework ... eu realmente fiquei travado .. Não estou conseguindo encontrar este caminho ou faltando alguma coisa ... por favor, guie
Bunny
0

Não posso comentar, mas este é basicamente um comentário para a excelente resposta de @ KennyTM ( https://stackoverflow.com/a/13550030/2923406 ):

Se você encontrar o seguinte erro no Eclipse:

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

(ou seja, android.internal. * não está disponível)

Então, uma solução possível é aplicar o mesmo método para /system/framework/framework2.jar. Usando o emulador Android para SDK19, tenho este jar extra. No meu HTC One, existe até um framework3.jar.

Rolf
fonte
como posso verificar este caminho acima / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
Bunny