☰
Dhizuku 设备所有者权限共享工具:架构原理、激活流程与 API 接入实践
2026/10/15 3:49:40 网站建设 项目流程
  • 移动开发

【免费下载链接】Dhizuku

A tool that can share DeviceOwner permissions to other application.

项目地址:https://gitcode.com/gh_mirrors/dh/Dhizuku
点击查看免费下载

Dhizuku 是一款借鉴 Shizuku 设计思想的开源 Android 工具,其核心能力是把系统的DeviceOwner(设备所有者)/ ProfileOwner(资料所有者)权限分享给其他应用,让普通应用也能调用DevicePolicyManager中仅限设备所有者使用的 API。本文以 docs/README.md 为骨架,结合仓库源码,系统讲解 Dhizuku 的权限共享架构、激活流程、权限校验机制,以及应用开发者如何通过 Dhizuku API 接入并获得设备所有者权限。

一、Dhizuku 是什么:从“单应用独占”到“多应用共享”

在 Android 系统中,DevicePolicyManager(以下简称 DPM)提供了一大批高级系统管理能力,例如静默安装/卸载应用、管理账号、设置密码复杂度、授予运行时权限等。但按照系统设计,只有被设置为Device Owner(设备所有者)或Profile Owner(资料所有者)的应用才能调用这些 API——这意味着这些能力默认被“独占”在单一系统级应用手中。

Dhizuku 的定位(见 docs/README.md)正是打破这种独占:参考 Shizuku 的设计思想,将 DeviceOwner 权限分享给其余应用。它本身先成为设备所有者,然后通过一套 Binder 服务与权限校验体系,把 DPM 能力以受控的方式“借给”第三方应用使用。与之相对,Shizuku 分享的是 ADB(shell 权限)能力,而 Dhizuku 分享的是设备所有者这一层更深的系统权限,两者互补但机制不同。

支持版本

根据 docs/README.md 的声明,Dhizuku 支持Android 8.0(API 26)~ Android 17(API 36)的系统版本,覆盖了从 Oreo 到最新一代 Android 的绝大多数设备。这一点在源码中也有印证:激活与权限相关代码同时兼容GET_SIGNING_CERTIFICATES(Android P 及以上)与旧版GET_SIGNATURES两套签名获取 API,并对 Android 14(UPSIDE_DOWN_CAKE)前后setDeviceOwner/setProfileOwner方法签名差异做了分支处理(见 ActivateViewModel.kt)。

二、核心架构:权限如何从系统流转到第三方应用

Dhizuku 的权限分享体系由四个核心组件协同完成,它们在 AndroidManifest.xml 中均有注册:

组件类职责
内容提供者MyDhizukuProvider对外暴露 Binder 服务入口,其他应用通过 authority 连接并创建服务实例
设备管理员接收器DhizukuDAReceiver接收设备所有者/资料所有者变更广播,触发状态同步
守护前台服务DaemonService常驻前台,监听应用安装/卸载变化,清理失效授权
权限服务实现MyDhizukuService承载 DPM 代理调用,并执行每次调用的权限校验

2.1 服务入口:ContentProvider 与 Binder

MyDhizukuProvider.kt 继承自DhizukuProvider,其onCreateService(client: IDhizukuClient)方法在第三方应用发起连接时创建MyDhizukuService实例,并把设备管理员组件(DhizukuState.admin)一并传入。该 Provider 在 Manifest 中声明了两个 authority:

<provider android:name=".server.MyDhizukuProvider" android:authorities="${applicationId}.dhizuku_server.provider;${applicationId}.server.provider" android:directBootAware="true" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="${applicationId}.server.provider" /> </intent-filter> </provider>

directBootAware="true"表示该组件在设备解锁前(Direct Boot 模式)也可访问,配合设备所有者场景下锁屏前即需执行管理任务的需求。此外 Manifest 还声明了自定义权限${applicationId}.permission.API(protectionLevel="dangerous"),用于约束访问 API 的应用范围。

