如何使用可用的隐藏API和内部API构建Android SDK?


85

我想重建Android SDK(或更确切地说,仅是android.jar)以包括隐藏的和内部的API。

我找不到有关如何执行此操作的任何文档或讨论。我已经安装了一个能够构建cm7的Ubuntu CyanogenMod构建环境。

现在,我读到make SDK将构建SDK,但我想构建一个SDK,其中包含使用@hide标记为隐藏的方法和字段。这可能吗?

我想要做的是对使用隐藏API的应用程序进行更改,为了重建它,我想使用修改后的SDK。


2
@Hidden只是隐藏了Javadoc,所有这些方法仍然可用
Blundell

12
@hide将它们从类文件中删除。
Thomas Hofmann


我知道我可以使用反射,但是我想更改一个使用隐藏API而不使用反射的现有应用程序,并且我不想更改所有现有代码以使用反射。
Thomas Hofmann

4
我认为您可以删除@Hidden要访问的API的标签,然后执行make update-apimake SDK构建自己的SDK。
dreamtale'3

Answers:


68

这就是我始终使用隐藏api所做的事情。

  1. 构建仓库或从https://sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong下载jar
  2. 复制出/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar(最好将其重命名为framework_all.jar之类)
  3. 配置项目的构建路径->库->添加此外部jar。在“订单和导出”中,将其向上移动并移至android.jar之前

这也对我有用!现在我可以继续实际的任务了,谢谢
CurlyPaul 2013年

恕我直言,这是最简单,最快的。
Patrick Cho 2014年

没有办法将其标记为正确答案吗?
克里斯·布罗瓦

2
此方法适用于所有设备,还是仅适用于目标设备?
海防

要在android studio中定义库顺序,您需要更改模块的.iml文件,并将所需的lib放在Android SDK<orderEntry>之前。不幸的是,该技术不是持久性的,因为一旦按下gradle-sync按钮,文件将被覆盖。
waqaslam

44

我已经对此进行了一些调查,而我的结论很简单:没有大量工作就无法完成。阅读此答案的其余部分,以详细了解我所发现的内容。


android.jar实际上由“公共API”的framework.jarcore.jar,其在被发现system/frameworks/的设备上。android.jar我称之为Java库标头,实际字节码中的所有实现都只是一个throw new RuntimeException("stub");,这使您可以针对它android.jar(例如在Eclipse中)进行构建,但是必须在设备或仿真器上执行。

Android SDK的公共API由@{hide}javadoc注释为前缀的类/方法/字段定义。也就是说,所有注释的内容都包含在SDK中。

android.jar从位于源中内置out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates本身由工具生成DroidDoc位于build/tools/droiddoc

DroidDoc是用于生成实际Android SDK文档的工具(可能是从javadoc改编而成,或使用javadoc编写的)。作为副作用,可能是因为它已经解析了所有javadoc,所以它还会喷出android存根,然后将android.jar其编译为在SDK中分发的。

因此,要包含隐藏的内容,如果只想包含特定部分,则可以删除@hide注释并重新构建SDK。

但是,如果要包括所有隐藏部分,事情会变得复杂得多。您可以修改DroidDoc(相关的源代码位于中build/tools/droiddoc/src/Stubs.java),以使没有任何东西被检测为隐藏。这非常琐碎,我已经尝试过了,但是随后生成的存根根本无法编译。

我现在的结论是,这根本不可行。如果删除DroidDoc中检测隐藏注释的部分,则生成的存根根本无法编译,并且需要大量工作才能正确编译。

因此,我对您的问题的回答是:不,如果不做很多工作就无法完成。抱歉。


有关该mkstubs工具的旁注。mkstubs在构建SDK插件时使用,即您可以在Android SDK管理器中从供应商处找到的插件,例如Samsung为您提供了针对Samsung手机特定内容的附加API。mkstubs与DroidDoc存根生成过程大致相同,但是它不使用@hide注释,它使用一个.defs文件来描述要从SDK插件中包含或排除哪些程序包/类/字段。

