1. 背景
1.1 Android隐藏API是什么
Android 系统中存在大量隐藏 API(Hidden API),这些 API 被标记为 @hide,意味着它们不在官方 SDK 中公开。
简单来说:这些接口是系统内部自己用的,不是给第三方 App 开发者调用的,官方也不会保证你调用后能在不同设备 / 版本上正常工作。
1.2 Android 官方为什么要隐藏API
- 稳定性考虑 : 隐藏 API 可能在不同 Android 版本之间发生变化,Google 不希望第三方应用依赖这些不稳定的接口
- 安全性考虑:某些 API 涉及系统底层操作,不当使用可能导致安全问题
- 兼容性考虑:隐藏 API 的行为可能因设备厂商定制而异
- 内部实现细节:某些 API 是 Android 内部实现的一部分,不适合外部使用
1.3 隐藏 API 的典型使用场景
尽管存在风险,但在某些特定场景下(如系统应用、车载应用、IoT 设备等),我们仍然需要调用这些隐藏 API:
kotlin
//调用 PowerManager.wakeUp() 唤醒屏幕
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
if (powerManager.isInteractive.not()) {
powerManager.wakeUp(
SystemClock.uptimeMillis(),
"com.zeekr.flexiscreen.launcher:systemdialog"
)
}
//调用 WifiManager.connect() 连接 WiFi
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
wifiManager.connect(
WifiConfiguration(), object : WifiManager.ActionListener {
override fun onSuccess() {
Log.i(TAG,"onSuccess")
}
override fun onFailure(reason: Int) {
Log.i(TAG,"onFailure")
}
})
但是直接调用隐藏API会报错 :
file:///D:/WorkSpace/Test/FrameApiTest/app/src/main/java/com/example/frameapitest/MainActivity.kt:27:26 Unresolved reference 'wakeUp'.
那么需要怎么办呢 ?
2. 原本可行的方案
原本的Android Studio中,存在可行的方案,我们先来回顾下 :
2.1 步骤一 : 复制framework.jar到app/libs目录下
官方给开发者的android.jar(SDK 目录下)是阉割版 ------ 移除了@hide标记的隐藏 API;
而framework.jar是包含完整 Android 框架层接口(公开 + 隐藏 API)的 jar 包,是调用隐藏 API 的核心依赖。
有三种方式可以获取到framework.jar
- 从已 Root 的设备 / 模拟器中提取
- 从 Android 源码编译生成
- 使用第三方现成包,比如github上有现成已经编译好的framework.jar : aosp-android-jar
2.2 步骤二 : 引入 framework.jar
使用 compileOnly 来引入 framework.jar
kotlin
dependencies {
compileOnly(files("libs/framework.jar"))
// 其他依赖...
}
注意,这里要用
compileOnly而不是implementation,否则会报错 :com.android.tools.r8.internal.wx: Absent Code attribute in method that is not native or abstract
2.3 步骤三 : 增加gradle配置
这一步骤的作用是 将你本地的framework.jar(包含隐藏 API)优先加入到 编译器的引导类路径中,让编译器优先使用这个完整的framework.jar,而非官方 SDK 中被阉割的android.jar。
2.1 方案一
在app模块的build.gradle中增加如下配置 :
kotlin
gradle.projectsEvaluated {
tasks.withType<JavaCompile> {
if (options.bootstrapClasspath == null) {
options.bootstrapClasspath = files("libs/framework.jar")
} else {
val fileSet = options.bootstrapClasspath!!.files
val newFileList = mutableListOf<File>()
newFileList.add(File("libs/framework.jar"))
newFileList.addAll(fileSet)
options.bootstrapClasspath = files(*newFileList.toTypedArray())
}
}
}
2.2 方案二
在app模块的build.gradle中增加如下配置 :
kotlin
gradle.projectsEvaluated {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
// 使用新的 compilerOptions DSL
compilerOptions {
val frameworkJar = file("libs/framework.jar")
// 使用 add 方法添加编译参数
freeCompilerArgs.add("-Xbootclasspath/p:${frameworkJar.absolutePath}")
}
}
}
2.3 方案三
在app模块的build.gradle中增加如下配置 :
kotlin
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
compilerOptions {
val frameworkJar = project.file("libs/framework.jar")
freeCompilerArgs.add("-Xbootclasspath/p:${frameworkJar.absolutePath}")
}
}
3. 新版Android Studio中失效
我使用的是Android Studio Otter 3 Feature Drop | 2025.2.3,使用的kotlin版本是2.2.21,agp版本是9.0.1,在此版本中新建项目,依赖framework.jar,上述配置会失效。
例如,在使用方案二的时候,会提示 :
kotlin
w: Flag is not supported by this version of the compiler: -Xbootclasspath/p:D:\WorkSpace\Test\FrameApiTest\app\libs\framework.jar
e: file:///D:/WorkSpace/Test/FrameApiTest/app/src/main/java/com/example/frameapitest/MainActivity.kt:27:26 Unresolved reference 'wakeUp'.
e: file:///D:/WorkSpace/Test/FrameApiTest/app/src/main/java/com/example/frameapitest/MainActivity.kt:34:21 Unresolved reference 'connect'.
原因是由于 Kotlin 编译器在较新版本中已不再支持 -Xbootclasspath/p 参数,因此导致了 Flag is not supported 的警告,并且因为 framework.jar 未能正确优先加载,导致了 Unresolved reference 错误。
故需修改 app/build.gradle.kts 配置。移除了不被支持的 -Xbootclasspath/p 参数,改为通过调整 KotlinCompile 任务的 libraries (classpath)顺序来确保 framework.jar 优先于 android.jar 加载,从而能够正确访问隐藏 API。
4. 新版解决方案
还是按照 2. 原本可行的方案 中的步骤一到步骤二进行操作,
区别在于步骤三 : 在app模块的build.gradle中增加如下配置 :
kotlin
gradle.projectsEvaluated {
/**tasks.withType<JavaCompile>().configureEach {
val frameworkJar = file("libs/framework.jar")
val bootstrapClasspath = options.bootstrapClasspath?.files?.toMutableList() ?: mutableListOf()
bootstrapClasspath.add(0, frameworkJar)
options.bootstrapClasspath = files(bootstrapClasspath)
}**/
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
val frameworkJar = file("libs/framework.jar")
// 将 framework.jar 添加到 libraries (classpath) 的最前面
libraries.setFrom(files(frameworkJar) + libraries)
}
}
再次运行项目,可以发现powerManager.wakeUp和wifiManager.connect这种隐藏API就不再报错了,能够正常运行了。