diff --git a/app/src/main/assets/installers.json b/app/src/main/assets/installers.json index c52676ed1..b8f86f8f6 100755 --- a/app/src/main/assets/installers.json +++ b/app/src/main/assets/installers.json @@ -24,5 +24,11 @@ "title": "Aurora Service", "subtitle": "Installer for background installations", "description": "Requires Aurora Services to be installed as system app." + }, + { + "id": "4", + "title": "AM Installer", + "subtitle": "Install use App Manager", + "description": "You must have App Manager. Need adb/root mode to install when miui optimization is on." } ] \ No newline at end of file diff --git a/app/src/main/java/com/aurora/store/data/installer/AMInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/AMInstaller.kt new file mode 100644 index 000000000..cd7828f26 --- /dev/null +++ b/app/src/main/java/com/aurora/store/data/installer/AMInstaller.kt @@ -0,0 +1,65 @@ +package com.aurora.store.data.installer + +import android.content.Context +import android.content.Intent +import androidx.core.content.FileProvider +import com.aurora.store.util.Log +import java.io.* +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream + +class AMInstaller(context: Context) : InstallerBase(context) { + companion object { + const val AM_PACKAGE_NAME = "io.github.muntashirakon.AppManager" + const val AM_DEBUG_PACKAGE_NAME = "io.github.muntashirakon.AppManager.debug" + } + + override fun install(packageName: String, files: List) { + if (isAlreadyQueued(packageName)) { + Log.i("$packageName already queued") + } else { + Log.i("Received AM install request for $packageName") + val fileList = files.map { + when (it) { + is File -> it.absolutePath + is String -> File(it).absolutePath + else -> { + throw Exception("Invalid data, expecting listOf() File or String") + } + } + } + val apks = zipFile(fileList) + xInstall(packageName, apks) + } + } + + private fun xInstall(packageName: String, file: File) { + val intent: Intent = Intent(Intent.ACTION_VIEW) + intent.setDataAndType( + FileProvider.getUriForFile( + context, + context.applicationContext.packageName + ".fileProvider", + file + ), "application/octet-stream" + ); + intent.flags = + Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION + context.startActivity(intent) + } + + @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") + private fun zipFile(files: List): File { + val outPath = File(files.first()).parentFile.absolutePath + "/bundle.apks" + val out = ZipOutputStream(BufferedOutputStream(FileOutputStream(outPath))) + for (file in files) { + val fi = FileInputStream(file) + val origin = BufferedInputStream(fi) + val entry = ZipEntry(file.substring(file.lastIndexOf("/"))) + out.putNextEntry(entry) + origin.copyTo(out, 1024) + origin.close() + } + out.close() + return File(outPath) + } +} \ 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 99e5ed78a..3e6165e22 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 @@ -77,6 +77,11 @@ open class AppInstaller private constructor(var context: Context) { choiceAndInstaller[prefValue] = installer installer } + 4 -> { + val installer = AMInstaller(context) + choiceAndInstaller[prefValue] = installer + installer + } else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val installer = SessionInstaller(context) choiceAndInstaller[prefValue] = installer diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/InstallerFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/InstallerFragment.kt index cc928e878..f7b313a01 100644 --- a/app/src/main/java/com/aurora/store/view/ui/onboarding/InstallerFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/onboarding/InstallerFragment.kt @@ -28,6 +28,7 @@ import com.aurora.extensions.isMiuiOptimizationDisabled import com.aurora.extensions.showDialog import com.aurora.store.BuildConfig import com.aurora.store.R +import com.aurora.store.data.installer.AMInstaller import com.aurora.store.data.installer.ServiceInstaller import com.aurora.store.data.model.Installer import com.aurora.store.databinding.FragmentOnboardingInstallerBinding @@ -130,6 +131,17 @@ class InstallerFragment : BaseFragment() { ) } } + 4 -> { + if (checkAMAvailability()) { + this.installerId = installerId + save(Preferences.PREFERENCE_INSTALLER_ID, installerId) + } else { + showDialog( + R.string.action_installations, + R.string.installer_am_unavailable + ) + } + } else -> { this.installerId = installerId save(PREFERENCE_INSTALLER_ID, installerId) @@ -169,4 +181,14 @@ class InstallerFragment : BaseFragment() { return isInstalled && isCorrectVersionInstalled } + + private fun checkAMAvailability(): Boolean { + return PackageUtil.isInstalled( + requireContext(), + AMInstaller.AM_PACKAGE_NAME + ) or PackageUtil.isInstalled( + requireContext(), + AMInstaller.AM_DEBUG_PACKAGE_NAME + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/aurora/store/view/ui/preferences/InstallationPreference.kt b/app/src/main/java/com/aurora/store/view/ui/preferences/InstallationPreference.kt index d84eaaff4..b6b553f2e 100644 --- a/app/src/main/java/com/aurora/store/view/ui/preferences/InstallationPreference.kt +++ b/app/src/main/java/com/aurora/store/view/ui/preferences/InstallationPreference.kt @@ -28,6 +28,7 @@ import com.aurora.extensions.showDialog import com.aurora.extensions.toast import com.aurora.store.BuildConfig import com.aurora.store.R +import com.aurora.store.data.installer.AMInstaller import com.aurora.store.data.installer.ServiceInstaller import com.aurora.store.util.CommonUtil import com.aurora.store.util.PackageUtil @@ -88,6 +89,17 @@ class InstallationPreference : PreferenceFragmentCompat() { ) false } + } else if (selectedId == 4) { + if (checkAMAvailability()) { + save(Preferences.PREFERENCE_INSTALLER_ID, selectedId) + true + } else { + showDialog( + R.string.action_installations, + R.string.installer_am_unavailable + ) + false + } } else { save(Preferences.PREFERENCE_INSTALLER_ID, selectedId) true @@ -115,4 +127,14 @@ class InstallationPreference : PreferenceFragmentCompat() { return isInstalled && isCorrectVersionInstalled } + + private fun checkAMAvailability(): Boolean { + return PackageUtil.isInstalled( + requireContext(), + AMInstaller.AM_PACKAGE_NAME + ) or PackageUtil.isInstalled( + requireContext(), + AMInstaller.AM_DEBUG_PACKAGE_NAME + ) + } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8631194fd..39f1a2d13 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -112,6 +112,7 @@ @string/pref_install_mode_native @string/pref_install_mode_root @string/pref_install_mode_services + @string/pref_install_mode_am @@ -119,6 +120,7 @@ 1 2 3 + 4 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d8fca7342..99a93fe69 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -205,6 +205,7 @@ "Positive" "Three" "Two" + Install App Manager or change the installer. "Root access available" No root access. Grant it or change the installer. "Aurora services is available and ready to install." @@ -279,6 +280,7 @@ "Auto install APKs after download" "APKs will be deleted by default" "Delete APK post-install" + AM installer. "Native installer" "Root installer" "Aurora Services"