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

发布于 2024-12-11 12:35:34 字数 264 浏览 0 评论 0 原文

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

我找不到任何有关如何解决此问题的文档或讨论。我已经设置了能够构建 cm7 的 Ubuntu CyanogenMod 构建环境。

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

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

I want to rebuild the Android SDK (or rather only the android.jar) to include hidden and internal APIs.

I could not find any documentation or discussion doing on how to go about this. I have an Ubuntu CyanogenMod build environment already setup that is able to build cm7.

Now, I read that make SDK will build the SDK but I want to build an SDK that includes methods and fields that are marked as hidden using @hide. Is this possible?

What I want to do is make changes to an application that uses hidden API and in order to rebuild it I would like to use the modified SDK.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

一影成城 2024-12-18 12:35:35

我们可以从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

引入这些 jar

  • 然后使用“添加外部 JAR...”(假设您使用的是 Eclipse ADT)右键单击 Project → Properties → Java Build Path → Libraries → Add external JARs... → (从上面选择 core-dex2jar.jarframework-dex2jar.jar)。

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

We could reconstruct the *.jar files from the Android platform.

First, connect ADB to your device. Then run:

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

The core.jar contain the standard Java libraries (java.*) and the framework.jar contain the Android libraries (android.*). This is not usable yet, as the actual files are in DEX format, not JAR format.

We could convert these DEX-formatted *.jars into real JARs using tools such as dex2jar:

dex2jar core.jar
dex2jar framework.jar

Then pull in these jars using "Add External JARs..." (assuming you're using Eclipse ADT)

  • right click on Project → Properties → Java Build Path → Libraries → Add External JARs... → (Choose the core-dex2jar.jar and framework-dex2jar.jar from above).

This will enable you to use the internal and some Java 7 APIs. (The generated APK, as far as I can see, does not contain any actual code from the JARs.)

泅渡 2024-12-18 12:35:35

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

You can download the modified android.jar to be used as hidden APIs from this repository. Follow the instructions there.

不必你懂 2024-12-18 12:35:35

对于 Lollipop,流程略有不同:

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

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

  3. 你会得到两个文件夹: dex和奥德克斯。转到 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

For Lollipop the flow is little different:

  1. Get /system/framework/arm/boot.oat from lollipop device

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

  3. You will get two folders: dex and odex. Go to dex and make 'java -jar dex2jar.jar framework.dex'
  4. Rename resulting framework.jar to .zip, extract and find classes you need
  5. Go to [sdk_path]/platforms/[target_platform] and extract android.jar (first rename it to zip).
  6. Copy files from extracted framework to extracted android.jar. Then compress to zip and rename to .jar :)

ps: probably you need repeat steps 4-6 for 'framework_classes2.dex'

过期以后 2024-12-18 12:35:35

DroidCon 2011

来自索尼爱立信的 Erik Hellman 解释了如何访问隐藏的 Android API :

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

转到DroidCon 网页第 2 天向下滚动到使用隐藏的 API 10 :15 你可以在那里观看。

链接正在消失!

我找到了这个: http://skillsmatter.com/podcast/os -mobile-server/hidden-api 我不知道,它会持续多久。

Android SDK 中的官方 API 通常足以满足大多数普通应用程序的需要。然而,有时开发人员需要访问官方 API 中未发布的内部系统服务、API 和资源。幸运的是,这些 API 仍然可以通过一些巧妙的技巧来使用,并且在 Android 上开发新的创新解决方案时通常很有用。在本次会议中,您将了解如何访问和使用这些隐藏和受保护的 API、它们的使用限制以及有关如何跨多个供应商设备和 Android 版本以安全和可控的方式使用它们的一些提示和技巧。观众将看到几个通常用 Android 无法做到的高级演示。期待一场相当高级的会议,其中包含有关 Android 平台内部的大量见解。

DroidCon 2011

Here Erik Hellman from Sony Ericson explains how to access the hidden Android API's:

http://vimeo.com/30180393
(Hmm link doesn't appear to work).

Goto the DroidCon webpage Day 2 scroll down to Using Hidden APIs 10:15 and you can watch it there.

Links are dieing!

I've found this one: http://skillsmatter.com/podcast/os-mobile-server/hidden-api I don't know, how long it'll be up.

The official APIs in the Android SDK is usually sufficient for most normal applications. However, there are sometimes situations where a developer needs access to the internal system services, APIs and resources that are not published in the official APIs. Fortunately, these APIs are still available through some clever tricks and can often be useful when developing new and innovative solution on top of Android. In this session you will learn how to access and use these hidden and protected APIs, the limitations of their usage and some tips'n'trick on how to use them in a safe and control manner across multiple vendors devices and Android versions. The audience will see several advanced demos that you normally cannot do with Android. Expect a fairly advanced session with lots of insights in the internals of the Android platform.

悸初 2024-12-18 12:35:35

尝试看看这个

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

但是,如果您使用这些非公共 API,那么您应该意识到您的应用程序面临巨大风险。基本上无法保证 API 不会因 Android 操作系统的下一次更新而被破坏。甚至无法保证不同供应商的设备之间的行为一致。你完全靠自己了。

您可能需要遵循三种情况:

  1. 启用内部隐藏 API(场景 A)
  2. 仅启用隐藏 API(场景 B)
  3. 仅启用内部 API(场景 C)

场景 A 是 B 和 C 的总和。场景 B 是最简单的一个(不需要修改 eclipse ADT 插件)。

场景 A:阅读部分 123, 45

场景 B:阅读部分 123, 5

场景 C:阅读部分 123, 45

Try to look at this:

The ultimate target of these articles is to give developers the power of Internal and Hidden APIs without using reflection. If you complete all the steps described in next several parts you will be able to use Internal and Hidden APIs as if they were public open APIs. There will be no need for reflection.

But if you’re using these non-public APIs then you should be aware that your application is at great risk. Basically there are no guarantees that APIs will not be broken with next update to Android OS. There are even no guarantees about consistent behavior across devices from different vendors. You are completely on your own.

There are three scenarios you may want to follow:

  1. Enable both internal and hidden APIs (scenario A)
  2. Enable only hidden API (scenario B)
  3. Enable only internal API (scenario C)

Scenario A is a sum of B and C. Scenario B is the easiest one (requires no eclipse ADT plugin modifications).

Scenario A: read parts 1, 2, 3, 4, 5

Scenario B: read parts 1, 2, 3, 5

Scenario C: read parts 1, 2, 3, 4, 5

鹿港小镇 2024-12-18 12:35:35

我曾经编写过一些 Groovy 脚本,用于从 http://source.android.com/ 然后编译它们,而不需要完整的工具链来编译所有 Android 源代码,包括所需的其他步骤(打包、生成资源等)。

它们可以在这里找到:

https://github.com/thoutbeckers/CollectAndroid

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

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

正如其他地方提到的,由于添加了访问规则,com/android/internal/** 在最新版本的 ADT 中仍将被隐藏。

I once wrote some Groovy scripts for extracting the java files from a repo checkout from http://source.android.com/ and then compiling them without the need for a full toolchain for compiling all the android sources, including the needed other steps (packaging, generating resources etc).

They can be found here:

https://github.com/thoutbeckers/CollectAndroid

But for sure this will need updating for anything after Gingerbread, mostly by setting the correct directories in "rootdirs" in the config file (CollectConfig.groovy).

At the time I regularly used this for development with all of the hidden API and sources (also problematic at the time) available.

As mentioned elsewhere com/android/internal/** will still be hidden in recent versions of ADT due to the access rule aded.

反差帅 2024-12-18 12:35:35

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

  1. 提取framework.jar文件

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

  3. 查找缺少的类的位置

    $ cd /path/to/out/target/common/obj/JAVA_LIBRARIES
    $ 查找 . | 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 。
    光盘课程
    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 .

Long's answer worked for me, but I was still missing some classes I needed, in particular android.provider.Telephony. I was able to add it like this:

  1. Extract the framework.jar file

    mkdir /tmp/framework
    cp framework.jar /tmp
    cd /tmp/framework
    jar xvf ../framework.jar
    mv android classes
    
  2. Build the Android repo, which will create the out/target/common/obj/JAVA_LIBRARIES directory

  3. Find where the missing classes are

    $ 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. Add the new classes and rebuild the framework JAR file

    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 .
    

Or you can just be lazy and include all of the classes into one giant jar file:

cd /tmp/framework
cp -r /path/to/out/target/common/obj/JAVA_LIBRARIES/*/classes .
cd classes
jar cvf ../framework.jar .
标点 2024-12-18 12:35:35

我无法发表评论,但这基本上是对 @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。

I can't comment but this is basically a comment to @KennyTM's (https://stackoverflow.com/a/13550030/2923406) excellent answer:

If you find yourself with the following error in Eclipse:

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

(that is, android.internal.* is not available)

Then one possible solution is to apply the same method for /system/framework/framework2.jar. Using the Android Emulator for SDK19 I have this extra jar. On my HTC One there is even a framework3.jar.

☆獨立☆ 2024-12-18 12:35:34

这就是我使用隐藏 api 时经常做的事情。

  1. 构建存储库或从 https:/ 下载 jar /sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong
  2. 复制out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar (最好将其重命名为类似framework_all.jar 的名称)
  3. 配置您的项目构建路径 --> 库 -->添加这个外部罐子。在 Order and Export 中,将其向上移动到 android.jar 之前

This is what I always do to use hidden api.

  1. Build the repo or download jars from https://sites.google.com/site/hippunosource/home/android/androidnohide-apiwo-shi-yongsuru-rifurekushonha-wei-shi-yong
  2. copy out out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar (better to rename it as something like framework_all.jar)
  3. config your project build path-->libraries --> add this external jars. In Order and Export, move it up and before android.jar
万人眼中万个我 2024-12-18 12:35:34

我对此进行了一些调查,我的结论很简单:如果没有大量工作,这是不可能完成的。阅读本答案的其余部分,了解我发现的详细信息。


android.jar 实际上由 framework.jarcore.jar 的“公共 api”组成,可以在 system/ 中找到设备上的框架/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 存根,然后这些存根被编译到在 SDK 中分发的 android.jar 中。

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

但是,如果您想包含所有隐藏部分,事情就会变得更加复杂。您可以修改DroidDoc(相关源位于build/tools/droiddoc/src/Stubs.java中),这样就不会检测到任何隐藏内容。这是非常简单的,我已经尝试过了,但是随后生成的存根根本无法编译。

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

所以我对你的问题的回答是:不,如果不做大量工作,这是不可能完成的。抱歉。


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

然而,这与问题无关,因为 Android SDK 构建使用 mkstubs 工具。 (很遗憾。)

I have done some investigating into this, and my conclusion is simply: This cannot be done without quite a bit of work. Read the rest of this answer for details on what I have found.


android.jar is actually comprised of the "public api" of framework.jar and core.jar which is found in system/frameworks/ on the device. android.jar is a kind of what I would call Java library header, all implementation in the actual byte code are just a throw new RuntimeException("stub");, this allows you to build against android.jar (e.g. in Eclipse), but execution has to be performed on a device or emulator.

The public API of the Android SDK is defined by classes/methods/fields that are not prefixed with the @{hide} javadoc annotation. I.e. everything that is not annotated is included in the SDK.

android.jar is built from the sources located in out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates which itself is generated by the tool DroidDoc located in build/tools/droiddoc.

DroidDoc is the tool (probably adapted from javadoc, or using javadoc) that generate the actual Android SDK documentation. As a side-effect, and probably because it is already parsing all the javadoc, it also spews out the android stubs which are then compiled into the android.jar which is distributed in the SDK.

So to include the stuff that is hidden you could, if you only want to include specific parts, just remove the @hide annotation and rebuild the SDK.

However if you want to include all the hidden parts things get a lot more complicated. You can modify DroidDoc (the relevant source is in build/tools/droiddoc/src/Stubs.java) such that nothing is detected as hidden. This is quite trivial and I have tried this, however the stubs that is then generated does not compile at all.

My conclusion by now is that this is simply not feasible. The stubs generated if you remove the part of DroidDoc that detect hidden annotations, is simply not compilable, and would require quite a bit of work to compile correctly.

So my answer to your questions is: No, this cannot be done, without doing a lot of work. Sorry.


A side note about the mkstubs tool. mkstubs are used when you build a SDK addon, i.e. the addons you can find in the Android SDK manager from vendors, e.g. Samsung providing you with an additional API for stuff specific to Samsung phones. mkstubs does much the same as the DroidDoc stubs generation process, however it does not use @hide annotations, it uses a .defs file describing which packages/classes/fields to include or exclude from your SDK addon.

However this is all irrelevant to the question, as the Android SDK build does not use the mkstubs tool. (Unfortunately.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文