使用internal(com.android.internal)和hidden(@hide)APIs

本文详细介绍了如何绕过SDK限制,使用Android内部API和隐藏API,包括还原android.jar、创建自定义Android平台、修改ADT插件等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Part One

原文路径:http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/

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

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

HiddenAPI 例子

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

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

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

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

Internal和hidden API的区别

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

对于internalAPI来说,从来都没有计划将其开放出来。它就是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和hiddenAPI。(但它对开发者来说,并不能友好地访问,因此,我将向大家展示不通过反射如何使用这些API)。

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

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

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

不通过反射使用internal和hidden API

这些文章的终极目标是让开发者能够不通过反射使用Internal和HiddenAPI。如果你完成了接下来部分中描述的步骤,你将能使用这些Internal和HiddenAPI,如同公开的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

Part 2

原文路径:http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-2-hacking-around/

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

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

如何得到原版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文件比较困难,这也是为什么我选择模拟器的原因。

与AndroidSDK中的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和hiddenAPI(尽管截图只确认了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

打完收功。

总结

我们还原了android.jar,使其包含所有的internal和hiddenAPI的.class文件。这只是第一步。下一步将创建定制的android平台,使其使用未删节版的android.jar,并将其添加到Android SDK platforms文件夹中。

Part 3

原文路径:http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-3-custom-android-platform/

在上一篇中,我已经展示了如何创建一个包含所有internal和hidden API的original-android.jar。

接下来的工作就是要修改已经存在的Android平台(SDK_DIR/platforms/platform-X/android.jar,X表示API等级)。你可以直接使用Part2中创建的original-android.jar替换android.jar。但这样的话,你的所有工程都将直接使用internal和hiddenAPI而没有任何限制。这不够方便,因为在多数的工程中你不希望这样。甚至,你可能更希望禁止这些API(ADT/android.jar的默认行为)。但对于一些特定的工程,你希望能够使用这些internal和hidden API。

为了达到这样的灵活性,你需要创建一个新的自定义的Android平台。当不需要访问internal和hiddenAPI时,你只需使用原有的Android平台。当你使用这些API时,你使用自定义的Android平台。

AndroidSDK文件夹结构

让我们看一下Android SDK树是如何组织的:

我们需要“platforms”文件夹。看一下里面:

这里列出了支持的Android平台。

现在,我们看一下它是如何与Eclipse设定关联的。选择你的工程,右击–> Properties –> Android。你将会看到一组支持的Android平台(与…/platforms/folder相似)。下面是截图:

创建新的平台

为了创建一个新的平台,我们需要拷贝android-9文件夹 -> android-9-internals。让我们做一些修正:

1. 删除其中的android.jar

2. 拷贝original-android.jar,并改名为android.jar

3. 修改build.prop文件:

ro.build.version.sdk=9 ->ro.build.version.sdk=-9

ro.build.version.release=2.3 ->ro.build.version.release=2.3.extended

重启Eclipse。并确认你能看到新的平台。下面是我所看到的:

为什么我选择API等级为-9?这是因为它必须是一个数字,而且它不能是9(或者其它已经存在的API等级)。否则,你自定义的平台将不能被使用(它在列表里可见,但选中后也不能正常工作,编译时仍然使用相应API等级的原始平台)。

下面是引用类库的截图(当前工程选中了自定义的平台):

总结

在上一篇中,我已经告诉你如何创建一个未删节版的android.jar。在这一篇中,我向你展示了如何创建一个自定义的Android平台,并在其中使用original-android.jar。这对于hidden API来说已经足够了。但对于internal API来说,还需要另一步。这是因为ADT仍然不允许使用com.android.internal包中的类(参见上图中的“forbidden”访问规则)。下一节我将向你展示如何定制ADT来允许使用internal包中的类。

============华丽的分割线=============

在实际的操作过程中,我创建的自定义的android.jar(API10)不能被Eclipse成功加载,会出现以下的错误框,如同网站上其它人操作的结果一样,期待解决方案。

不过,作者提供了可用的自定义的android.jar,如果不想自己尝试的话,可以直接从网站下载,地址将在Part5中给出,稍等。

Part 4

原文路径:http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-4-customizing-adt/

在上一篇文章里,我描述了如何创建一个自定义的original-android.jar,以及如何创建一个自定义的Android平台来使用这个original-android.jar。这对Hidden API来说足够了。但对Internal API来说,仍然还有一个包袱:Eclipse的ADT插件。它限制使用com.android.internal包中的任何类。

有几种方法可以解决这个访问限制。

1) ADT源码可以下载。因此,删除/修改代码中的某些代码,从而编译出一个新的ADT是可以的。麻烦的是你需要搭建64位Linux系统,下载源码,编译等。它需要花费一些时间。当有新的ADT版本时,你需要重来一遍。