2.2 状态中枢:DhizukuState 与 DAReceiver

DhizukuState.kt 是全局状态单例,维护三个关键信息:

  • isDeviceOwner:本应用是否为设备所有者;
  • isProfileOwner:本应用是否为资料所有者;
  • isOwner = isDeviceOwner || isProfileOwner:任一所有者身份成立即视为“已激活”;
  • admin:当前设备管理员组件ComponentName。

DhizukuDAReceiver.kt 继承自DeviceAdminReceiver,在收到DEVICE_ADMIN_ENABLED、DEVICE_OWNER_CHANGED、PROFILE_OWNER_CHANGED、PROFILE_PROVISIONING_COMPLETE等广播后,转交DaemonReceiver调用DhizukuState.sync(context)刷新状态。状态同步时如果确认已成为所有者,会自动执行两件事:

  1. 自动授予危险权限:grantPermissions()扫描自身 Manifest 中声明的所有危险权限(PROTECTION_DANGEROUS),通过dpm.setPermissionGrantState(admin, admin.packageName, it, PERMISSION_GRANT_STATE_GRANTED)以设备所有者身份强制授予,避免用户在激活后还需手动同意各类权限弹窗;
  2. 启动/停止守护服务:autoDaemonService()在成为所有者时启动DaemonService(含startForegroundService),失去所有者身份时停止。

DhizukuDAReceiver.onEnabled()还会根据isDeviceOwnerApp/isProfileOwnerApp的判断结果,弹出对应文案的 Toast 提示用户当前以哪种所有者身份被授予权限(见 DhizukuDAReceiver.kt)。

2.3 守护服务:授权记录的“体检器”

DaemonService.kt 是一个前台服务(foregroundServiceType="remoteMessaging",通知渠道daemon_service,ID 1001),除维持常驻外还承担授权数据治理职责:

  • 启动时遍历数据库中全部授权记录,删除所有未通过verify()校验的条目;
  • 注册ACTION_PACKAGE_REMOVED、ACTION_PACKAGE_FULLY_REMOVED、ACTION_PACKAGE_CHANGED广播(dataScheme="package"),在应用被卸载、更换时按 UID 找到记录并重新校验,校验失败即删除。

verify()的校验逻辑与后续服务端权限校验保持一致:要求allowApi == true、blocked == false,且当前安装包的签名与库中记录的签名一致(见 DaemonService.kt)。这保证了一旦应用被卸载重装(签名变化),旧的授权不会残留,避免权限被冒用。

三、激活教程:前置条件与两种激活路径

[!IMPORTANT] 官方文档(docs/README.md)强烈建议:在没有任何账户(Accounts)的设备上完成激活设置。如果设备已经登录过账号,可能需要先移除这些账号再启用 Dhizuku;设备上存在任何已配置账号时,官方可能无法提供支持。

之所以有这一限制,是因为 Android 系统规定:存在账号(尤其是 Device Owner 相关账号)时不允许设置设备所有者。这一约束同样体现在源码的失败分支中——通过 Shizuku 方式激活时,如果setDeviceOwner返回失败,会抛出异常提示 “Failed to set Device Owner. Please make sure there are no accounts on the device.”(见 ActivateViewModel.kt)。

激活的核心路径有两条,均由 ActivateViewModel.kt 实现:

3.1 路径一:通过 Shizuku / Sui 激活

这是日常使用最便捷的方式,前提是设备已运行 Shizuku(ADB 授权)或 Sui(ROOT 授权)。激活流程如下:

  1. collectData()扫描设备上所有声明了DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED且非系统应用(排除ApplicationInfo.FLAG_SYSTEM)的设备管理员组件,列出可激活目标;
  2. 用户选择目标后,以设备所有者或资料所有者身份执行激活:
    • activateAsDeviceOwnerByShizuku():通过反射调用 DPM 隐藏方法,先setActiveAdmin(who, true, userId)设置活动管理员,再setDeviceOwner(who, ownerName, userId)设置设备所有者;
    • activateAsProfileOwnerByShizuku():对应setProfileOwner(...)设置资料所有者;
  3. 由于系统账号缓存刷新存在延迟,激活前会delay(1500)等待 1.5 秒(源码注释 “wait for the account cache be refreshed”);
  4. 调用成功后执行DhizukuState.sync(context)刷新状态并自动授予危险权限、启动守护服务。

