内部API和隐藏代码的例子
在翻阅Android源码的时候有时会遇到一些奇怪的代码,例如下面这个:
//注:这段代码在源码android/provider/Telephony.java中。 import android.util.Patterns; import com.android.internal.telephony.SmsApplication; import java.util.HashSet; //……
还有这种(下面这段摘自同一文件):
/** * //comments... * @hide */ public static boolean isOutgoingFolder(int messageType) { //method body... }
这些代码是什么意思呢?
内部API:android.internal.*
实际上,在SDK的source目录,是找不到所谓android.internal包的。该包下的所有类的源码都是不可见的,仅供系统内部使用。一般而言,在这个包下的都是Android系统核心功能,不对外开放接口和源码。
隐藏代码:@hide
与内部API不同,使用@hide标记的一般并非整个文件或外部类,而一般是内部类、函数或字段,姑且笼统称其为隐藏代码(我个人认为不对外开放的代码不应该叫做Application Programming Interface)。这些隐藏代码在源码中可见,但并不能直接引用。
内部API和隐藏API的不同
从Google的目的看,使用两种不同的方式,是有自己的考虑的,内部API属于系统核心部分,不计划对外开放。系统的核心功能会通过Framework提供一定的访问,但并不需要公布其代码。
而隐藏API则更多是为了考虑Android不同版本间的安全性。很有可能一个正在开发的、并不稳定的Feature被隐藏,直到稳定、成熟后再开放。Android在API Level5之后才出现Bluetooth API,但实际上更早的源码中就已经有这部分代码,只不过被@hide隐藏起来了。可以想见,如果某个应用程序依赖于API 4的Bluetooth API,很有可能在Android2.0(API Level5)的机器上出现不可预料的问题。
当然,内部代码也有可能发生这样的变动,但由于它本身对开发者来说就是个黑盒子,因此它内部的变动我们大可放心交给Google啦。
开发者眼中的不同
目前一般Android开发者使用Eclispe ADT插件进行开发,对于一般的开发者来说,内部API和隐藏代码没什么区别,都没法用嘛。不过,总有那么一些人出于各种目的,希望使用这些API。
在开发的时候我们使用最多的库就是android.jar包,该包下有我们用的几乎所有功能【不排除会使用到android-support-v4.jar】。在该jar包中,我们可以看到,所有的android.internal内的类都不见了,同样,类中也不含有源码中标记为@hide的字段、函数和类。
但是在应用程序真正在设备上运行的时候,系统加载的是framework.jar包,该包未被裁剪,包含所有内部API和隐藏代码。因此开发者可以通过反射机制进行调用。
此外,在使用Eclipse ADT 的时候,ADT插件专门对android.internal包做了访问规则限制。因此,即使将项目下的android.jar替换成未裁剪的android.jar包,也是很难使用内部API的。
不推荐使用内部API和隐藏代码
如前所述,理论上,开发者尽可以使用反射机制进行对这些功能的调用。但是,必须面对以下问题:
- 使用这样的功能会使程序的代码变得晦涩难懂,难于维护;
- 不同厂家的Framework包可能略有差别,难以兼顾多种设备;
- Android版本升级后,其内部功能或者隐藏代码可能发生较大的变化,因此使用了这些代码的程序无法确保向后兼容。
参考资料:使用内部(com.android.internal)和隐藏(@hide)API[第1部分,介绍]
Android 内部API (com.android.internal)和隐藏API(@hide)概述