然而,这一切无关的问题,如在Android SDK构建并不能使用该mkstubs工具。(不幸。)


我也看了 除了Droiddoc,/ development / tools / mkstubs中还有一个称为mkstubs的工具。它在构建过程中被调用,据我所知它将修改类文件中的内容。在build / core / tasks / sdk-addon.mk中,有以下代码:define stub-addon-jar $(call stub-addon-jar-file,$(1)):$(1)| mkstubs $(信息使用$(PRODUCT_SDK_ADDON_STUB_DEFS)附加插件jar)$(隐藏)java -jar $(调用模块安装文件,mkstubs)$(如果$(隐藏),,-v)\“ $$ <” “ $$ @” @ $(PRODUCT_SDK_ADDON_STUB_DEFS)endef
Thomas Hofmann

不幸的是,我不喜欢这些东西,但我也似乎都依赖于名为hide的变量。我没有发现它被设置了。如果在其他构建文件中搜索$(hide),您会发现很大程度上取决于此值。这似乎也影响到C库的构建方式。
Thomas Hofmann 2012年

@ThomasHofmann:我最初也对mkstubs工具感到困惑。我了解到,只有在构建(供应商)sdk插件时才使用mkstubs,而不是在构建普通的sdk时才使用。但是,mkstubs与DroidDoc几乎相同,除了它不使用@hide注释,它“只是”使用一个.defs文件来描述插件的API中将包含哪些包/类/字段。
Bjarke Freund-Hansen'3

2
@ThomasHofmann:关于$(hide),您感到困惑。$(hide)只是makefile中的前缀,以隐藏正在执行的程序的实际命令行,仅此而已,并且它几乎在任何地方都可以使用。它与Android SDK或@hide源代码中的注释无关。
Bjarke Freund-Hansen'3

我如何才能在上面的路径中检查出这一点out / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
兔子

31

我们可以从Android平台重建* .jar文件。

首先,将ADB连接到您的设备。然后运行:

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

core.jar包含标准的Java库(java.*)和framework.jar包含了Android库(android.*)。由于实际文件是DEX格式,而不是JAR格式,因此尚不可用。

我们可以使用诸如dex2jar之类的工具将这些DEX格式的* .jars转换为真实的JAR :

dex2jar core.jar
dex2jar framework.jar

然后使用“添加外部JAR ...”拉入这些jar(假设您正在使用Eclipse ADT)

  • 右键单击Project → Properties → Java Build Path → Libraries → Add External JARs...→(从上方选择core-dex2jar.jarframework-dex2jar.jar)。

这将使您能够使用内部和某些Java 7 API。(据我所知,生成的APK不包含JAR中的任何实际代码。)


非常感谢,我尝试了很多方法,只有您的方法对我有用。
SalutonMondo 2014年

7
重要的是要注意,此方法仍适用于ICS和更高版本的系统,但需要更多操作。相关文件是/system/framework/core.odex,,/system/framework/framework.odex可能还有更多。可以对它们进行脱氧(java -jar baksmali-2.0.3.jar -d system.framework -x system.framework/core.odex -o core)和脱氧((java -jar smali-2.0.3.jar -x -o core.dex core))操作,然后再进行dex2jar core.dex工作。
Alex Cohn 2014年

无法在棉花糖中找到core.jar
mehmet6parmak

您对android p中的core和framework jar有什么想法吗?
Prabhakaran

我如何才能在上面的路径中检查出这一点out / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
兔子

17

对于棒棒糖,流程几乎没有什么不同:

  1. 从棒棒糖设备获取/system/framework/arm/boot.oat

  2. 使用'java -jar oat2dex.jar boot boot.oat'

  3. 您将获得两个文件夹:dex和odex。转到dex并制作'java -jar dex2jar.jar framework.dex”
  4. 将生成的framework.jar重命名为.zip,提取并查找所需的类
  5. 转到[sdk_path] / platforms / [target_platform]并解压缩android.jar(首先将其重命名为zip)。
  6. 将文件从提取的框架复制到提取的android.jar。然后压缩为zip并重命名为.jar :)

