android怎样调用@hide和internal API

发布网友 发布时间:2022-04-22 17:02

我来回答

1个回答

热心网友 时间:2023-11-13 09:40

  Android有两种类型的API是不能经由SDK访问的。

  第一种是位于com.android.internal包中的API。我将称之为internal API。第二种API类型是一系列被标记为@hide属性的类和方法。从严格意义上来讲,这不是一个单一的API,而是一组小的被隐藏的API,但我仍将其假设为一种API,并称之为hidden API。

  Hidden API 例子

  你可以查看一下android的源码,并能找到一些变量、函数和类等,都被@hide属性标记了。

  下面的例子就是在WifiManager(API 10源码)中隐藏的变量。

  另一个例子是在WifiManager(API 10源码)中隐藏了setWifiApEnabled函数。

  因此,只要你看到@hide属性,那你看到的就是hidden API。

  Internal和hidden API的区别

  Hidden API之所以被隐藏,是想阻止开发者使用SDK中那些未完成或不稳定的部分(接口或架构)。举个例子,Bluetooth API在API 5(Android 2.0)上才开放;在API 3 和4上都是用@hide属性隐藏了。当这些API被验证和清理后,Google的开发者会移除@hide属性,并让其在API 5官方化。很多地方在API 4 和5之间发生了变化。如果你的程序依赖某些隐藏的API,当其部署到新的平台上时,就有可能陷入困境。

  对于internal API来说,从来都没有计划将其开放出来。它就是Android的“内部厨房”,对开发者来说,应该将其视作黑盒。凡事都会有变化的。如果你依赖某些internal API,也有可能在新的Android release上,这些internal API发生变化,从而令你失望。

  总结一下区别:

  Hidden API = 进行中的工作;

  Internal API = 黑盒;

  Internal和hidden API的编译时 vs. 运行时

  当你使用Android SDK进行开发的时候,你引用了一个非常重要的jar文件——android.jar。它位于Android SDK平台的文件夹中(SDK_DIR/platforms/platform-X/android.jar,其中,X表示API等级)。这个android.jar移掉了com.android.internal包中所有的类,也移掉了所有标记有@hide的类,枚举,字段和方法。

  但当你在设备上启动应用程序时,它将加载framework.jar(简单来说,它和android.jar等同),而其未移掉internal API和hidden API。(但它对开发者来说,并不能友好地访问,因此,我将向大家展示不通过反射如何使用这些API)。

  关于internal API,还有一件事需要说明。Eclipse的ADT插件增加了一个额外的规则,那就是禁止使用com.android.internal包中的任何东西。所以,即便是我们可以拿到最原始的android.jar(未删减版),也没有轻松的办法通过Eclipse使用这些internal API。

  你可以亲自检查一下。创建一个新的Android工程(或者使用已有的)。查看一下它引用的类库(右击project Properties –> Java Build Path –> Libraries)。

  重要的总结:internal和hidden API在SDK中是按照一样的方式处理的(都从android.jar中移除了),但internal API更惨的是,还被Eclipse的ADT插件显式禁止了。

  不通过反射使用internal和hidden API

  这些文章的终极目标是让开发者能够不通过反射使用Internal和Hidden API。如果你完成了接下来部分中描述的步骤,你将能使用这些Internal和Hidden API,如同公开的API。你不再需要使用反射。

  注:如果你正在使用这些非公开的API,你必须知道,你的程序有着极大的风险。基本上,无法保证在下一次的Android OS更新时,这些API不被破坏,也无法保证不同的运营商有着一致的行为。你自己决定吧。

  接下来有三个场景:

  1. Internal 和hidden API都可用(场景A)

  2. 只Hidden API可用(场景B)

  3. 只Internal API可用(场景C)

  场景A是B、C的总和。场景B是最简单的一个(不需要对Eclipse的ADT修改)。

  场景A:阅读Part1, 2, 3, 4, 5

  场景B:阅读Part1, 2, 3, 5

  场景C:阅读Part1, 2, 3, 4, 5

  我解释了为什么我们不通过反射就会很难使用internal和hidden API。这是因为android.jar中就没包含这些API,因此,没人能够在编译时引用这些类。

  这篇文章将描述如何还原最初的android.jar。这将允许我们像使用公开的API那样使用internal和hidden API。

  如何得到原版android.jar?

  我们需要修改android.jar,这样它才能包含所有的*.class文件(包括internal和hidden API类)。有两种办法:

  1) Android是一个开源工程。我们可以下载源码并搭建编译环境,这样它就不能移除那些internal和hidden的类了。这个办法比较困难;

  2) 每个模拟器或真机在运行时都会有一个等同android.jar的东西。我们可以从这里拿到jar文件,提取出原始的.class文件,并拷贝到Android SDK的android.jar中。

  我将采用方案2。它易于开始,还不需要搭建Linux环境及编译环境等。

  从设备上获取framework.jar

  你可以使用命令行(adb pull)从模拟器或设备上下载文件,或者使用DDMS(借助Eclipse或SDK中的应用)。

  注意:模拟器通常在.dex文件中包含代码,而真机一般在优化版的dex文件中包含代码——odex文件。操作odex文件比较困难,这也是为什么我选择模拟器的原因。

  与Android SDK中的android.jar等同的文件是framework.jar。这个文件位于设备的:/system/framework/framework.jar

  adb pull /system/framework/framework.jar

  当framework.jar从设备上下下来之后,重命名为framework.zip并解压到的文件夹中,看起来是这个样子的:

  classes.dex正是我们需要的。

  创建framework-classes.zip

  首先,我们需要把.dex文件转换成.jar格式。你可以使用通用的工具dex2jar。只需要运行:

  dev2jar classes.dex

  当转换结束时,你应该得到了classes.dex.dex2jar.jar文件。重命名为framework-classes.zip。使用zip查看器,进入到framework-classes.zip/com/android/internal/:

  恭喜你,你已经拥有了所有的.class文件,包括internal和hidden API(尽管截图只确认了internal部分)。

  创建original-android.jar

  Android SDK的android.jar位于ANDROID_SDK/platforms/android-X/android.jar(X表示API等级)。

  拷贝android.jar成custom-android.jar。解压至custom-android文件夹。将framework-classes.zip中所有的.class文件拷贝到custom-android文件夹中(你需要覆盖所有已经存在的.class文件)。

  然后,压缩custom-android文件成original-android.zip。重命名为original-android.jar。

  步骤总结

  1. 选择你的目标平台X

  2. 创建目标平台X的模拟器

  3. 启动模拟器,下载/system/framework/framework.jar

  4. 重命名framework.jar -> framework.zip

  5. 从framework.zip中抽取classes.dex

  6. 使用dex2jar工具,将其转换成classes.jar

  7. 重命名classes.jar -> framework-classes.zip

  8. 拷贝android.jar –> custom-android.zip

  9. 解压custom-android.zip至custom-android文件夹

  10. 将framework-classes.zip中所有文件拷贝至custom-android文件夹(覆盖存在的文件)

  11. 压缩custom-android文件夹成original-android.zip

  12. 重命名original-android.zip -> original-android.jar

  打完收功。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com