use microGInstaller if available & minor ui state fix

This commit is contained in:
Rahul Patel
2025-12-24 15:09:23 +05:30
parent dd7f495e26
commit 434d285732
10 changed files with 83 additions and 31 deletions

View File

@@ -2,11 +2,11 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 5, "version": 5,
"identityHash": "d5da6e54113409ba811bafebc85632e6", "identityHash": "82935f33f6fe476bd752dd3643095d69",
"entities": [ "entities": [
{ {
"tableName": "download", "tableName": "download",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `offerType` INTEGER NOT NULL, `isInstalled` INTEGER NOT NULL, `displayName` TEXT NOT NULL, `iconURL` TEXT NOT NULL, `size` INTEGER NOT NULL, `id` INTEGER NOT NULL, `downloadStatus` TEXT NOT NULL, `progress` INTEGER NOT NULL, `speed` INTEGER NOT NULL, `timeRemaining` INTEGER NOT NULL, `totalFiles` INTEGER NOT NULL, `downloadedFiles` INTEGER NOT NULL, `fileList` TEXT NOT NULL, `sharedLibs` TEXT NOT NULL, `targetSdk` INTEGER NOT NULL, `downloadedAt` INTEGER NOT NULL, PRIMARY KEY(`packageName`))", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `offerType` INTEGER NOT NULL, `isInstalled` INTEGER NOT NULL, `displayName` TEXT NOT NULL, `iconURL` TEXT NOT NULL, `size` INTEGER NOT NULL, `id` INTEGER NOT NULL, `downloadStatus` TEXT NOT NULL, `progress` INTEGER NOT NULL, `speed` INTEGER NOT NULL, `timeRemaining` INTEGER NOT NULL, `totalFiles` INTEGER NOT NULL, `downloadedFiles` INTEGER NOT NULL, `fileList` TEXT NOT NULL, `sharedLibs` TEXT NOT NULL, `targetSdk` INTEGER NOT NULL, `downloadedAt` INTEGER NOT NULL, `requiresGMS` INTEGER NOT NULL, PRIMARY KEY(`packageName`))",
"fields": [ "fields": [
{ {
"fieldPath": "packageName", "fieldPath": "packageName",
@@ -57,7 +57,7 @@
"notNull": true "notNull": true
}, },
{ {
"fieldPath": "downloadStatus", "fieldPath": "status",
"columnName": "downloadStatus", "columnName": "downloadStatus",
"affinity": "TEXT", "affinity": "TEXT",
"notNull": true "notNull": true
@@ -115,6 +115,12 @@
"columnName": "downloadedAt", "columnName": "downloadedAt",
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": true "notNull": true
},
{
"fieldPath": "requiresGMS",
"columnName": "requiresGMS",
"affinity": "INTEGER",
"notNull": true
} }
], ],
"primaryKey": { "primaryKey": {
@@ -122,9 +128,7 @@
"columnNames": [ "columnNames": [
"packageName" "packageName"
] ]
}, }
"indices": [],
"foreignKeys": []
}, },
{ {
"tableName": "favourite", "tableName": "favourite",
@@ -166,9 +170,7 @@
"columnNames": [ "columnNames": [
"packageName" "packageName"
] ]
}, }
"indices": [],
"foreignKeys": []
}, },
{ {
"tableName": "update", "tableName": "update",
@@ -270,15 +272,12 @@
"columnNames": [ "columnNames": [
"packageName" "packageName"
] ]
}, }
"indices": [],
"foreignKeys": []
} }
], ],
"views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd5da6e54113409ba811bafebc85632e6')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '82935f33f6fe476bd752dd3643095d69')"
] ]
} }
} }

View File

@@ -69,4 +69,9 @@ object Constants {
const val PACKAGE_NAME_GMS = "com.google.android.gms" const val PACKAGE_NAME_GMS = "com.google.android.gms"
const val PACKAGE_NAME_PLAY_STORE = "com.android.vending" const val PACKAGE_NAME_PLAY_STORE = "com.android.vending"
const val PACKAGE_NAME_APP_GALLERY = "com.huawei.appmarket" const val PACKAGE_NAME_APP_GALLERY = "com.huawei.appmarket"
// FLAVOURS
const val FLAVOUR_VANILLA = "vanilla"
const val FLAVOUR_HUAWEI = "huawei"
const val FLAVOUR_PRELOAD = "preload"
} }

View File

