Merge branch 'feature/add-microg-installer' into 'dev'
Add microG Installer See merge request AuroraOSS/AuroraStore!528
This commit is contained in:
@@ -119,6 +119,13 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/AppTheme.Translucent" />
|
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 -->
|
<!-- DownloadWorker -->
|
||||||
<service
|
<service
|
||||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.Installer
|
||||||
import com.aurora.store.data.model.InstallerInfo
|
import com.aurora.store.data.model.InstallerInfo
|
||||||
import com.aurora.store.util.PackageUtil
|
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
|
||||||
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@@ -52,7 +53,8 @@ class AppInstaller @Inject constructor(
|
|||||||
private val rootInstaller: RootInstaller,
|
private val rootInstaller: RootInstaller,
|
||||||
private val serviceInstaller: ServiceInstaller,
|
private val serviceInstaller: ServiceInstaller,
|
||||||
private val amInstaller: AMInstaller,
|
private val amInstaller: AMInstaller,
|
||||||
private val shizukuInstaller: ShizukuInstaller
|
private val shizukuInstaller: ShizukuInstaller,
|
||||||
|
private val microGInstaller: MicroGInstaller
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -73,7 +75,8 @@ class AppInstaller @Inject constructor(
|
|||||||
if (hasRootAccess()) RootInstaller.installerInfo else null,
|
if (hasRootAccess()) RootInstaller.installerInfo else null,
|
||||||
if (hasAuroraService(context)) ServiceInstaller.installerInfo else null,
|
if (hasAuroraService(context)) ServiceInstaller.installerInfo else null,
|
||||||
if (hasAppManager(context)) AMInstaller.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.SERVICE -> hasAuroraService(context)
|
||||||
Installer.AM -> false // We cannot check if AppManager has ability to auto-update
|
Installer.AM -> false // We cannot check if AppManager has ability to auto-update
|
||||||
Installer.SHIZUKU -> isOAndAbove && hasShizukuOrSui(context) && hasShizukuPerm()
|
Installer.SHIZUKU -> isOAndAbove && hasShizukuOrSui(context) && hasShizukuPerm()
|
||||||
|
Installer.MICROG -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +180,7 @@ class AppInstaller @Inject constructor(
|
|||||||
defaultInstaller
|
defaultInstaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Installer.MICROG -> if(hasMicroGCompanion(context)) microGInstaller else defaultInstaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,5 +9,6 @@ enum class Installer {
|
|||||||
ROOT,
|
ROOT,
|
||||||
SERVICE,
|
SERVICE,
|
||||||
AM,
|
AM,
|
||||||
SHIZUKU
|
SHIZUKU,
|
||||||
|
MICROG
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ object PackageUtil {
|
|||||||
|
|
||||||
private const val VERSION_CODE_MICRO_G: Long = 240913402
|
private const val VERSION_CODE_MICRO_G: Long = 240913402
|
||||||
private const val VERSION_CODE_MICRO_G_HUAWEI: Long = 240913007
|
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> {
|
fun getAllValidPackages(context: Context): List<PackageInfo> {
|
||||||
return context.packageManager.getInstalledPackages(PackageManager.GET_META_DATA)
|
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 {
|
fun isInstalled(context: Context, packageName: String, versionCode: Long? = null): Boolean {
|
||||||
return try {
|
return try {
|
||||||
val packageInfo = getPackageInfo(context, packageName, PackageManager.GET_META_DATA)
|
val packageInfo = getPackageInfo(context, packageName, PackageManager.GET_META_DATA)
|
||||||
|
|||||||
@@ -178,6 +178,7 @@
|
|||||||
<string name="installer_service_available">"Aurora Services is available and ready to install."</string>
|
<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_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_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">"Installer failed"</string>
|
||||||
<string name="installer_status_failure_blocked">"Installation was blocked"</string>
|
<string name="installer_status_failure_blocked">"Installation was blocked"</string>
|
||||||
<string name="installer_status_failure_session">"Could not create session"</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_root">"Root installer"</string>
|
||||||
<string name="pref_install_mode_services">"Aurora Services (Deprecated)"</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_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_summary">"Select mode of APK installation"</string>
|
||||||
<string name="pref_install_mode_title">"Installation method"</string>
|
<string name="pref_install_mode_title">"Installation method"</string>
|
||||||
<string name="pref_vending_version_title">Google Play version</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="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_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="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_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="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>
|
<string name="shizuku_installer_subtitle">Using system APIs directly with adb/root privileges</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user