AMInstaller: Support installing shared libraries as well

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-02-07 21:12:48 +01:00
parent 59b38f9ac4
commit cb584db2e4
3 changed files with 50 additions and 39 deletions

View File

@@ -2,14 +2,16 @@ package com.aurora.store.data.installer
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.core.content.FileProvider
import com.aurora.store.data.room.download.Download import com.aurora.store.data.room.download.Download
import com.aurora.store.util.Log import com.aurora.store.util.Log
import java.io.* import com.aurora.store.util.PackageUtil.isSharedLibraryInstalled
import com.aurora.store.util.PathUtil
import java.io.File
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
class AMInstaller(context: Context) : InstallerBase(context) { class AMInstaller(context: Context) : InstallerBase(context) {
companion object { companion object {
const val AM_PACKAGE_NAME = "io.github.muntashirakon.AppManager" const val AM_PACKAGE_NAME = "io.github.muntashirakon.AppManager"
const val AM_DEBUG_PACKAGE_NAME = "io.github.muntashirakon.AppManager.debug" const val AM_DEBUG_PACKAGE_NAME = "io.github.muntashirakon.AppManager.debug"
@@ -20,50 +22,46 @@ class AMInstaller(context: Context) : InstallerBase(context) {
Log.i("${download.packageName} already queued") Log.i("${download.packageName} already queued")
} else { } else {
Log.i("Received AM install request for ${download.packageName}") Log.i("Received AM install request for ${download.packageName}")
val fileList = val fileList = mutableListOf<File>()
getFiles(download.packageName, download.versionCode).map { it.absolutePath }
when { download.sharedLibs.forEach {
fileList.size == 1 -> { // Shared library packages cannot be updated
xInstall(File(fileList.first())) if (!isSharedLibraryInstalled(context, it.packageName, it.versionCode)) {
} fileList.addAll(
fileList.size > 1 -> { getFiles(
val apks = zipFile(fileList) download.packageName,
xInstall(apks) download.versionCode,
} it.packageName
else -> { )
throw Exception("Invalid data, expecting non empty fileList") )
} }
} }
val zipFile = PathUtil.getZipFile(context, download.packageName, download.versionCode)
fileList.add(zip(getFiles(download.packageName, download.versionCode), zipFile))
install(fileList)
} }
} }
private fun xInstall(file: File) { private fun install(files: List<File>) {
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply {
intent.setDataAndType( type = "application/x-apks"
FileProvider.getUriForFile( flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
context, putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(files.map { getUri(it) }))
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) context.startActivity(intent)
} }
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") fun zip(files: List<File>, zipFile: File): File {
private fun zipFile(files: List<String>): File { ZipOutputStream(zipFile.outputStream()).use { zipOutput ->
val outPath = File(files.first()).parentFile.absolutePath + "/bundle.apks" files.forEach { file ->
val out = ZipOutputStream(BufferedOutputStream(FileOutputStream(outPath))) file.inputStream().use { input ->
for (file in files) { zipOutput.putNextEntry(ZipEntry(file.name))
val fi = FileInputStream(file) input.copyTo(zipOutput)
val origin = BufferedInputStream(fi) }
val entry = ZipEntry(file.substring(file.lastIndexOf("/"))) }
out.putNextEntry(entry)
origin.copyTo(out, 1024)
origin.close()
} }
out.close() return zipFile
return File(outPath)
} }
} }

View File

@@ -25,7 +25,6 @@ import androidx.core.content.FileProvider
import com.aurora.store.AuroraApplication import com.aurora.store.AuroraApplication
import com.aurora.store.BuildConfig import com.aurora.store.BuildConfig
import com.aurora.store.data.event.InstallerEvent import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.room.download.Download
import com.aurora.store.util.Log import com.aurora.store.util.Log
import com.aurora.store.util.PathUtil import com.aurora.store.util.PathUtil
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus

View File

@@ -90,6 +90,20 @@ object PathUtil {
) + "/${file.name}" ) + "/${file.name}"
} }
fun getZipFile(
context: Context,
packageName: String,
versionCode: Int
): File {
return File(
getAppDownloadDir(
context,
packageName,
versionCode,
), "${packageName}_${versionCode}.apks"
)
}
fun getExternalPath(context: Context): String { fun getExternalPath(context: Context): String {
val defaultDir = val defaultDir =
File("${Environment.getExternalStorageDirectory().absolutePath}/Aurora/Store") File("${Environment.getExternalStorageDirectory().absolutePath}/Aurora/Store")