diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5af65e1d6..e7d15f5ec 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -119,6 +119,13 @@
android:exported="false"
android:theme="@style/AppTheme.Translucent" />
+
+
) {
+ 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? = 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()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/aurora/store/data/installer/AppInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/AppInstaller.kt
index f3884f05e..91105ec67 100644
--- a/app/src/main/java/com/aurora/store/data/installer/AppInstaller.kt
+++ b/app/src/main/java/com/aurora/store/data/installer/AppInstaller.kt
@@ -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
}
}
}
diff --git a/app/src/main/java/com/aurora/store/data/installer/MicroGInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/MicroGInstaller.kt
new file mode 100644
index 000000000..03424bd2d
--- /dev/null
+++ b/app/src/main/java/com/aurora/store/data/installer/MicroGInstaller.kt
@@ -0,0 +1,92 @@
+/*
+ * Aurora Store
+ * Copyright (C) 2021, Rahul Kumar Patel
+ *
+ * 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 .
+ *
+ */
+
+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): 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)
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/aurora/store/data/model/Installer.kt b/app/src/main/java/com/aurora/store/data/model/Installer.kt
index 7efa730b1..59366452f 100644
--- a/app/src/main/java/com/aurora/store/data/model/Installer.kt
+++ b/app/src/main/java/com/aurora/store/data/model/Installer.kt
@@ -9,5 +9,6 @@ enum class Installer {
ROOT,
SERVICE,
AM,
- SHIZUKU
+ SHIZUKU,
+ MICROG
}
diff --git a/app/src/main/java/com/aurora/store/util/PackageUtil.kt b/app/src/main/java/com/aurora/store/util/PackageUtil.kt
index 0eeda6428..70370ff9c 100644
--- a/app/src/main/java/com/aurora/store/util/PackageUtil.kt
+++ b/app/src/main/java/com/aurora/store/util/PackageUtil.kt
@@ -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 {
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)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 04b3e9fa1..3c564a9dc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -178,6 +178,7 @@
"Aurora Services is available and ready to install."
Install Aurora Services 1.0.9 or above, or change the installer.
Set up Aurora Services and grant all permissions first.
+ MicroG installer failed to install app, likely due to misconfiguration.
"Installer failed"
"Installation was blocked"
"Could not create session"
@@ -211,6 +212,7 @@
"Root installer"
"Aurora Services (Deprecated)"
"Session installer"
+ "MicroG installer"
"Select mode of APK installation"
"Installation method"
Google Play version
@@ -387,6 +389,8 @@
Best suited for devices running below Android 4.4
Installer for background installations
Requires Aurora Services to be installed as a privileged-system app
+ Requires microG companion app to be installed
+ Helps you bypass App Integrity (installer only) check
Full-featured open source package manager
Requires App Manager, need adb/root mode to install when miui optimization is on
Using system APIs directly with adb/root privileges