昨天 App 終於跑起來了
今天先完成一個很樸實的功能:確認 Shizuku 到底有沒有活著
不用急著刪 App,先確認工具人有來上班
Shizuku 透過 ShizukuProvider 把 Binder 傳進我們的 App,所以 Manifest 要加:
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission
android:name="moe.shizuku.manager.permission.API_V23" />
<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" />
exported 要是 true,不然 Shizuku 進不來
multiprocess 要是 false,不然 Provider 到處分身,事情會開始變玄學
QUERY_ALL_PACKAGES 則是因為我們之後要看見手機裡所有 App
套件管理工具如果看不到套件,跟近視的驗光師差不多
最直接的方法是:
Shizuku.pingBinder()
回傳 true 代表服務有在跑,但還不代表已經授權
有來公司,不代表願意做事
先定義三種狀態:
sealed interface ShizukuState {
data object NotInstalled : ShizukuState
data object NotRunning : ShizukuState
data object Ready : ShizukuState
}
再包進 ShizukuManager:
class ShizukuManager(private val context: Context) {
private val _state =
MutableStateFlow<ShizukuState>(ShizukuState.NotRunning)
val state = _state.asStateFlow()
fun refresh() {
val alive = runCatching {
Shizuku.pingBinder()
}.getOrDefault(false)
_state.value = when {
alive -> ShizukuState.Ready
isInstalled() -> ShizukuState.NotRunning
else -> ShizukuState.NotInstalled
}
}
private fun isInstalled() = runCatching {
context.packageManager.getPackageInfo(
"moe.shizuku.privileged.api",
0
)
true
}.getOrDefault(false)
}
判斷時要先 pingBinder(),再檢查有沒有安裝 Shizuku
因為使用 Sui 的手機可能沒有 Shizuku App,但服務照樣活得很好
世界很複雜,不能只看戶口名簿
使用者可能切出去啟動 Shizuku,再回到我們的 App,所以記得:
override fun onResume() {
super.onResume()
container.shizuku.refresh()
}
不加這段,畫面會一直顯示「沒有執行」
然後使用者會覺得 App 壞了
通常他是對的,但這次不是
現在畫面已經能分辨 Shizuku 沒安裝、沒啟動或已就緒
明天再補授權和狀態監聽,讓它不要每次都要人類提醒才更新