2) 另外的方法就是修改ADT的字节码。用一个类似于“com/android/internax/**”的字符串替换“com/android/internal/**”。

第二种方法可以用脚本实现。并且不需要访问源码以及可在Windows上操作。这也是为什么我在这篇中选用第二种解决方案的原因。

修改ADT的字节码

进入Eclipse的plugins文件夹。找到文件名看起来像“com.android.ide.eclipse.adt_*.jar”的文件。备份一下这个文件(以防中间有错误发生)。并拷贝这个文件到一个“experimental”文件夹,在这里,我们要完成对其字节码的修改。

重命名*.jar为*.zip。解压这个文件到单独的文件夹。参看以下图片:

现在,进入到com/android/ide/eclipse/adt/internal/project子文件夹。

找到AndroidClasspathContainerInitializer.class文件。

这个文件包含“com/android/internal/**”字符串。接下来就是要替换这个字符串,例如“com/android/internax/**”。改变字符串的长度理论上是安全的,但最好还是替换其中的一个字母,并保持长度一致。

我使用notepad++修改的,它支持非可印刷字符,因此在对其修改时,不要触碰修改非可印刷字符。

当做完这个,保存文件。压缩这个文件夹,保证文件名与原始文件一模一样。在我这里,文件名是:com.android.ide.eclipse.adt_8.0.1.v201012062107-82219.zip。

注意:确保压缩文件的正确性。比较原始文件和修改文件的根文件结构。

现在,用修改后的版本替换原来的ADT的*.jar文件。然后,启动Eclipse。

在使用库窗口,你应该看到下面的样子,一切都变得那么的美好:

步骤总结

1. 关闭Eclipse

2. 从Eclipse的plugin文件夹中拷贝出ADT插件的jar文件

3. 重命名.jar -> .zip,然后解压至独立的文件夹

4. 找到com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.class文件

5. 用“com/android/internax/**”替换“com/android/internal/**”

6. 压缩这个文件夹

7. 重命名 .zip -> .jar

8. 用修改后的jar替换原始的ADT jar文件

9. 启动Eclipse

结论

这是不使用反射也能使用Internal API的最后一步。

Part 5

 

原文路径:https://devmaze.wordpress.com/2011/01/19/using-com-android-internal-part-5-summary-and-example/

为了能够使用Internal和HiddenAPI,你需要:

1. 创建自定义的original-android.jar,包含所有的.class文件

2. 创建自定义的Android平台来使用original-android.jar

3. 修改ADT插件,允许使用com.android.internal包(只为Internal API)

4. 创建新的工程,引用自定义的Android平台(本文中的例子)

在本文中,我将向你们展示如何使用那些Internal和HiddenAPI。

此外,在本文的结尾,我列出了一些自定义的Android平台,它们都包含Internal和HiddenAPI。我附带了它们,是为了可能你不想花太多时间在这方面,但又想快速的尝试什么。

例子

创建一个新工程,选择2.3.extender平台:

下面是代码:

这个代码使用了Internal API(PowerProfile)和Hidden API(isWifiApEnabled)。我不用使用反射就能编译并运行这些代码。

自定义平台

下面有些平台,是我为自己创建的。只用拷贝它们到SDK_DIR\platforms文件夹下。这只是让Hidden API可用。对于Internal API,你需要修改你的ADT插件。

API 3:http://www.megaupload.com/?d=S1F2MKYZ

API 4:http://www.megaupload.com/?d=VUCTRI3Y

API 7:http://www.megaupload.com/?d=7ITNILBK

API 8:http://www.megaupload.com/?d=EXT5FKKT

API 9:http://www.megaupload.com/?d=EXT5FKKT

API 10:http://www.megaupload.com/?d=FCV78A9M

==============华丽的分割线=============

我尝试了其中的几个自定义平台,发现,internal 和hiddenAPI真的是可用了,但也有一些意外的问题,如AlertDialog.Builder(Context context)居然说Context参数是多余的。。

没花时间去研究为什么会这样,如果哪位童鞋知道原因,告诉我哈~~

 

<think>好的,用户想在Android Studio中集成或使用play.googleapis.com服务,我需要帮他解决配置使用的问题。首先,我得回忆一下相关的步骤可能遇到的问题。 首先,应该确保项目配置正确。用户可能需要添加Google Play服务依赖。记得在build.gradle里添加implementation 'com.google.android.gms:play-services-auth:20.7.0'这样的依赖,版本号可能需要更新,得检查最新的版本。同时,可能还需要在项目的build.gradle里包含Google的Maven仓库,这样Gradle才能找到这些依赖。 然后,可能需要配置API密钥启用相关的API。用户需要在Google Cloud控制台创建一个项目,启用需要的API,比如Maps、Location或Sign-In,然后生成API密钥,并在AndroidManifest.xml里添加元数据。这部分可能需要指导用户如何获取密钥,并且注意保护密钥不被泄露。 另外,关于ProGuard的配置,如果启用了代码混淆,可能需要添加规则来保留Play服务的类,避免运行时出错。比如-keep class com.google.android.gms.** { *; }这样的规则。 还有可能遇到依赖冲突的问题,特别是如果项目中用了其他Google库,版本不一致的话。这时候需要统一版本号,或者排除冲突的模块。例如,使用exclude group来排除特定组。 用户可能还会遇到API级别的问题,比如Google Play要求target API 30以上,这时候需要检查build.gradle中的targetSdkVersion,确保不低于30。如果用户遇到相关错误,可能需要调整lintOptions来暂时绕过检查,但最终还是要升级API级别。 另外,关于模拟器的选择,可能需要使用带有Google Play服务的系统镜像,这样在测试时才能正常调用相关APIAndroid 11之后可能只有Google API的镜像可用,用户需要确认在创建AVD时选择正确的镜像。 可能还需要引用一些官方文档或博客,比如Android开发者博客中的最新工具更新,或者Google Play Publisher API使用教程,来增强答案的可信度。同时,注意引用用户提供的参考链接,比如引用[1]到[5]中的相关内容。 最后,用户可能会遇到编译错误,比如重复的类或依赖冲突,这时候需要检查依赖树,使用./gradlew app:dependencies命令分析,然后排除冲突的依赖。例如,排除com.google.android.gms中的重复模块。 总结下来,步骤应该是:添加依赖、配置API密钥、处理ProGuard、解决依赖冲突、调整API级别、选择正确的模拟器镜像,并引用相关的文档解决方案。同时,生成相关的问题,帮助用户进一步了解可能遇到的其他问题。</think>在Android Studio中配置使用play.googleapis.com服务(如Google Play服务API)需遵循以下步骤: ### 一、基础配置 1. **添加Google Play服务依赖** 在模块的`build.gradle`文件中添加最新版本依赖(当前推荐版本): ```groovy dependencies { implementation 'com.google.android.gms:play-services-auth:20.7.0' // 示例认证服务 implementation 'com.google.android.gms:play-services-maps:18.2.0' // 示例地图服务 } ``` 需在`settings.gradle`中包含Google Maven仓库: ```groovy dependencyResolutionManagement { repositories { google() // 必须添加[^5] } } ``` 2. **API密钥配置** - 在[Google Cloud控制台](https://console.cloud.google.com/)创建项目并启用所需API - 在`AndroidManifest.xml`中添加元数据: ```xml <meta-data android:name="com.google.android.geo.API_KEY" android:value="YOUR_API_KEY"/> ``` ### 二、常见问题处理 1. **API级别冲突** 修改`build.gradle`确保最低兼容: ```groovy android { defaultConfig { minSdkVersion 21 targetSdkVersion 34 // 必须≥30[^1] } lintOptions { checkReleaseBuilds false // 临时绕过检查 } } ``` 2. **依赖冲突解决** 当出现`Program type already present`错误时: ```groovy implementation('com.google.api-client:google-api-client-android:1.22.0') { exclude group: 'com.google.android.gms' // 排除冲突模块[^2] } ``` ### 三、高级配置 1. **ProGuard规则** 在`proguard-rules.pro`中添加: ```proguard -keep class com.google.android.gms.** { *; } -keep interface com.google.android.gms.** { *; } ``` 2. **模拟器选择** 在AVD Manager中创建模拟器时: - 选择带有`Google Play`或`Google APIs`标识的系统镜像 - 推荐使用Pixel系列设备模板 ### 四、验证与调试 1. **检查服务可用性** ```java if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) { // 服务可用 } ``` 2. **生成式AI集成(可选)** 最新Android工具链支持AI辅助开发,可参考[Android开发者博客][^3]的最新指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值