我想重建 Android SDK(或者更确切地说只有 android.jar)以包含隐藏和内部 API。
我找不到任何有关如何解决此问题的文档或讨论。我已经设置了一个能够构建 cm7 的 Ubuntu CyanogenMod 构建环境。
现在,我读到 make SDK 将构建 SDK,但我想构建一个 SDK,其中包含使用 @hide 标记为隐藏的方法和字段。这可能吗?
我想做的是对使用隐藏 API 的应用程序进行更改,为了重建它,我想使用修改后的 SDK。
我想重建 Android SDK(或者更确切地说只有 android.jar)以包含隐藏和内部 API。
我找不到任何有关如何解决此问题的文档或讨论。我已经设置了一个能够构建 cm7 的 Ubuntu CyanogenMod 构建环境。
现在,我读到 make SDK 将构建 SDK,但我想构建一个 SDK,其中包含使用 @hide 标记为隐藏的方法和字段。这可能吗?
我想做的是对使用隐藏 API 的应用程序进行更改,为了重建它,我想使用修改后的 SDK。
这就是我使用隐藏 api 时常做的事情。
我对此进行了一些调查,我的结论很简单:没有大量工作就无法做到这一点。阅读此答案的其余部分,了解我所发现的详细信息。
android.jar
实际上由设备上的“公共 api framework.jar
”core.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
其中的源构建而成,该源由位于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 管理器中找到的插件,例如三星为您提供特定于三星手机的附加 API。mkstubs
与 DroidDoc 存根生成过程大致相同,但是它不使用@hide
注释,它使用一个.defs
文件来描述要从您的 SDK 插件中包含或排除的包/类/字段。
然而,这与问题无关,因为 Android SDK 构建不使用该mkstubs
工具。(很遗憾。)
我们可以从 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 格式的 *.jar 转换为真正的 JAR :
dex2jar core.jar
dex2jar framework.jar
然后使用“Add External JARs ...”拉入这些 jars(假设您使用的是 Eclipse ADT)
Project → Properties → Java Build Path → Libraries → Add External JARs
... →(从上面选择core-dex2jar.jar
和framework-dex2jar.jar
)。这将使您能够使用内部和一些 Java 7 API。(据我所知,生成的 APK 不包含来自 JAR 的任何实际代码。)
您可以从该存储库android.jar
下载修改后的 API 以用作隐藏 API 。按照那里的说明进行操作。
对于 Lollipop,流程略有不同:
从棒棒糖设备获取 /system/framework/arm/boot.oat
使用'java -jar oat2dex.jar boot boot.oat'
ps:可能您需要对“framework_classes2.dex”重复步骤 4-6
在这里,来自索尼爱立信的 Erik Hellman 解释了如何访问隐藏的 Android API:
http://vimeo.com/30180393 (嗯链接似乎不起作用)。
转到DroidCon 网页 Day 2向下滚动到Using Hidden APIs 10:15,您可以在那里观看。
链接死了!
我找到了这个:http ://skillsmatter.com/podcast/os-mobile-server/hidden-api我不知道,它会持续多久。
Android SDK 中的官方 API 通常足以满足大多数普通应用程序的需求。但是,有时开发人员需要访问未在官方 API 中发布的内部系统服务、API 和资源。幸运的是,这些 API 仍然可以通过一些巧妙的技巧获得,并且在基于 Android 开发新的创新解决方案时通常很有用。在本课程中,您将了解如何访问和使用这些隐藏和受保护的 API、它们的使用限制以及一些关于如何在多个供应商设备和 Android 版本中以安全和可控的方式使用它们的技巧。观众将看到几个您通常无法使用 Android 进行的高级演示。期待一个相当高级的会议,其中包含很多关于 Android 平台内部的见解。
试着看看这个:
这些文章的最终目标是在不使用反射的情况下为开发人员提供内部和隐藏 API 的强大功能。如果您完成接下来几部分中描述的所有步骤,您将能够使用内部和隐藏API,就好像它们是公共开放 API 一样。将不需要反思。
但是,如果您使用这些非公共 API,那么您应该意识到您的应用程序存在很大风险。基本上,不能保证下次更新 Android 操作系统时 API 不会被破坏。甚至无法保证来自不同供应商的设备之间的一致行为。你完全靠自己。
您可能需要遵循三种方案:
- 启用内部和隐藏API(场景 A)
- 仅启用隐藏API(场景 B)
- 仅启用内部API(方案 C)
场景 A 是 B 和 C 的总和。场景 B 是最简单的一个(不需要修改 eclipse ADT 插件)。
我曾经写过一些 Groovy 脚本,用于从http://source.android.com/的 repo checkout 中提取 java 文件,然后编译它们而不需要完整的工具链来编译所有 android 源代码,包括所需的其他步骤(打包、生成资源等)。
它们可以在这里找到:
https://github.com/thoutbeckers/CollectAndroid
但可以肯定的是,这需要在 Gingerbread 之后更新任何内容,主要是通过在配置文件 (CollectConfig.groovy) 的“rootdirs”中设置正确的目录。
当时我经常使用它来开发所有隐藏的 API 和源(当时也有问题)可用。
正如其他地方提到的,由于添加了访问规则,com/android/internal/** 仍将隐藏在最新版本的 ADT 中。
Long 的回答对我有用,但我仍然缺少一些我需要的课程,特别是 android.provider.Telephony。我能够像这样添加它:
提取 framework.jar 文件
mkdir /tmp/framework
cp framework.jar /tmp
cd /tmp/framework
jar xvf ../framework.jar
mv android classes
构建 Android 存储库,它将创建 out/target/common/obj/JAVA_LIBRARIES 目录
查找缺失的类在哪里
$ 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
添加新类并重建框架 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 .
我无法发表评论,但这基本上是对@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。