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

@@ -119,6 +119,13 @@
android:exported="false"
android:theme="@style/AppTheme.Translucent" />
<activity
android:name=".data.activity.MicroGInstallerActivity"
android:excludeFromRecents="true"
android:exported="false"
android:launchMode="singleTop"
android:theme="@style/AppTheme.Translucent" />
<!-- DownloadWorker -->
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"

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)

View File

@@ -178,6 +178,7 @@
<string name="installer_service_available">"Aurora Services is available and ready to install."</string>
<string name="installer_service_unavailable">Install Aurora Services 1.0.9 or above, or change the installer.</string>
<string name="installer_service_misconfigured">Set up Aurora Services and grant all permissions first.</string>
<string name="installer_microg_misconfigured">MicroG installer failed to install app, likely due to misconfiguration.</string>
<string name="installer_status_failure">"Installer failed"</string>
<string name="installer_status_failure_blocked">"Installation was blocked"</string>
<string name="installer_status_failure_session">"Could not create session"</string>
@@ -211,6 +212,7 @@
<string name="pref_install_mode_root">"Root installer"</string>
<string name="pref_install_mode_services">"Aurora Services (Deprecated)"</string>
<string name="pref_install_mode_session">"Session installer"</string>
<string name="pref_install_mode_microg">"MicroG installer"</string>
<string name="pref_install_mode_summary">"Select mode of APK installation"</string>
<string name="pref_install_mode_title">"Installation method"</string>
<string name="pref_vending_version_title">Google Play version</string>
@@ -387,6 +389,8 @@
<string name="native_installer_desc">Best suited for devices running below Android 4.4</string>
<string name="services_installer_subtitle">Installer for background installations</string>
<string name="services_installer_desc">Requires Aurora Services to be installed as a privileged-system app</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="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>