android调用webapi怎样调用@hide和internal API

android使用隐藏api的方法(使用被@hide的api)
一开始需要说明的是,之所以要将一些隐藏(指加上标记的类、方法或常量)是有原因的。其中很大的原因就是系统本身还在不断的进化发展中。从、到现在即将问世的。&这些隐藏的本身可能是不稳定的,所以,使用隐藏,意味着程序更差的兼容性。
&&&&如果要我给出建议的话,最好还是不要使用隐藏的。不过有时为了实现应用某些特殊的功能或者效果,隐藏的往往能发挥意想不到的作用。这些具体能做些什么事,我就不在这里举例了。正好,如果你不知道隐藏能做什么的话,那么还是尽早放弃使用它们吧……
&&&&不想长篇大论,直接进入正题吧。使用隐藏主要有两种办法:一是我在《》一文中提到的反射的方法得到隐藏;二是使用源码编译时生成的全编译的包。
&&&&使用反射的方式,在这里就不详细介绍了,具体见《》。利用反射机制使用隐藏的方法的优点是灵活,能够在不兼容的系统捕获异常,而使程序不至于崩溃;缺点是过程太繁杂,而且对于隐藏类的继承等很难实现。如果需要大量使用隐藏,使用反射无疑会让程序员很烦的。
&&&&这篇文章主要要介绍的就是通过导入全编译的包,来实现对隐藏的使用。这种方法实现简单,程序员编程也简单,就像是那些隐藏的在中变得可见了一样。它的缺点就是兼容性问题,希望使用者引起重视,在使用时考虑清楚。
我们使用sdk在开发一个android项目时,往往不能使用被隐藏的api,比如说:
1.我们想实现应用的静默安装,我们不能使用
pm.installPackage(mPackageURI, observer,
installFlags,installerPackageName);
2.使用大容量存储的相关功能时,不能使用
StorageManager s =
(StorageManager)
getSystemService(Context.STORAGE_SERVICE);
以自带android自带的AlarmClock 为例,导入eclipse后,往往出现很多错误,如下图所示:
例如,上图中的Intent.ACTION_ALARM_CHANGED 无法访问,下面我们就找到源代码看看原因何在?
我所介绍的方法必须要在linux下编译,但仅仅只是编译sdk,开发还是在windows下,假如你现在还不会android源码编译,请先搞定这个,再往下看。下面的方法二真的是非常的方便,解决了我好多问题,强烈建议你耐心看看。
根据java 编程规范,我们知道这个api
(静态变量)被隐藏掉了,所以在sdk中无法使用。在知道了原因之后,我们有几种解决方案(强烈建议使用方法二):
方法一:自己将源代码中的@hide去掉,然后编译一个sdk来替换默认的sdk。&
在linux上使用& make PRODUCT-sdk-sdk
命令,编译一个新的sdk出来,注意编译后其实我们不需要整个sdk,只需要android.jar这个文件替换掉sdk里的android.jar,例如:笔者的sdk里的jar对应的目录为:
F:/Program
Files/Android/android-sdk-windows/platforms/android-8/android.jar
具体编译sdk的方法是,在linux编译环境下用命令make PRODUCT-sdk-sdk ,成功后,会有如下提示:
Package SDK:
out/host/linux-x86/sdk/android-sdk_eng.stevewang_linux-x86.zip
我们进入到linux编译环境的&out/host/linux-x86/sdk/android-sdk_eng.stevewang_linux-x86/platforms/android-2.2/目录下可以看到android.jar&文件。使用此文件替换&&
F:/Program
Files/Android/android-sdk-windows/platforms/android-8/android.jar
即可。替换前记得备份
此方法较为麻烦,建议使用方法二
方法二:添加framework
编译出来的classes.jar文件到eclipse的build
其实在编译android的时候,我们将framework
编译到一个临时的jar包中了,这个jar包的路径一般为:
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
我们只需要在linux上android源代码目录下使用make 命令即可生成此文件。
由于这个jar文件中的api
还没有重新打包,里面被@hide掉的api并没有被去掉。所以我们依然能够引用里面被@hide的api。而sdk
中的android.jar文件时重新打包生成的,其里标记有@hide的api已经被去掉了。所以我们把&out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
拷贝到本地pc上。然后在工程中添加此jar包。
拷贝linux编译生成的&
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar到本机PC。
2,在eclipse的Android项目中,选择项目属性-&Java
Build Path-&Libraries-&Add Library-&User
Library-&Next-&
UserLibraries进入到User
Libraries管理界面,点击New新建一个User
Library,比如android_framework,点击Add
Jars把Jar包加入到建立的User
Library中,最后点击OK。
3.选择项目属性-&Java Build
Path-&Order and
Export,使用右面的“UP”键,把所建立的User
Libraries移到Android
SDK的上面。这样做的意思就是优先使用classes.jar中的API,其次使用android.jar中的API。为什么不直接使用classes.Jar?因为我在使用时发现,android.jar中有的东西classes.jar中没有。
之后我们的工程错误消失了:
到此问题基本解决.
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Android——@hide和internal API
& 在使用eclipse编译android工程时,有时会碰到找不到引用的错误,但是在linux下又是能编译过的。
这是因为eclipse编译通过SDK无法访问到com.android.internal包中的API,以及标记为@hide属性的类和方法。
一般网上下载的android-sdk-linux安装好之后 会在android-sdk-linux/platforms/android-17/ (我的是api 17 android 4.2)下有一个android.jar
这个android.jar移掉了com.android.internal包中所有的类,也移掉了所有标记有@hide的类,枚举,字段和方法的。
package android.content.
See {@link PackageManager} for documentation on most of the APIs
public interface IPackageManager extends android.os.IInterface
这个作为 PackageManager的实现接口 其中有很多@hide方法 比如比较实用的静默安装API &:
public void installPackage(android.net.Uri packageURI, android.content.pm.IPackageInstallObserver observer, int flags, java.lang.String installerPackageName)
同样 com.android.internal.content中的PackageHelper.java &也是无法调用的。
下面记录一下如何制作完整的 android.jar 的方法:
1:下载源码编译过的,在/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates中有javalib.jar 也就是 framework.jar
& & & &或者 通过 eclipse adb 连接真机获取 adb pull /system/framework/framework.jar
2:重命名framework.jar为framework.zip 解压获得 classes.dex。 使用 dex2jar 反编译 得到 classes_dex2jar.jar(反编译脚本 dex2jar.sh),classes_dex2jar.jar中有所有的@hide以及internal的class。
3:重命名然后解压sdk中的android.jar,将classes_dex2jar.jar中的.class 拷贝覆盖过去。然后再压缩成.zip ,重命名为android.jar。
此时的android.jar 完整!
eclipse安装的ADT会限制com.android.internal的使用,所以需要修改如下:
从eclipse中的plugins中拷贝出adt文件:com.android.ide.eclipse.adt_22.0.1.v--685705.jar(根据个人版本而定)
重命名&&.zip 解压 找到com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.class文件。
使用编辑器打开 搜索到关键的 internal/** , 用 &&com/android/internax/**& &替换&com/android/internal/**& & &将internal改成internax &只要不是internal 就行,但是字母数不变。
改好之后,压缩,重命名回去。重启eclipse,
至此,eclipse上就没有限制了!
这样做,无法保证在下一次的Android更新时,这些API不被破坏,等于你的代码跳出了兼容圈。慎用~
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'使用内部(com.android.internal)和隐藏(@hide)API[第4部分,定制ADT] - veins - 博客园
随笔 - 191, 文章 - 0, 评论 - 2, 引用 - 0
本文翻译自
在前面的文章中,我讲述了如何创建定制的original-android.jar和创建定制的android平台以使用original-android.jar。这仅仅能够使用隐藏API,还为内部API留有一个障碍: ADT。ADT定义了一个规则禁止使用来自com.android.internal的类。
有几种方法可以越过该限制规则:
1)完整的ADT源代码可以下载,可以移除或者修改代码,编译然后安装新的定制版本ADT。不好的地方是您必须配置一台64位linux系统,下载源码,编译之。这会花费一些时间,当新版本的ADT出来后,您又需要重新来过。
2)另外一种方式是修改ADT的字节码,只需替换"com/android/inter/**&字符串为其它的字符串,比如"com/android/internax&。
第二种方法可通过脚本自动化完成,也不需要访问源码,在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++进行替换的,因为它支持非打印字符,而且在编辑打印字符时不会修改非打印字符。
修改完后,保存文件,zip压缩文件夹,文件名和原始版本一样。以我的为例:com.android.ide.eclipse.adt_8.0.1.v-82219.zip,然后重命名为*.jar。
注意:请确保您正确的压缩了文件,可以比较一下修改的zip和原始的zip的内部目录结构。
现在删除eclipse plugins文件夹下的原始ADT*.jar文件,复制经过修改的版本,重启eclipse。
如果没有问题,则会如下图所示:
步骤总结:
停止eclipse
从eclipse的plugins文件夹取得adt插件的jar文件。
重命名.jar为.zip,然后解压到一个单独的目录。
找到com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.class
将字符串"com/android/internal/**&替换为"com/android/internax/**&
zip压缩所有文件
重命名.zip为.jar
用修改版本替换eclipse plugins文件夹下的原始adt jar文件
启动eclipse。13249人阅读
Android开发(290)
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
打完收功。
我们还原了android.jar,使其包含所有的internal和hidden API的.class文件。这只是第一步。下一步将创建定制的android平台,使其使用未删节版的android.jar,并将其添加到Android SDK platforms文件夹中。
我已经展示了如何创建一个包含所有internal和hidden API的original-android.jar。
接下来的工作就是要修改已经存在的Android平台(SDK_DIR/platforms/platform-X/android.jar,X表示API等级)。你可以直接使用Part2中创建的original-android.jar替换android.jar。但这样的话,你的所有工程都将直接使用internal和hidden API而没有任何限制。这不够方便,因为在多数的工程中你不希望这样。甚至,你可能更希望禁止这些API(ADT/android.jar的默认行为)。但对于一些特定的工程,你希望能够使用这些internal和hidden
为了达到这样的灵活性,你需要创建一个新的自定义的Android平台。当不需要访问internal和hidden API时,你只需使用原有的Android平台。当你使用这些API时,你使用自定义的Android平台。
Android SDK文件夹结构
让我们看一下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(API 10)不能被Eclipse成功加载,会出现以下的错误框,如同网站上其它人操作的结果一样,期待解决方案。
不过,作者提供了可用的自定义的android.jar,如果不想自己尝试的话,可以直接从网站下载,地址将在Part5中给出,稍等。
为了能够使用Internal和Hidden API,你需要:
1. 创建自定义的original-android.jar,包含所有的.class文件
2. 创建自定义的Android平台来使用original-android.jar
3. 修改ADT插件,允许使用com.android.internal包(只为Internal API)
4. 创建新的工程,引用自定义的Android平台(本文中的例子)
在本文中,我将向你们展示如何使用那些Internal和Hidden API。
此外,在本文的结尾,我列出了一些自定义的Android平台,它们都包含Internal和Hidden API。我附带了它们,是为了可能你不想花太多时间在这方面,但又想快速的尝试什么。
创建一个新工程,选择2.3.extender平台:
下面是代码:
这个代码使用了Internal API(PowerProfile)和Hidden API(isWifiApEnabled)。我不用使用反射就能编译并运行这些代码。
自定义平台
下面有些平台,是我为自己创建的。只用拷贝它们到SDK_DIR\platforms文件夹下。这只是让Hidden API可用。对于Internal API,你需要修改你的ADT插件。
==============华丽的分割线=============
我尝试了其中的几个自定义平台,发现,internal 和hidden API真的是可用了,但也有一些意外的问题,如AlertDialog.Builder(Context context)居然说Context参数是多余的。。
没花时间去研究为什么会这样,如果哪位童鞋知道原因,告诉我哈~~
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1234615次
积分:12179
积分:12179
排名:第802名
原创:151篇
转载:262篇
评论:218条
(1)(12)(5)(1)(2)(1)(1)(6)(15)(3)(8)(6)(3)(27)(22)(25)(4)(6)(7)(7)(2)(2)(13)(8)(3)(2)(2)(11)(2)(3)(3)(14)(6)(7)(11)(1)(6)(9)(19)(14)(3)(7)(10)(3)(4)(7)(6)(14)(13)(4)(4)(22)(3)(6)(6)由于黏贴后原有图片显示不出来,感兴趣的可以下载word文档,详见如下&
使用internal(com.android.internal)和hidden(@hide)APIs
原文路径:
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
打完收功。
我们还原了android.jar,使其包含所有的internal和hidden
API的.class文件。这只是第一步。下一步将创建定制的android平台,使其使用未删节版的android.jar,并将其添加到Android SDK platforms文件夹中。
原文路径:
在上一篇中,我已经展示了如何创建一个包含所有internal和hidden API的original-android.jar。
接下来的工作就是要修改已经存在的Android平台(SDK_DIR/platforms/platform-X/android.jar,X表示API等级)。你可以直接使用Part2中创建的original-android.jar替换android.jar。但这样的话,你的所有工程都将直接使用internal和hidden API而没有任何限制。这不够方便,因为在多数的工程中你不希望这样。甚至,你可能更希望禁止这些API(ADT/android.jar的默认行为)。但对于一些特定的工程,你希望能够使用这些internal和hidden API。
为了达到这样的灵活性,你需要创建一个新的自定义的Android平台。当不需要访问internal和hidden
API时,你只需使用原有的Android平台。当你使用这些API时,你使用自定义的Android平台。
Android SDK文件夹结构
让我们看一下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(API 10)不能被Eclipse成功加载,会出现以下的错误框,如同网站上其它人操作的结果一样,期待解决方案。
不过,作者提供了可用的自定义的android.jar,如果不想自己尝试的话,可以直接从网站下载,地址将在Part5中给出,稍等。
原文路径:
在上一篇文章里,我描述了如何创建一个自定义的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.v-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
8. 用修改后的jar替换原始的ADT jar文件
9. 启动Eclipse
这是不使用反射也能使用Internal
API的最后一步。
原文路径:
为了能够使用Internal和Hidden API,你需要:
1. 创建自定义的original-android.jar,包含所有的.class文件
2. 创建自定义的Android平台来使用original-android.jar
3. 修改ADT插件,允许使用com.android.internal包(只为Internal API)
4. 创建新的工程,引用自定义的Android平台(本文中的例子)
在本文中,我将向你们展示如何使用那些Internal和Hidden API。
此外,在本文的结尾,我列出了一些自定义的Android平台,它们都包含Internal和Hidden
API。我附带了它们,是为了可能你不想花太多时间在这方面,但又想快速的尝试什么。
创建一个新工程,选择2.3.extender平台:
下面是代码:
这个代码使用了Internal
API(PowerProfile)和Hidden API(isWifiApEnabled)。我不用使用反射就能编译并运行这些代码。
自定义平台
下面有些平台,是我为自己创建的。只用拷贝它们到SDK_DIR\platforms文件夹下。这只是让Hidden API可用。对于Internal
API,你需要修改你的ADT插件。
==============华丽的分割线=============
我尝试了其中的几个自定义平台,发现,internal 和hidden API真的是可用了,但也有一些意外的问题,如AlertDialog.Builder(Context
context)居然说Context参数是多余的。。
没花时间去研究为什么会这样,如果哪位童鞋知道原因,告诉我哈~~
@import url(/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
阅读(2764)
&re: [转]使用internal(com.android.internal)和hidden(@hide)APIs
好东西。。。&&&&&&
&re: [转]使用internal(com.android.internal)和hidden(@hide)APIs
absolutely 牛逼&&&&&&
&re: [转]使用internal(com.android.internal)和hidden(@hide)APIs
请问,AlertDialog.Builder的这个问题解决了吗?&&&&&&
留言簿(13)
个人其它博客
转android开发后,新开设的技术方面的博客空间
个人的QQ空间,记得日志相对比较多一些,目前主要在这里活动了,呵呵。
本来是msn的space空间,但是Live Space没落了,所以转到了新浪的博客,但是更新也不太多
基础知识链接
阅读排行榜
评论排行榜

我要回帖

更多关于 hide android调用 的文章

 

随机推荐