ps:可能您需要为“ framework_classes2.dex”重复步骤4-6


对于第3步,我在该链接中找不到dex2jar.jar...。我尝试了很多事情,但无法弄清楚。在某处有链接吗?它位于我的Android SDK中吗?我找不到
Dwebtron

是的,它去了一个github项目,也许是我,但是我在那里找不到任何以“ .jar”结尾的文件...
Dwebtron 2015年

1
参见“发布”部分
2015年

2
因此,看来dex2jar的最新版本已更改了下载格式。只需解压缩下载文件即可,而不是'java -jar ...'而是直接在framework.dex文件上运行脚本'd2j-dex2jar.sh'或'd2j-dex2jar.bat',具体取决于您的平台
CalumMcCall

1
我已经将两个jar文件都复制到了android.jar中,现在android studio告诉我错误:任务':app:processDebugResources'的执行失败。> com.android.ide.common.process.ProcessException:org.gradle.process.internal.ExecException:处理'命令'D:\ Programme \ Android \ android-sdk \ build-tools \ 19.1.0 \ aapt.exe' '以非零退出值1结束
wutzebaer

15

DroidCon 2011

索尼爱立信的Erik Hellman在这里说明了如何访问隐藏的Android API:

http://vimeo.com/30180393(Hmm 链接似乎不起作用)。

转到DroidCon网页的第2天,向下滚动到Using Hidden APIs 10:15,您可以在那里观看。

链接消失了!

我找到了这个:http : //skillsmatter.com/podcast/os-mobile-server/hidden-api dunno它将持续多长时间

Android SDK中的官方API通常对于大多数普通应用程序就足够了。但是,有时在某些情况下,开发人员需要访问未在官方API中发布的内部系统服务,API和资源。幸运的是,这些API仍可以通过一些巧妙的技巧获得,并且在基于Android的基础上开发新的创新解决方案时通常非常有用。在本课程中,您将学习如何访问和使用这些隐藏和受保护的API,它们的使用限制以及如何在多个供应商的设备和Android版本之间以安全和可控制的方式使用它们的一些技巧。观众将看到几个通常无法使用Android进行的高级演示。期待一个相当高级的会议,其中包含有关Android平台内部知识的大量见解。


1
这很有趣,但不幸的是它没有回答我的问题。我在寻找一种方法来实际重建包含隐藏内容的SDK。
托马斯·霍夫曼

看来我找到了实现所需目标的另一种方法。我明天再描述。
托马斯·霍夫曼

我发现,如果要编译在ADT中使用隐藏API的项目的源代码,则可以执行以下操作:1)为源代码创建一个Android项目。2)从构建路径中删除Android classpath容器。3)定义一个用户库(也请选中系统库复选框),其中包括来自ASOP ROM构建的JAR文件,例如cm7。您使用哪种JAR文件取决于您需要参考的内容。框架直接对象可能是其中的一部分。
Thomas Hofmann

4)现在构建项目时,用户库类将不包含在正在创建的APK中。隐藏的API是可见的,一切都可以正常编译。
Thomas Hofmann

@Blundell:能否请您更新链接..它们已经死了!
僵尸2012年

15

您可以android.jar从此存储库下载修改后的用作隐藏API 。按照那里的说明进行操作。


4
由于这是最简单的解决方案,因此应该更多地支持该答案。人们,如果您正在寻找解决方案,请知道其他人已经做到了,并为该github存储库提供了解决方案。使用它并享受!))
Mixaz '16

1
将android.jar用于API 28时,robolectric出现错误。提出了一个问题github.com/anggrayudi/android-hidden-api/issues/62并感谢您的jar @Anggrayudi
Prabhakaran

12

尝试看看这个