其中隐藏方法的调用通过requireBinderWrapperDevicePolicyManager()完成:它反射取出DevicePolicyManager中的mService字段(IDevicePolicyManagerBinder),用ShizukuBinderWrapper包装后重新注入,从而以 Shizuku 身份调用系统隐藏 API,调用结束后再将原 Binder 还原(见 ActivateViewModel.kt)。在界面层(ActivatePage.kt),选择“资料所有者”模式时会弹出警示对话框(profile_owner_warning),提示用户 Profile Owner 与 Device Owner 的权限差异。

3.2 路径二:通过 Android 设备预配(Provisioning)激活

对于未运行 Shizuku/Sui 的环境,Dhizuku 还实现了 Android 官方的设备预配(Device Provisioning)流程,对应 Manifest 中两个导出 Activity:

  • ProvisioningActivity.kt:响应android.app.action.GET_PROVISIONING_MODE,直接返回PROVISIONING_MODE_FULLY_MANAGED_DEVICE(完全托管设备模式)并setResult(RESULT_OK),即声明“本应用希望成为完全托管设备的所有者”;
  • FinalizeActivity.kt:响应android.app.action.ADMIN_POLICY_COMPLIANCE,作为预配完成后的收尾 Activity 直接返回成功。

这两个 Activity 在 Manifest 中均声明了android:permission="android.permission.BIND_DEVICE_ADMIN",确保只有系统预配流程才能拉起。使用这一路径时,设备需处于未初始化或可通过adb shell dpm类命令触发预配的状态,具体操作步骤官方在激活讨论帖中有详细图文指引。

3.3 激活后的自动处理链

无论走哪条路径,激活成功后都会触发同一套状态机(见 DhizukuState.kt):

isDeviceOwner/isProfileOwner 变为 true └─ grantPermissions():以所有者身份自动授予 Dhizuku 自身声明的全部危险权限 └─ autoDaemonService():启动 DaemonService 前台服务(常驻 + 授权记录治理) └─ DhizukuDAReceiver.onEnabled():Toast 提示 "已授予设备所有者/资料所有者权限"

四、权限校验机制:第三方应用如何安全获得授权

4.1 授权数据的持久化模型

Dhizuku 使用 Room 数据库(文件dhizuku.db,存放于设备保护存储区createDeviceProtectedStorageContext(),见 DhizukuRoom.kt)维护授权记录,实体 AppEntity.kt 的字段如下:

字段类型说明
idLong主键,自增
uidInt被授权应用的 UID,建有唯一索引
signatureString被授权应用的签名 SHA-256(十六进制大写),默认空串
allow_apiBoolean是否允许调用 Dhizuku API
blockedBoolean是否被拉黑(默认 false)
created_at/modified_atLong创建/修改时间戳

其中uid与allow_api分别建有索引,便于按 UID 查找和按授权状态筛选。数据库当前版本为 3,并通过 Room 的AutoMigration(from=1,to=2)、AutoMigration(from=2,to=3)声明了自动迁移(见 DhizukuRoom.kt)。

4.2 每次调用的四重校验

第三方应用通过 Binder 调用 API 时,服务端会执行MyDhizukuService.checkCallingPermission(func, callingUid, callingPid)进行鉴权(见 MyDhizukuService.kt),校验链依次为:

  1. 全局开关:settingsRepo.isDhizukuEnabled必须为 true(对应设置项dhizuku_enabled,默认开启,见 SettingsRepoImpl.kt);
  2. 存在授权记录:按调用方 UID 查库,findByUID(callingUid)必须命中;
  3. 启用且未拉黑:entity.allowApi == true且entity.blocked == false;
  4. 白名单模式:若settingsRepo.isWhitelistMode(设置项whitelist_mode,默认关闭)为 true,则仅允许allowApi的应用访问——即开启白名单后,未被授权的应用一律拒绝;
  5. 签名一致性:通过PackageManager读取调用方 UID 当前安装包的签名,计算 SHA-256 后与库中记录的signature比对,不一致则拒绝(签名获取见 PackageInfoUtil.kt)。

