一、android.jar包
android.jar是我们Android应用开发包,它内部包含了我们在应用开发中需要使用的所有API调用。
二、显式使用 Android 隐藏 API 和内部 API
在进行Android应用开发的时候,一般会选择指定的编译版本,选择编译版本之后,我们的项目就会使用我们SDK目录中对应版本的android.jar(sdk/platforms/android-version/android.jar)进行开发,如下图。
但是有一个问题,Android 有两种类型的 API 不能通过 SDK 访问。
(1)com.android.internal 包中的 API,称之为 internal API。
(2)被标记为 @hide 属性的类和方法,这是被隐藏的 API,称之为 hidden API。
1、为什么这两种类型的API不能通过SDK来进行访问?
原因很简单,就是sdk/platforms/android-version/android.jar被进行了处理,在这个jar中,默认移除了所有的被@hide
标识的方法或者类,以及internal包下的类。所以我们在开发的时候这两种类型的API无法被访问到。
2、为什么我们进行反射就能够调用这些类和方法呢?
在我们的Android设备上,使用的并不是跟我们SDK中相同的jar包,仔细想想,如果设备上也是使用这个jar包,那么这两种类型的API既然被移除了,就说明它根本就不存在,就算是反射也没法调用一个根本不存在的方法呀。
真正的原因是当应用在设备上运行时,它会加载 /system/framework/framework.jar ,framework.jar 和 android.jar的唯一的区别就是它没有移除 internal API 和 hidden API,这就说明了为什么我们可以通过反射调用,因为我们开发的SDK中不包含这些API,所以我们无法进行显式的调用,当我们利用反射,程序在设备上运行的时候,其实是可以找到对应的方法进行调用的。
3、也就是说系统有意屏蔽了一些类和方法在我们应用开发的时候不让我们进行使用,但是这些类和方法是确实存在的,如果我们不想通过反射来进行调用,我们该如何处理呢?
方法也很简单,把我们sdk/platforms/android-version/android.jar这个jar替换成framework.jar就可以了(这里需要将framework.jar的名字更改成android.jar,然后替换上面sdk中的android.jar),这样使用包含了隐藏API的jar包进行开发,肯定就可以显式的调用这些方法了。
这里其实也解释了为什么sdk中的隐藏方法不能被显式调用,只能通过反射调用,这是如何做到的,之前感觉很神奇,现在是不是豁然开朗了。
前面说了,如果希望显式的调用隐藏API,需要从android设备中提取/system/framework/framework.jar,把它的名字修改为android.jar,然后将sdk/platforms/android-version/android.jar中的jar进行替换,这样做无非就是希望sdk使用的是没有移除 internal API 和 hidden API的jar包。要想得到完整的android.jar其实并不用那么麻烦,已经有人帮助我们在做这样的事情了.
https://github.com/anggrayudi/android-hidden-api
上面这个开源项目已经包含了所有版本的完整的android.jar,我们只需要将其替换sdk/platforms/android-version/android.jar就可以了。
具体的做法这个项目的说明也介绍的很清楚,这里直接粘贴过来。
If you also want to include the internal classes or methods, do the following:
Go to /platforms/.
Copy, paste and replace the downloaded hidden API file into this directory, e.g. android-25/android.jar.
Change compileSdkVersion and targetSdkVersion to 25 (for example).
Finally, rebuild your project.
三、使用Android内部资源
https://github.com/anggrayudi/android-hidden-api
这个项目也包含一个Android内部资源访问的工具包,可以让你轻松的复用到Android内部的所有的Android资源,包含字符串、尺寸和颜色等等。
使用方法:
1、项目引入
dependencies {
compile 'com.anggrayudi:android-hidden-api:0.0.7'
}
repositories {
maven { url 'https://dl.bintray.com/anggrayudi/maven/' }
// Or, you can use jCenter instead
jcenter()
}
2、资源复用
import com.anggrayudi.hiddenapi.r.Rc;
String accept = InternalAccessor.getString(Rc.string.accept);
float sbar_height = InternalAccessor.getDimension(Rc.dimen.status_bar_height);
int notif_color = InternalAccessor.getColor("config_defaultNotificationColor");
参考文章:
Android 轻松的查看与使用hide与internal API
怎样查看并且使用 Android 隐藏 API 和内部 API
https://github.com/anggrayudi/android-hidden-api