Shizuku 集成终极指南:解决应用“隐身”与闪退问题

发布于 4 天前  13 次阅读


前言

在将 Shizuku 集成到应用的过程中,开发者常常会遇到两个令人头疼的问题:

  1. 应用在 Shizuku 的授权列表中不显示(“隐身”)
  2. 应用一打开就闪退

经过对 Shizuku 官方 demo、Hail、gkd 等多个成功项目的源码分析,我找到了问题的根本原因和可靠的解决方案。


核心原理

Shizuku 通过一个特殊的 ContentProvider(ShizukuProvider)来发现和管理授权应用。当你的应用启动时,这个 Provider 会被系统初始化,从而在 Shizuku Manager 中“注册”你的应用。

问题根源:ShizukuProvider 的配置和依赖如果处理不当,要么导致 Shizuku 找不到你的应用,要么导致应用因权限问题直接崩溃。


解决方案

第一步:添加正确的依赖

在 app/build.gradle 中同时添加以下两个依赖:dependencies { // Shizuku 核心 API implementation 'dev.rikka.shizuku:api:13.1.5' // Shizuku Provider(自动注册应用) implementation 'dev.rikka.shizuku:provider:13.1.5' }

关键点:api 和 provider 两个依赖缺一不可。只添加其中一个会导致编译错误或运行时功能异常。


第二步:配置 AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- ★ 关键:声明 Shizuku API 权限 --> <uses-permission android:name="moe.shizuku.manager.permission.API_V23" /> <!-- ★ 关键:声明系统级权限(Provider 需要) --> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <application android:name=".MyApplication" ...> <!-- ★ 关键:声明支持 Shizuku V3 API(必须使用 tools:replace 防止冲突) --> <meta-data android:name="moe.shizuku.client.V3_SUPPORT" android:value="true" tools:replace="android:value" /> <!-- ★ 关键:注册 ShizukuProvider(与官方 demo 完全一致) --> <provider android:name="rikka.shizuku.ShizukuProvider" android:authorities="${applicationId}.shizuku" android:enabled="true" android:exported="true" android:multiprocess="false" android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" /> </application> </manifest>

第三步:保持 MyApplication 简洁package com.example.myapplication import android.app.Application class MyApplication : Application() { override fun onCreate() { super.onCreate() // 无需任何手动初始化,provider 库会自动处理 } }

第四步:编写 ShizukuEngine(推荐方式:反射调用)

由于 IPackageManager 等为隐藏 API,推荐使用反射调用 Shizuku.newProcess() 执行 shell 命令,兼容性最佳。package com.example.myapplication.security.plugins.shizuku import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import rikka.shizuku.Shizuku import java.io.BufferedReader import java.io.InputStreamReader object ShizukuEngine { fun isAvailable(): Boolean { return try { Shizuku.pingBinder() } catch (e: Exception) { false } } fun hasPermission(): Boolean { return try { Shizuku.checkSelfPermission() == android.content.pm.PackageManager.PERMISSION_GRANTED } catch (e: Exception) { false } } fun requestPermission(requestCode: Int) { try { Shizuku.requestPermission(requestCode) } catch (e: Exception) { e.printStackTrace() } } suspend fun grantPermission(packageName: String, permission: String): String = withContext(Dispatchers.IO) { if (!isAvailable()) return@withContext "❌ Shizuku 服务未运行" if (!hasPermission()) return@withContext "❌ 尚未授权" try { val cmd = "pm grant $packageName $permission" val method = Shizuku::class.java.getDeclaredMethod( "newProcess", Array<String>::class.java, Array<String>::class.java, String::class.java ) method.isAccessible = true val process = method.invoke(null, arrayOf("sh", "-c", cmd), null, null) as Process val reader = BufferedReader(InputStreamReader(process.inputStream)) val errReader = BufferedReader(InputStreamReader(process.errorStream)) val out = reader.readText().trim() val err = errReader.readText().trim() process.waitFor() if (out.isEmpty() && err.isEmpty()) "✅ 权限已成功授予" else "结果:$out $err" } catch (e: Exception) { "❌ 执行失败:${e.message}" } } suspend fun grantTermuxPermission(packageName: String): String { return grantPermission(packageName, "com.termux.permission.RUN_COMMAND") } }


常见问题排查清单

问题 原因 解决方案
应用在授权列表中不显示 缺少 api 或 provider 依赖 确保两者都已添加
应用闪退 MetaData 冲突 添加 tools:replace="android:value"
编译时报 Shizuku 类找不到 只添加了 provider 没加 api 同时添加两个依赖
授权后功能仍不可用 使用了隐藏 API 导致编译失败 改用反射调用
列表时有时无 系统杀后台导致 Provider 被销毁 在 MyApplication 中动态初始化


总结

Shizuku 集成的关键在于三点:

  1. 同时添加 api 和 provider 依赖
  2. 正确配置 Manifest 中的 MetaData 和 Provider
  3. 使用反射调用隐藏 API 以避免编译问题

遵循本指南的配置,你的应用将能够稳定地出现在 Shizuku 授权列表中,并且不会出现闪退问题。