这些文章的最终目标是在不使用反射的情况下为开发人员提供内部和隐藏API的功能。如果您完成了以下几部分中描述的所有步骤,您将能够使用内部隐藏API,就像它们是公共开放API一样。无需反思。

但是,如果您使用的是这些非公共API,则应意识到您的应用程序存在很大的风险。基本上,我们无法保证在下次更新Android OS时不会破坏API。甚至不能保证来自不同供应商的设备之间的行为一致。您完全是一个人。

您可能要遵循三种情况:

  1. 启用内部隐藏API(方案A)
  2. 仅启用隐藏的API(方案B)
  3. 仅启用 内部API(方案C)

方案A是B和C的总和。方案B是最简单的方案(不需要修改Eclipse ADT插件)。

方案A:读取部件12345

方案B:读取部件123 5

方案C:读取部件12345


3
我已经读过该博客条目。它提到:“ 1)Android是一个开放源代码项目。我们可以下载源代码并定制构建系统,因此它不会从android.jar中排除内部和隐藏类。这是一种很难的方法。” 不幸的是,它没有详细介绍。
Thomas Hofmann

3
转到博客文章的最后部分(devmaze.wordpress.com/2011/01/19/…),有一个指向预建Android的链接(github.com/inazaruk/android-sdk/tree/master/platforms)具有所有隐藏和内部API的API。
鲍勃

1
给定的链接不可访问,需要作者的许可
SHAHS

我如何才能在上面的路径中检查出这一点out / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
兔子

1

我曾经写过一些Groovy脚本,用于从http://source.android.com/的回购结帐中提取Java文件,然后进行编译,而无需使用完整的工具链来编译所有android源代码,包括所需的其他步骤(包装,产生资源等)。

它们可以在这里找到:

https://github.com/thoutbeckers/CollectAndroid

但是可以肯定这需要在Gingerbread之后进行任何更新,主要是通过在配置文件(CollectConfig.groovy)的“ rootdirs”中设置正确的目录。

当时,我经常使用它进行开发,并提供所有隐藏的API和源(当时也有问题)。

如其他地方所述,由于访问规则的加入,com / android / internal / **仍会在ADT的最新版本中隐藏。


我如何在上面的路径中检查出这一点out / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
兔子

自从上次为Gingerbread更新该存储库以来,我就对其进行了归档。您将不得不不幸地找到另一种方法。
thoutbeckers

1

Long的答案对我有用,但是我仍然缺少一些我需要的类,特别是android.provider.Telephony。我能够像这样添加它:

  1. 提取framework.jar文件

    mkdir /tmp/framework
    cp framework.jar /tmp
    cd /tmp/framework
    jar xvf ../framework.jar
    mv android classes
    
  2. 构建Android存储库,这将创建out / target / common / obj / JAVA_LIBRARIES目录

  3. 查找丢失的类在哪里

    $ 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. 添加新类并重建框架JAR文件

    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 .
    

或者,您可以懒惰,将所有类都包含在一个巨大的jar文件中:

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

out / target / common / obj / JAVA_LIBRARIES如何找到此路径?
兔子

@Bunny我更新了更多详细信息。但似乎这里的答案可能更容易:stackoverflow.com/a/32626155/399105
bmaupin

感谢您的回复@bmaupin ..能否请您帮助我如何找到此路径/ target / common / obj / JAVA_LIBRARIES以获取框架jar ...我真的被卡住了。我无法找到此路径或遗失了一些东西...请引导
兔子

0

我无法发表评论,但这基本上是对@KennyTM的评论(https://stackoverflow.com/a/13550030/2923406)的出色:

如果您在Eclipse中发现以下错误:

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

(即android.internal。*不可用)

然后一种可能的解决方案是对/system/framework/framework2.jar应用相同的方法。使用适用于SDK19的Android模拟器,我有这个额外的jar。在我的HTC One上甚至有一个framework3.jar。


我如何在上面的路径中检查出这一点out / target / common / obj / JAVA_LIBRARIES / framework_intermediates / classes.jar
兔子
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.