@@ -492,7 +492,7 @@ private fun ScreenContentApp(
is ExtraScreen.MicroG -> MicroGScreen( is ExtraScreen.MicroG -> MicroGScreen(
packageName = app.packageName, packageName = app.packageName,
onNavigateUp = ::onNavigateBack, onNavigateUp = ::onNavigateBack,
onIgnore = { onInstall(ignoreMicroG = true) } onIgnore = { onInstall(ignoreMicroG = it) }
) )
is Screen.DevProfile -> DevProfileScreen( is Screen.DevProfile -> DevProfileScreen(

View File

@@ -49,7 +49,7 @@ import com.aurora.store.viewmodel.onboarding.MicroGViewModel
fun MicroGScreen( fun MicroGScreen(
packageName: String, packageName: String,
onNavigateUp: () -> Unit, onNavigateUp: () -> Unit,
onIgnore: () -> Unit, onIgnore: (Boolean) -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName), appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
viewModel: MicroGViewModel = hiltViewModel(), viewModel: MicroGViewModel = hiltViewModel(),
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo() windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
@@ -57,7 +57,7 @@ fun MicroGScreen(
val app by appDetailsViewModel.app.collectAsStateWithLifecycle() val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val topAppBarTitle = when { val topAppBarTitle = when {
windowAdaptiveInfo.isWindowCompact -> app!!.displayName windowAdaptiveInfo.isWindowCompact -> app!!.displayName
else -> stringResource(R.string.onboarding_title_gsf) else -> stringResource(R.string.onboarding_title_gsf)
} }
ScreenContent( ScreenContent(
@@ -75,7 +75,7 @@ private fun ScreenContent(
uiState: MicroGUIState = MicroGUIState(), uiState: MicroGUIState = MicroGUIState(),
onNavigateUp: () -> Unit = {}, onNavigateUp: () -> Unit = {},
onInstall: () -> Unit = {}, onInstall: () -> Unit = {},
onIgnore: () -> Unit = {}, onIgnore: (Boolean) -> Unit = {},
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo() windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -101,7 +101,10 @@ private fun ScreenContent(
modifier = Modifier.weight(1F), modifier = Modifier.weight(1F),
onInstall = { onInstall = {
when { when {
PermissionProvider.isGranted(context, PermissionType.INSTALL_UNKNOWN_APPS) -> { PermissionProvider.isGranted(
context,
PermissionType.INSTALL_UNKNOWN_APPS
) -> {
onInstall() onInstall()
} }
@@ -128,10 +131,14 @@ private fun ScreenContent(
Button( Button(
modifier = Modifier.weight(1F), modifier = Modifier.weight(1F),
onClick = onIgnore onClick = { onIgnore(uiState.isInstalled) },
enabled = !uiState.isDownloading
) { ) {
Text( Text(
text = stringResource(R.string.action_ignore), text = if (uiState.isInstalled)
stringResource(R.string.action_install)
else
stringResource(R.string.action_ignore),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
@@ -143,7 +150,7 @@ private fun ScreenContent(
@Preview @Preview
@Composable @Composable
private fun MicroGScreenPreview(@PreviewParameter(AppPreviewProvider ::class) app: App) { private fun MicroGScreenPreview(@PreviewParameter(AppPreviewProvider::class) app: App) {
PreviewTemplate { PreviewTemplate {
ScreenContent(topAppBarTitle = app.displayName) ScreenContent(topAppBarTitle = app.displayName)
} }

View File

@@ -166,6 +166,10 @@ class AppInstaller @Inject constructor(
private val defaultInstaller: IInstaller private val defaultInstaller: IInstaller
get() = sessionInstaller get() = sessionInstaller
fun getMicroGInstaller(): IInstaller {
return microGInstaller
}
fun getPreferredInstaller(): IInstaller { fun getPreferredInstaller(): IInstaller {
return when (getCurrentInstaller(context)) { return when (getCurrentInstaller(context)) {
Installer.SESSION -> sessionInstaller Installer.SESSION -> sessionInstaller

View File

@@ -26,6 +26,10 @@ object MigrationHelper {
override fun migrate(db: SupportSQLiteDatabase) = migrateFrom4To5(db) override fun migrate(db: SupportSQLiteDatabase) = migrateFrom4To5(db)
} }
val MIGRATION_5_6 = object : Migration(5, 6) {
override fun migrate(db: SupportSQLiteDatabase) = migrateFrom5To6(db)
}
private const val TAG = "MigrationHelper" private const val TAG = "MigrationHelper"
private fun migrateFrom1To2(database: SupportSQLiteDatabase) { private fun migrateFrom1To2(database: SupportSQLiteDatabase) {
@@ -83,4 +87,21 @@ object MigrationHelper {
database.endTransaction() database.endTransaction()
} }
} }
/**
* Add requiresGMS column to download table for checking if app requires GMS to install.
*/
private fun migrateFrom5To6(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL(
"ALTER TABLE `download` ADD COLUMN requiresGMS INTEGER NOT NULL DEFAULT 0"
)
database.setTransactionSuccessful()
} catch (exception: Exception) {
Log.e(TAG, "Failed while migrating from database version 5 to 6", exception)
} finally {
database.endTransaction()
}
}
} }

View File

@@ -6,6 +6,7 @@ import com.aurora.store.data.room.MigrationHelper.MIGRATION_1_2
import com.aurora.store.data.room.MigrationHelper.MIGRATION_2_3 import com.aurora.store.data.room.MigrationHelper.MIGRATION_2_3
import com.aurora.store.data.room.MigrationHelper.MIGRATION_3_4 import com.aurora.store.data.room.MigrationHelper.MIGRATION_3_4
import com.aurora.store.data.room.MigrationHelper.MIGRATION_4_5 import com.aurora.store.data.room.MigrationHelper.MIGRATION_4_5
import com.aurora.store.data.room.MigrationHelper.MIGRATION_5_6
import com.aurora.store.data.room.download.DownloadConverter import com.aurora.store.data.room.download.DownloadConverter
import com.aurora.store.data.room.download.DownloadDao import com.aurora.store.data.room.download.DownloadDao
import com.aurora.store.data.room.favourite.FavouriteDao import com.aurora.store.data.room.favourite.FavouriteDao
@@ -30,7 +31,7 @@ object RoomModule {
downloadConverter: DownloadConverter downloadConverter: DownloadConverter
): AuroraDatabase { ): AuroraDatabase {
return Room.databaseBuilder(context, AuroraDatabase::class.java, DATABASE) return Room.databaseBuilder(context, AuroraDatabase::class.java, DATABASE)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5) .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6)
.addTypeConverter(downloadConverter) .addTypeConverter(downloadConverter)
.build() .build()
} }

View File

@@ -5,6 +5,7 @@ import android.os.Parcelable
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.aurora.extensions.requiresGMS
import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.PlayFile import com.aurora.gplayapi.data.models.PlayFile
import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.model.DownloadStatus
@@ -35,7 +36,8 @@ data class Download(
var fileList: List<PlayFile>, var fileList: List<PlayFile>,
val sharedLibs: List<SharedLib>, val sharedLibs: List<SharedLib>,
val targetSdk: Int = 1, val targetSdk: Int = 1,
val downloadedAt: Long = 0 val downloadedAt: Long = 0,
val requiresGMS: Boolean = false
) : Parcelable { ) : Parcelable {
val isFinished get() = status in DownloadStatus.finished val isFinished get() = status in DownloadStatus.finished
val isRunning get() = status in DownloadStatus.running val isRunning get() = status in DownloadStatus.running
@@ -61,7 +63,8 @@ data class Download(
app.fileList.filterNot { it.url.isBlank() }, app.fileList.filterNot { it.url.isBlank() },
app.dependencies.dependentLibraries.map { SharedLib.fromApp(it) }, app.dependencies.dependentLibraries.map { SharedLib.fromApp(it) },
app.targetSdk, app.targetSdk,
Date().time Date().time,
app.requiresGMS()
) )
} }

View File

@@ -19,7 +19,9 @@ import androidx.work.ForegroundInfo
import androidx.work.WorkInfo.Companion.STOP_REASON_CANCELLED_BY_APP import androidx.work.WorkInfo.Companion.STOP_REASON_CANCELLED_BY_APP
import androidx.work.WorkInfo.Companion.STOP_REASON_USER import androidx.work.WorkInfo.Companion.STOP_REASON_USER
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.aurora.Constants.FLAVOUR_HUAWEI
import com.aurora.extensions.copyTo import com.aurora.extensions.copyTo
import com.aurora.extensions.isHuawei
import com.aurora.extensions.isPAndAbove import com.aurora.extensions.isPAndAbove
import com.aurora.extensions.isQAndAbove import com.aurora.extensions.isQAndAbove
import com.aurora.extensions.isSAndAbove import com.aurora.extensions.isSAndAbove
@@ -28,6 +30,7 @@ import com.aurora.gplayapi.data.models.PlayFile
import com.aurora.gplayapi.helpers.PurchaseHelper import com.aurora.gplayapi.helpers.PurchaseHelper
import com.aurora.gplayapi.network.IHttpClient import com.aurora.gplayapi.network.IHttpClient
import com.aurora.store.AuroraApp import com.aurora.store.AuroraApp
import com.aurora.store.BuildConfig
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.event.InstallerEvent import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.helper.DownloadHelper import com.aurora.store.data.helper.DownloadHelper
@@ -40,7 +43,9 @@ import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.data.room.download.Download import com.aurora.store.data.room.download.Download
import com.aurora.store.data.room.download.DownloadDao import com.aurora.store.data.room.download.DownloadDao
import com.aurora.store.util.CertUtil import com.aurora.store.util.CertUtil
import com.aurora.store.util.FlavouredUtil
import com.aurora.store.util.NotificationUtil import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PackageUtil
import com.aurora.store.util.PathUtil import com.aurora.store.util.PathUtil
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
@@ -88,8 +93,11 @@ class DownloadWorker @AssistedInject constructor(
inner class NoNetworkException : Exception(context.getString(R.string.title_no_network)) inner class NoNetworkException : Exception(context.getString(R.string.title_no_network))
inner class NothingToDownloadException : Exception(context.getString(R.string.purchase_no_file)) inner class NothingToDownloadException : Exception(context.getString(R.string.purchase_no_file))
inner class DownloadFailedException : Exception(context.getString(R.string.download_failed)) inner class DownloadFailedException : Exception(context.getString(R.string.download_failed))
inner class DownloadCancelledException : Exception(context.getString(R.string.download_canceled)) inner class DownloadCancelledException :
inner class VerificationFailedException : Exception(context.getString(R.string.verification_failed)) Exception(context.getString(R.string.download_canceled))
inner class VerificationFailedException :
Exception(context.getString(R.string.verification_failed))
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
super.doWork() super.doWork()
@@ -198,7 +206,10 @@ class DownloadWorker @AssistedInject constructor(
private suspend fun onSuccess(): Result { private suspend fun onSuccess(): Result {
return withContext(NonCancellable) { return withContext(NonCancellable) {
return@withContext try { return@withContext try {
appInstaller.getPreferredInstaller().install(download) if (BuildConfig.FLAVOR == FLAVOUR_HUAWEI && download.requiresGMS && PackageUtil.hasMicroGCompanion(context))
appInstaller.getMicroGInstaller().install(download)
else
appInstaller.getPreferredInstaller().install(download)
Result.success() Result.success()
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e(TAG, "Failed to install ${download.packageName}", exception) Log.e(TAG, "Failed to install ${download.packageName}", exception)
@@ -220,7 +231,7 @@ class DownloadWorker @AssistedInject constructor(
notifyStatus(DownloadStatus.CANCELLED) notifyStatus(DownloadStatus.CANCELLED)
} }
else -> { else -> {
notifyStatus(status = DownloadStatus.FAILED, exception = exception) notifyStatus(status = DownloadStatus.FAILED, exception = exception)
AuroraApp.events.send( AuroraApp.events.send(
InstallerEvent.Failed( InstallerEvent.Failed(
@@ -410,7 +421,7 @@ class DownloadWorker @AssistedInject constructor(
downloadDao.updateProgress(download.packageName, 100, 0, 0) downloadDao.updateProgress(download.packageName, 100, 0, 0)
} }
else -> {} else -> {}
} }
val notification = NotificationUtil.getDownloadNotification( val notification = NotificationUtil.getDownloadNotification(

View File

@@ -11,6 +11,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.aurora.Constants.FLAVOUR_HUAWEI
import com.aurora.Constants.PACKAGE_NAME_GMS import com.aurora.Constants.PACKAGE_NAME_GMS
import com.aurora.Constants.PACKAGE_NAME_PLAY_STORE import com.aurora.Constants.PACKAGE_NAME_PLAY_STORE
import com.aurora.extensions.areNotificationsEnabled import com.aurora.extensions.areNotificationsEnabled
@@ -82,7 +83,7 @@ class OnboardingViewModel @Inject constructor(
Log.i(TAG, "Finishing onboarding with defaults") Log.i(TAG, "Finishing onboarding with defaults")
context.saveDefaultPreferences() context.saveDefaultPreferences()
if (BuildConfig.FLAVOR == "huawei") { if (BuildConfig.FLAVOR == FLAVOUR_HUAWEI) {
blacklistProvider.blacklist(PACKAGE_NAME_GMS) blacklistProvider.blacklist(PACKAGE_NAME_GMS)
blacklistProvider.blacklist(PACKAGE_NAME_PLAY_STORE) blacklistProvider.blacklist(PACKAGE_NAME_PLAY_STORE)
} }