这套机制意味着:即使某个应用曾获得授权,如果它被卸载后以不同签名重装、被用户拉黑、或全局开关被关闭,都无法再调用 Dhizuku API——权限分享始终处于可审计、可撤销的状态。

4.3 授权交互:15 秒倒计时授权弹窗

第三方应用首次调用Dhizuku.requestPermission()时,会通过 Intent(action${applicationId}.action.request.permission,见 AndroidManifest.xml)拉起 RequestPermissionActivity.kt:

  • 弹窗展示请求应用的图标、名称与说明文案;
  • 内置15 秒倒计时(AUTO_DENY_SECONDS = 15),配合环形饼图进度动画提示剩余时间;超时未操作则自动拒绝(timedOut后finish());
  • 用户点击“同意/拒绝”后,结果写入 Room(appRepo.insert/update生成或更新AppEntity),并通过IDhizukuRequestPermissionListener回调把PERMISSION_GRANTED/PERMISSION_DENIED返回给请求方;
  • 若已开启白名单模式、全局开关关闭、或该应用已被拉黑,则弹窗直接跳过并返回拒绝。

4.4 应用管理:授权、拉黑与回收

应用管理界面由 AppManagementViewModel.kt 驱动,它会列出所有声明了 Dhizuku API 权限(DhizukuVariables.PERMISSION_API)或已有授权记录的应用,支持:

  • 启用授权:setEnabled(uid, true)写入/更新allowApi = true;
  • 拉黑:setBlocked(uid, true)写入blocked = true并强制allowApi = false。

当应用被取消授权或拉黑时,AppRepoImpl.kt 的update()/delete()还会调用clearDelegatedScopes():若 Dhizuku 仍保有所有者身份,则通过dpm.setDelegatedScopes(admin, packageName, emptyList())清空该应用此前被委托的设备管理作用域(delegated scopes),实现权限的彻底回收,防止残留的委托权限被继续使用。

五、开发者接入:使用 Dhizuku API 获取设备所有者能力

5.1 API 库与基础权限

面向应用开发者的接入方式是官方提供的Dhizuku API库(独立于本仓库的 AIDL/封装层,本仓库的app模块即该 API 的主要消费方)。接入步骤概述:

  1. 在应用 Manifest 中声明 Dhizuku 的 API 权限(权限名形如com.rosan.dhizuku.permission.API,由 Dhizuku 端定义,protectionLevel="dangerous",见 AndroidManifest.xml);
  2. 初始化并请求授权:Dhizuku.init()检查服务可用性,Dhizuku.isPermissionGranted()检查是否已授权,未授权时通过Dhizuku.requestPermission(listener)拉起授权弹窗——这一请求流程的封装见 DhizukuUtil.kt,其中requireDhizukuPermissionGranted采用callbackFlow以挂起函数形式等待授权结果,授权被拒或 Dhizuku 未激活时抛出DhizukuNotWorkException;
  3. 授权通过后,即可调用DevicePolicyManager中设备所有者专属的 API。

值得注意的是,仓库在 ShizukuUtil.kt 中提供了平行的requireShizukuPermissionGranted,说明Dhizuku 自身的激活能力同样依赖 Shizuku/Sui 权限——Dhizuku 与 Shizuku 是“依赖”而非“互斥”关系:Shizuku 负责把 ADB/ROOT 能力带给 Dhizuku,Dhizuku 再把它获得的 DeviceOwner 能力分享给普通应用。

5.2 一个完整的调用链路示例

