写 Android 应用时,有些系统 API 需要 Shell 或 Root 权限才能调用,一般可以通过 Shizuku 来实现
但是用户需要先安装 Shizuku ,启动服务,再给你的应用授权。原版 Shizuku 实际上已经停止维护,issue 区也被垃圾机器人灌满了,各种 fork 的维护和适配情况又不一样。开发者除了维护自己的应用,还得帮用户处理装哪个版本、哪个版本能正常工作的问题
如果只是为了使用自己应用里的一个功能,还要额外折腾这些,就比较麻烦。因此可以把这部分能力直接放进自己的应用,让用户无需额外安装 Shizuku
下面介绍三个可以配合使用的项目,目前 GKD 都在使用,有类似需求的开发者可以参考
Priv Kit
Priv Kit 可以理解为一个嵌入式的 Shizuku ,集成后应用可以自行启动和管理特权进程
支持通过 ADB 、Root 、Shell 命令启动,也可以接入 Shizuku 等外部授权服务。如果用户已经安装并启动了 Shizuku ,可以在授权后通过它启动应用自己的特权进程
ADB 启动后使用 Shell 权限,Root 启动后使用 Root 权限,从而调用普通应用无权访问的系统 API
相比 shizuku-api ,它已经内置了文件操作、命令执行、模拟点击和滑动等功能,不需要自己再封装一遍
需要实现其他功能时,也可以通过 Binder 调用系统接口,或者把需要特权的代码放进自定义 UserService 中运行,再由应用调用
remap
有了特权进程,还会遇到另一个问题:很多系统接口不在公开 SDK 里,代码中无法直接引用
我注意到 GitHub 上很多项目还在大量使用反射调用隐藏 API ,手动查找类、方法和字段,再传入参数调用。其实这部分有更方便的方案,可以像调用普通方法一样写代码,也能有 IDE 补全和编译期类型检查
remap 是基于 HiddenApiRefinePlugin 改进的 Gradle 插件。先声明需要的隐藏类型和方法,业务代码就可以正常引用,编译时再把这些引用转换成实际的系统类型和方法,不用到处写反射
它支持普通 Android 模块,也适配了 KMP 的 Android target ,并且可以自动生成相关的 R8 规则,库模块的规则可以随 AAR 一起提供给使用方
隐藏 API 还有一个比较容易遇到的问题,就是 Debug 正常,开启 R8 后的 Release 却出错,尤其是实现了系统隐藏接口或回调的情况
项目里也提供了 android-hidden-api-r8 skill ,使用 AI 写代码时可以配合使用,让它检查这些声明和回调经过 R8 优化后是否还能正常工作
android-api-diff
隐藏 API 会随着 Android 版本变化,同一个方法可能增加参数、修改参数类型,或者换了返回类型。有些变化甚至发生在 API level 相同的系统版本之间,只判断 SDK_INT 也不够
如果只照着一个版本的源码写,换个系统就可能调用失败,但是每次手动翻各个版本的 AOSP 源码又比较麻烦
android-api-diff 可以查询 Java/AIDL 类型和成员在不同 Android 版本中的变化,包括方法签名、存在范围和对应源码,方便按实际差异编写兼容代码
除了网页查询,也提供 CLI 和配套 skill ,可以让 AI 在写代码前先查询接口变化,并生成隐藏 API 访问声明,减少凭印象写错接口的情况