glasses: switch to rikka.shizuku.ShizukuProvider, fix binder acquisition
- Add dev.rikka.shizuku:provider:13.1.5 dependency. - Replace custom ShizukuInitProvider with rikka.shizuku.ShizukuProvider from the upstream library; configured per Shizuku v12+ docs with android:permission='android.permission.INTERACT_ACROSS_USERS_FULL' to protect the provider from ordinary apps. - Move ShizukuBootstrap.attach() from GlassesVmApp.onCreate to MainActivity.onCreate (requestPermission needs an Activity context). - MainActivity now overrides onRequestPermissionsResult and forwards the grant to ShizukuBootstrap. - Rewrite ShizukuBootstrap strictly per the Shizuku-API guide: addBinderReceivedListenerSticky + addRequestPermissionResultListener in attach(); pingBinder / checkSelfPermission / requestPermission in refresh(). - Drop ShizukuInitProvider.kt — its job is now done by rikka.shizuku.ShizukuProvider.onCreate (verified in logcat: 'ShizukuProvider: binder received'). Verified on device ARGF20 (A06B4AB933C4103, API 32): Shizuku dialog 'Allow rayneo-vm to use Shizuku?' opens correctly; binder received via ShizukuProvider; launcher icon now visible (meta-data fix).
This commit is contained in:
@@ -9,23 +9,30 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import pw.binom.rayneovm.glasses.protocol.VmGlassesController
|
||||
import pw.binom.rayneovm.glasses.ui.GlassesScreen
|
||||
import pw.binom.rayneovm.glasses.vm.GlassesScreenState
|
||||
|
||||
/**
|
||||
* Single-Activity приложения: Compose host для GlassesScreen.
|
||||
*
|
||||
* Никакой навигации — здесь один экран (зеркало гостевого приложения + state overlay).
|
||||
*/
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
// По доке Shizuku (https://github.com/RikkaApps/Shizuku-API): подписываемся на
|
||||
// listener-ы здесь, после super.onCreate, но ДО setContent. ShizukuProvider
|
||||
// (rikka.shizuku.ShizukuProvider в манифесте) уже инициализировал binder через
|
||||
// ContentProvider.onCreate — pingBinder() сразу вернёт true.
|
||||
ShizukuBootstrap.attach(this)
|
||||
val controller = VmGlassesController.fromContext(this)
|
||||
|
||||
setContent {
|
||||
CompositionLocalProvider(VmGlassesController.Local provides controller) {
|
||||
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||
@@ -34,10 +41,61 @@ class MainActivity : ComponentActivity() {
|
||||
.fillMaxSize()
|
||||
.background(Color.Black)
|
||||
) {
|
||||
GlassesScreen(controller = controller)
|
||||
val shizukuState by ShizukuBootstrap.state.collectAsState()
|
||||
val vmState by controller.state.collectAsState()
|
||||
DriveShizukuState(controller, shizukuState)
|
||||
GlassesScreen(
|
||||
controller = controller,
|
||||
onRequestShizukuPermission = { ShizukuBootstrap.refresh() },
|
||||
)
|
||||
// Как только VM ушёл в Running (запущен гость) — сворачиваем свой Activity,
|
||||
// чтобы SurfaceView гостя оказался поверх и был виден на очках.
|
||||
// Service продолжает жить в фоне (WebSocket/mDNS не рвутся).
|
||||
if (vmState is GlassesScreenState.Running) {
|
||||
(this as? ComponentActivity)?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
ShizukuBootstrap.refresh()
|
||||
}
|
||||
|
||||
/**
|
||||
* По доке Shizuku, мы должны вручную передать результат диалога в Shizuku -
|
||||
* иначе он не узнает, что пользователь нажал Allow.
|
||||
*/
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray,
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == ShizukuBootstrap.REQUEST_CODE_PERMISSION) {
|
||||
val grant = grantResults.firstOrNull() ?: -1
|
||||
ShizukuBootstrap.onRequestPermissionResult(requestCode, grant)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DriveShizukuState(controller: VmGlassesController, shizuku: ShizukuBootstrap.AllowState) {
|
||||
LaunchedEffect(shizuku) {
|
||||
when (shizuku) {
|
||||
ShizukuBootstrap.AllowState.NotRunning,
|
||||
ShizukuBootstrap.AllowState.Waiting,
|
||||
ShizukuBootstrap.AllowState.NeedsPermission -> {
|
||||
controller.setState(GlassesScreenState.ShizukuMissing)
|
||||
}
|
||||
ShizukuBootstrap.AllowState.Granted -> {
|
||||
if (controller.state.value is GlassesScreenState.ShizukuMissing) {
|
||||
controller.setState(GlassesScreenState.NoAppSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user