mirror of
https://github.com/whyorean/AuroraStore.git
synced 2026-06-12 01:38:35 -04:00
Enable microG Installer and add microG installer prerequisite dialog
Partially addresses: #1485 Show the microG installer whenever the companion app is present instead of relying on the misleading vending_apps_install metadata flag, and warn users to enable it from microG settings before use. The dialog also offers a shortcut to open microG settings. microG only exposes the top-level settings activity; the App Installer Settings screen is a Navigation fragment with no deep link, so the dialog guides users through the remaining steps.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Aurora OSS
|
||||
* SPDX-FileCopyrightText: 2026 The Calyx Institute
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.aurora.store.compose.ui.commons
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewWrapper
|
||||
import com.aurora.Constants.PACKAGE_NAME_GMS
|
||||
import com.aurora.extensions.TAG
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.compose.preview.ThemePreviewProvider
|
||||
|
||||
private const val MICROG_SETTINGS_ACTIVITY = "org.microg.gms.ui.SettingsActivity"
|
||||
|
||||
/**
|
||||
* Dialog informing users about the prerequisite for using the microG installer
|
||||
* @param onConfirm Callback on confirmation
|
||||
* @param onDismiss Callback on dismissal
|
||||
*/
|
||||
@Composable
|
||||
fun MicroGInstallerPrerequisiteDialog(onConfirm: () -> Unit = {}, onDismiss: () -> Unit = {}) {
|
||||
val context = LocalContext.current
|
||||
|
||||
AlertDialog(
|
||||
title = { Text(text = stringResource(R.string.microg_installer_prerequisite_title)) },
|
||||
text = {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
dimensionResource(R.dimen.spacing_small)
|
||||
)
|
||||
) {
|
||||
Text(text = stringResource(R.string.microg_installer_prerequisite_desc))
|
||||
OutlinedButton (
|
||||
onClick = {
|
||||
try {
|
||||
context.startActivity(
|
||||
Intent().apply {
|
||||
component = ComponentName(
|
||||
PACKAGE_NAME_GMS,
|
||||
MICROG_SETTINGS_ACTIVITY
|
||||
)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
)
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
Log.i(TAG, "Unable to launch microG settings")
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(text = stringResource(R.string.microg_installer_open_settings))
|
||||
}
|
||||
}
|
||||
},
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = {
|
||||
TextButton(onClick = onConfirm) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewWrapper(ThemePreviewProvider::class)
|
||||
@Preview
|
||||
@Composable
|
||||
private fun MicroGInstallerPrerequisiteDialogPreview() {
|
||||
MicroGInstallerPrerequisiteDialog()
|
||||
}
|
||||
@@ -15,7 +15,9 @@ import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
@@ -28,6 +30,7 @@ import com.aurora.store.R
|
||||
import com.aurora.store.compose.composable.InstallerListItem
|
||||
import com.aurora.store.compose.composable.TopAppBar
|
||||
import com.aurora.store.compose.preview.ThemePreviewProvider
|
||||
import com.aurora.store.compose.ui.commons.MicroGInstallerPrerequisiteDialog
|
||||
import com.aurora.store.data.installer.AppInstaller
|
||||
import com.aurora.store.data.installer.SessionInstaller
|
||||
import com.aurora.store.data.model.Installer
|
||||
@@ -61,6 +64,17 @@ private fun ScreenContent(
|
||||
onInstallerSelected: (installer: Installer) -> Unit = {}
|
||||
) {
|
||||
val snackBarHostState = remember { snackBarHostState }
|
||||
var showMicroGPrerequisite by remember { mutableStateOf(false) }
|
||||
|
||||
if (showMicroGPrerequisite) {
|
||||
MicroGInstallerPrerequisiteDialog(
|
||||
onConfirm = {
|
||||
showMicroGPrerequisite = false
|
||||
onInstallerSelected(Installer.MICROG)
|
||||
},
|
||||
onDismiss = { showMicroGPrerequisite = false }
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
snackbarHost = {
|
||||
@@ -82,7 +96,13 @@ private fun ScreenContent(
|
||||
InstallerListItem(
|
||||
installerInfo = installerInfo,
|
||||
isSelected = installerInfo.installer == currentInstaller,
|
||||
onClick = { onInstallerSelected(installerInfo.installer) }
|
||||
onClick = {
|
||||
if (installerInfo.installer == Installer.MICROG) {
|
||||
showMicroGPrerequisite = true
|
||||
} else {
|
||||
onInstallerSelected(installerInfo.installer)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.aurora.store.data.installer.base.IInstaller
|
||||
import com.aurora.store.data.model.Installer
|
||||
import com.aurora.store.data.model.InstallerInfo
|
||||
import com.aurora.store.util.PackageUtil
|
||||
import com.aurora.store.util.PackageUtil.hasMicroGCompanion
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -83,7 +84,7 @@ class AppInstaller @Inject constructor(
|
||||
if (hasAuroraService(context)) ServiceInstaller.installerInfo else null,
|
||||
if (hasAppManager(context)) AMInstaller.installerInfo else null,
|
||||
if (hasShizukuOrSui(context)) ShizukuInstaller.installerInfo else null,
|
||||
if (hasMicroGInstaller(context)) MicroGInstaller.installerInfo else null
|
||||
if (hasMicroGCompanion(context)) MicroGInstaller.installerInfo else null
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -154,6 +155,7 @@ class AppInstaller @Inject constructor(
|
||||
false
|
||||
}
|
||||
|
||||
// TODO: Use microG's proposed API instead of relying on a hardcoded metadata flag that can be misleading (e.g. user can enable the installer from UI)
|
||||
fun hasMicroGInstaller(context: Context): Boolean {
|
||||
if (!PackageUtil.hasMicroGCompanion(context)) return false
|
||||
return try {
|
||||
@@ -236,7 +238,7 @@ class AppInstaller @Inject constructor(
|
||||
defaultInstaller
|
||||
}
|
||||
|
||||
Installer.MICROG -> if (hasMicroGInstaller(context)) {
|
||||
Installer.MICROG -> if (hasMicroGCompanion(context)) {
|
||||
microGInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.aurora.store.data.installer.base.InstallerBase
|
||||
import com.aurora.store.data.model.Installer
|
||||
import com.aurora.store.data.model.InstallerInfo
|
||||
import com.aurora.store.data.room.download.Download
|
||||
import com.aurora.store.util.PackageUtil.hasMicroGCompanion
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@@ -68,7 +69,7 @@ class MicroGInstaller @Inject constructor(
|
||||
Log.i(TAG, "${download.packageName} already queued")
|
||||
}
|
||||
|
||||
AppInstaller.hasMicroGInstaller(context) -> {
|
||||
hasMicroGCompanion(context) -> {
|
||||
Log.i(TAG, "Received microG install request for ${download.packageName}")
|
||||
|
||||
val files = getFiles(download.packageName, download.versionCode)
|
||||
|
||||
@@ -469,6 +469,9 @@
|
||||
<string name="microg_removed_auth_warning">microG is no longer installed. Run setup again to keep things working smoothly.</string>
|
||||
<string name="microg_installer_subtitle">Requires microG companion app to be installed</string>
|
||||
<string name="microg_installer_desc">Helps you bypass App Integrity (installer only) check</string>
|
||||
<string name="microg_installer_prerequisite_title" translatable="false">Enable microG installer</string>
|
||||
<string name="microg_installer_prerequisite_desc" translatable="false">Before using the microG installer, please ensure you have enabled it.\n\nPlay Store services → ⋮ → App Installer Settings → Allow App Installation</string>
|
||||
<string name="microg_installer_open_settings" translatable="false">Open microG settings</string>
|
||||
<string name="am_installer_subtitle">Full-featured open source package manager</string>
|
||||
<string name="am_installer_desc">Requires App Manager, need adb/root mode to install when miui optimization is on</string>
|
||||
<string name="shizuku_installer_subtitle">Using system APIs directly with adb/root privileges</string>
|
||||
|
||||
Reference in New Issue
Block a user