Add microG Installer

This commit is contained in:
Rahul Patel
2025-11-03 11:28:51 +05:30
parent 29dbc18750
commit 1142ecac80
7 changed files with 210 additions and 3 deletions

View File

@@ -0,0 +1,76 @@
package com.aurora.store.data.activity
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.core.content.FileProvider
import com.aurora.Constants.PACKAGE_NAME_PLAY_STORE
import com.aurora.extensions.isTAndAbove
import com.aurora.store.BuildConfig
import com.aurora.store.data.installer.MicroGInstaller.Companion.buildMicroGInstallIntent
import java.io.File
class MicroGInstallerActivity : Activity() {
companion object {
private val TAG = MicroGInstallerActivity::class.java.simpleName
private const val REQUEST_CODE = 1001
const val EXTRA_FILES = "extra_files"
const val EXTRA_PACKAGE_NAME = "extra_package_name"
fun launch(context: Context, packageName: String, files: List<File>) {
val uris = files.map { file ->
val uri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileProvider",
file
)
context.grantUriPermission(
PACKAGE_NAME_PLAY_STORE,
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
uri
}
val intent = Intent(context, MicroGInstallerActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(EXTRA_PACKAGE_NAME, packageName)
putExtra(EXTRA_FILES, ArrayList(uris))
}
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val files: ArrayList<Uri>? = if (isTAndAbove) {
intent.getParcelableArrayListExtra(EXTRA_FILES, Uri::class.java)
} else {
intent.getParcelableArrayListExtra(EXTRA_FILES)
}
if (files.isNullOrEmpty()) {
Log.e(TAG, "No files provided, cannot proceed with MicroG installation")
return finish()
}
startActivityForResult(
buildMicroGInstallIntent(files),
REQUEST_CODE
)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// TODO: Handle result if needed
finish()
}
}

View File

@@ -35,6 +35,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
@@ -52,7 +53,8 @@ class AppInstaller @Inject constructor(
private val rootInstaller: RootInstaller,
private val serviceInstaller: ServiceInstaller,
private val amInstaller: AMInstaller,
private val shizukuInstaller: ShizukuInstaller
private val shizukuInstaller: ShizukuInstaller,
private val microGInstaller: MicroGInstaller
) {
companion object {
@@ -73,7 +75,8 @@ class AppInstaller @Inject constructor(
if (hasRootAccess()) RootInstaller.installerInfo else null,
if (hasAuroraService(context)) ServiceInstaller.installerInfo else null,
if (hasAppManager(context)) AMInstaller.installerInfo else null,
if (hasShizukuOrSui(context)) ShizukuInstaller.installerInfo else null
if (hasShizukuOrSui(context)) ShizukuInstaller.installerInfo else null,
if (hasMicroGCompanion(context)) MicroGInstaller.installerInfo else null
)
}
@@ -106,6 +109,7 @@ class AppInstaller @Inject constructor(
Installer.SERVICE -> hasAuroraService(context)
Installer.AM -> false // We cannot check if AppManager has ability to auto-update
Installer.SHIZUKU -> isOAndAbove && hasShizukuOrSui(context) && hasShizukuPerm()
Installer.MICROG -> false
}
}
@@ -176,6 +180,7 @@ class AppInstaller @Inject constructor(
defaultInstaller
}
}
Installer.MICROG -> if(hasMicroGCompanion(context)) microGInstaller else defaultInstaller
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* Aurora Store is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Aurora Store is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.aurora.store.data.installer
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import com.aurora.Constants.PACKAGE_NAME_PLAY_STORE
import com.aurora.store.R
import com.aurora.store.data.activity.MicroGInstallerActivity
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
@Singleton
class MicroGInstaller @Inject constructor(
@ApplicationContext private val context: Context
) : InstallerBase(context) {
companion object {
val installerInfo: InstallerInfo
get() = InstallerInfo(
id = 6,
installer = Installer.MICROG,
packageNames = listOf(PACKAGE_NAME_PLAY_STORE),
installerPackageNames = listOf(PACKAGE_NAME_PLAY_STORE),
title = R.string.pref_install_mode_microg,
subtitle = R.string.microg_installer_subtitle,
description = R.string.microg_installer_desc
)
fun buildMicroGInstallIntent(uris: ArrayList<Uri>): Intent {
return Intent("org.microg.vending.action.INSTALL_PACKAGE").apply {
setPackage(PACKAGE_NAME_PLAY_STORE)
setType("application/vnd.android.package-archive")
putExtra(Intent.EXTRA_STREAM, uris)
}
}
}
private val TAG = MicroGInstaller::class.java.simpleName
override fun install(download: Download) {
super.install(download)
when {
isAlreadyQueued(download.packageName) -> {
Log.i(TAG, "${download.packageName} already queued")
}
hasMicroGCompanion(context) -> {
Log.i(TAG, "Received microG install request for ${download.packageName}")
val files = getFiles(download.packageName, download.versionCode)
MicroGInstallerActivity.launch(context, download.packageName, files)
Log.i(TAG, "Sent install request to microG installer for ${download.packageName}")
}
else -> {
postError(
download.packageName,
context.getString(R.string.installer_status_failure),
context.getString(R.string.installer_microg_misconfigured)
)
}
}
}
}

View File

@@ -9,5 +9,6 @@ enum class Installer {
ROOT,
SERVICE,
AM,
SHIZUKU
SHIZUKU,
MICROG
}

View File

@@ -55,6 +55,8 @@ object PackageUtil {
private const val VERSION_CODE_MICRO_G: Long = 240913402
private const val VERSION_CODE_MICRO_G_HUAWEI: Long = 240913007
private const val VERSION_CODE_MICROG_COMPANION_MIN: Long = 84022620
private const val MICROG_INSTALL_ACTIVITY = "org.microg.vending.installer.AppInstallActivity"
fun getAllValidPackages(context: Context): List<PackageInfo> {
return context.packageManager.getInstalledPackages(PackageManager.GET_META_DATA)
@@ -109,6 +111,26 @@ object PackageUtil {
}
}
fun hasActivity(context: Context, packageName: String, activityName: String): Boolean {
val intent = Intent()
intent.setClassName(packageName, activityName)
val resolveInfo = context.packageManager.resolveActivity(intent, 0)
return resolveInfo != null
}
fun hasMicroGCompanion(context: Context): Boolean {
return isInstalled(
context,
PACKAGE_NAME_PLAY_STORE,
VERSION_CODE_MICROG_COMPANION_MIN
) && hasActivity(
context,
PACKAGE_NAME_PLAY_STORE,
MICROG_INSTALL_ACTIVITY
)
}
fun isInstalled(context: Context, packageName: String, versionCode: Long? = null): Boolean {
return try {
val packageInfo = getPackageInfo(context, packageName, PackageManager.GET_META_DATA)