以 Dhizuku 内部激活其他设备管理员组件为例(ActivateViewModel.kt),可以看到 API 的典型用法:

// 1. 确保 Dhizuku 已激活且已获得授权 requireDhizukuPermissionGranted { // 2. 通过 Dhizuku 包装 DevicePolicyManager 的 Binder requireBinderWrapperDevicePolicyManager(wrapper = { Dhizuku.binderWrapper(it) }) { // 3. 以设备所有者身份执行 transferOwnership(转移所有权) it.transferOwnership(Dhizuku.getOwnerComponent(), comp, null) } // 4. 刷新 Dhizuku 状态 DhizukuState.sync(context) }

即:第三方应用先向 Dhizuku 请求授权,Dhizuku 服务端通过checkCallingPermission完成鉴权后,把包装好的 DPM Binder 交给调用方,调用方即可在其上执行原本只有设备所有者能做的操作。服务端鉴权与客户端调用之间的对应关系,正是 MyDhizukuService.kt 中checkCallingPermission所承担的职责。

5.3 版本与兼容性说明

  • Dhizuku 自身声明支持 Android 8.0 ~ 17(见 docs/README.md);
  • 服务端通过getVersionName()暴露当前版本代码,客户端可据此判断 API 兼容性(见 MyDhizukuService.kt);
  • 授权记录按 UID + 签名双重绑定,应用签名变更后需重新授权。

六、翻译、捐赠与开源协议

  • 翻译:Dhizuku 的界面字符串支持数十种语言,仓库中每个语言目录对应一份strings.xml(如 values-zh-rCN/strings.xml、values-ja/strings.xml 等),社区可通过 Weblate 平台参与翻译与纠错(官方介绍见 docs/README.md);
  • 捐赠:项目支持社区捐赠,相关说明见 docs/DONATE.md 及简体中文版 docs/DONATE_zh_Hans.md;
  • 开源协议:Dhizuku 基于GNU General Public License v3(GPL-3)开源,并承诺未来持续以该协议开放,许可证全文见仓库根目录 LICENSE;
  • 配套文档:使用条款见 docs/TERMS.md,隐私政策见 docs/PRIVACY.md。

七、总结

Dhizuku 通过“自己成为设备所有者 + Binder 服务共享 + 签名/白名单双重鉴权 + 数据库授权治理”这一完整闭环,把 Android 系统中最深层的一类权限(DeviceOwner/ProfileOwner)安全地下放给普通应用。其核心设计要点可归纳为:

  1. 共享而非劫持:权限始终掌握在 Dhizuku 手中,第三方应用每次调用都经过checkCallingPermission鉴权;
  2. 可治理可撤销:授权记录持久化于 Room 数据库,支持白名单模式、拉黑、签名变更自动失效、以及setDelegatedScopes作用域回收;
  3. 激活路径多样:既可通过 Shizuku/Sui 便捷激活,也实现了 Android 官方设备预配流程(Provisioning),并针对 Android 各版本隐藏 API 差异做了兼容处理;
  4. 对开发者友好:通过 Dhizuku API,普通应用即可获得静默安装、账号管理等设备所有者能力,无需 ROOT 或刷机。

对于想要在自己的应用中获得系统级管理能力的开发者,Dhizuku 提供了一个经过实践检验、权限边界清晰的参考范式:以本仓库的 server 目录为服务端参考,以 data 目录的授权与设置模型为权限治理参考,即可完整理解并复用这套“设备所有者权限共享”方案。

  • 移动开发

【免费下载链接】Dhizuku

A tool that can share DeviceOwner permissions to other application.

项目地址:https://gitcode.com/gh_mirrors/dh/Dhizuku
点击查看免费下载

相关推荐

上一篇:Blue Laser Clean Glass Layout 技能演示指南:用 PROMPT 驱动的暗色玻璃仪表盘布局复刻实战
下一篇:OpenUI 生成式 UI 标准框架:OpenUI Lang、组件库驱动提示词与流式渲染实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询