Move post-installation steps to AppInstaller class

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-05-04 14:05:56 +05:30
parent f7667c17aa
commit 8f4995221a
8 changed files with 61 additions and 75 deletions

View File

@@ -1,24 +0,0 @@
package com.aurora.extensions
import android.content.BroadcastReceiver
import com.aurora.store.AuroraApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
fun BroadcastReceiver.goAsync(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> Unit
) {
val pendingResult = goAsync()
AuroraApp.scope.launch(context) {
try {
block()
} finally {
pendingResult.finish()
cancel()
}
}
}

View File

@@ -20,6 +20,7 @@
package com.aurora.store.data.installer
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
@@ -31,6 +32,8 @@ import com.aurora.extensions.isOAndAbove
import com.aurora.extensions.isPAndAbove
import com.aurora.store.BuildConfig
import com.aurora.store.R
import com.aurora.store.data.room.download.Download
import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PackageUtil
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
@@ -43,6 +46,15 @@ import javax.inject.Inject
class AppInstaller @Inject constructor(@ApplicationContext private val context: Context) {
companion object {
const val EXTRA_DOWNLOAD = "com.aurora.store.data.installer.AppInstaller.EXTRA_DOWNLOAD"
fun notifyInstallation(context: Context, download: Download) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification = NotificationUtil.getInstallNotification(context, download)
notificationManager.notify(download.packageName.hashCode(), notification)
}
fun getErrorString(context: Context, status: Int): String {
return when (status) {
PackageInstaller.STATUS_FAILURE_ABORTED -> context.getString(R.string.installer_status_user_action)

View File

@@ -25,13 +25,23 @@ import androidx.core.content.FileProvider
import com.aurora.store.AuroraApp
import com.aurora.store.BuildConfig
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.PathUtil
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE
import org.greenrobot.eventbus.EventBus
import java.io.File
abstract class InstallerBase(protected var context: Context) : IInstaller {
var download: Download? = null
private set
override fun install(download: Download) {
this.download = download
}
override fun clearQueue() {
AuroraApp.enqueuedInstalls.clear()
}
@@ -44,6 +54,16 @@ abstract class InstallerBase(protected var context: Context) : IInstaller {
AuroraApp.enqueuedInstalls.remove(packageName)
}
open fun onInstallationSuccess() {
download?.let {
AppInstaller.notifyInstallation(context, it)
if (Preferences.getBoolean(context, PREFERENCE_AUTO_DELETE)) {
PathUtil.getAppDownloadDir(context, it.packageName, it.versionCode)
.deleteRecursively()
}
}
}
open fun postError(packageName: String, error: String?, extra: String?) {
Log.e("Service Error :$error")

View File

@@ -93,7 +93,9 @@ class RootInstaller(context: Context) : InstallerBase(context) {
val shellResult = Shell.cmd("pm install-commit $sessionId").exec()
if (!shellResult.isSuccess) {
if (shellResult.isSuccess) {
onInstallationSuccess()
} else {
removeFromInstallQueue(packageName)
val event = InstallerEvent.Failed(
packageName,

View File

@@ -36,6 +36,7 @@ import com.aurora.extensions.isTAndAbove
import com.aurora.extensions.isUAndAbove
import com.aurora.extensions.runOnUiThread
import com.aurora.store.R
import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_DOWNLOAD
import com.aurora.store.data.model.Installer
import com.aurora.store.data.receiver.InstallerStatusReceiver
import com.aurora.store.data.room.download.Download
@@ -63,6 +64,8 @@ class SessionInstaller(context: Context) : InstallerBase(context) {
}
override fun install(download: Download) {
super.install(download)
if (isAlreadyQueued(download.packageName)) {
Log.i("${download.packageName} already queued")
} else {
@@ -168,6 +171,7 @@ class SessionInstaller(context: Context) : InstallerBase(context) {
action = InstallerStatusReceiver.ACTION_INSTALL_STATUS
setPackage(context.packageName)
putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName)
putExtra(EXTRA_DOWNLOAD, download)
addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
}
val flags = if (isSAndAbove()) {

View File

@@ -31,6 +31,7 @@ import androidx.annotation.RequiresApi
import com.aurora.extensions.isOAndAbove
import com.aurora.extensions.isSAndAbove
import com.aurora.store.R
import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_DOWNLOAD
import com.aurora.store.data.model.Installer
import com.aurora.store.data.receiver.InstallerStatusReceiver
import com.aurora.store.data.room.download.Download
@@ -81,6 +82,8 @@ class ShizukuInstaller(context: Context) : InstallerBase(context) {
}
override fun install(download: Download) {
super.install(download)
if (isAlreadyQueued(download.packageName)) {
Log.i("${download.packageName} already queued")
} else {
@@ -142,6 +145,7 @@ class ShizukuInstaller(context: Context) : InstallerBase(context) {
setPackage(context.packageName)
addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, sharedLibPkgName.ifBlank { packageName })
putExtra(EXTRA_DOWNLOAD, download)
}
val flags = if (isSAndAbove()) {
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE

View File

@@ -30,8 +30,13 @@ import com.aurora.gplayapi.data.models.App
import com.aurora.store.R
import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.installer.AppInstaller
import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_DOWNLOAD
import com.aurora.store.data.room.download.Download
import com.aurora.store.util.CommonUtil.inForeground
import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PathUtil
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE
import dagger.hilt.android.AndroidEntryPoint
import org.greenrobot.eventbus.EventBus
@@ -50,9 +55,19 @@ class InstallerStatusReceiver : BroadcastReceiver() {
val packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)
val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)
val extra = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
val download = IntentCompat.getParcelableExtra(
intent, EXTRA_DOWNLOAD, Download::class.java
)
// Exit early if package was successfully installed, nothing to do
if (status == PackageInstaller.STATUS_SUCCESS) return
// If package was successfully installed, exit after notifying user and doing cleanup
if (status == PackageInstaller.STATUS_SUCCESS && download != null) {
AppInstaller.notifyInstallation(context, download)
if (Preferences.getBoolean(context, PREFERENCE_AUTO_DELETE)) {
PathUtil.getAppDownloadDir(context, download.packageName, download.versionCode)
.deleteRecursively()
}
return
}
if (inForeground() && status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
promptUser(intent, context)

View File

@@ -19,60 +19,29 @@
package com.aurora.store.data.receiver
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.aurora.extensions.goAsync
import com.aurora.store.data.event.BusEvent.InstallEvent
import com.aurora.store.data.event.BusEvent.UninstallEvent
import com.aurora.store.data.installer.AppInstaller
import com.aurora.store.data.model.DownloadStatus
import com.aurora.store.data.room.download.Download
import com.aurora.store.util.DownloadWorkerUtil
import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PackageUtil.isSharedLibrary
import com.aurora.store.util.PathUtil
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.firstOrNull
import org.greenrobot.eventbus.EventBus
@AndroidEntryPoint
open class PackageManagerReceiver : BroadcastReceiver() {
private val TAG = PackageManagerReceiver::class.java.simpleName
@Inject
lateinit var downloadWorkerUtil: DownloadWorkerUtil
@Inject
lateinit var appInstaller: AppInstaller
override fun onReceive(context: Context, intent: Intent) = goAsync {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != null && intent.data != null) {
val packageName = intent.data!!.encodedSchemeSpecificPart
// We don't care about shared libraries, bail out
if (isSharedLibrary(context, packageName)) return@goAsync
when (intent.action) {
Intent.ACTION_PACKAGE_ADDED -> {
Log.i(TAG, "Installed $packageName")
EventBus.getDefault().post(InstallEvent(packageName, ""))
downloadWorkerUtil.downloadsList.filter { it.isNotEmpty() }.firstOrNull()
?.find { it.packageName == packageName && it.downloadStatus == DownloadStatus.COMPLETED }
?.let {
notifyInstallation(context, it)
if (Preferences.getBoolean(context, PREFERENCE_AUTO_DELETE)) {
clearDownloads(context, it)
}
}
}
Intent.ACTION_PACKAGE_REMOVED -> {
@@ -84,20 +53,4 @@ open class PackageManagerReceiver : BroadcastReceiver() {
appInstaller.getPreferredInstaller().removeFromInstallQueue(packageName)
}
}
private fun clearDownloads(context: Context, download: Download) {
try {
PathUtil.getAppDownloadDir(context, download.packageName, download.versionCode)
.deleteRecursively()
} catch (exception: Exception) {
Log.e(TAG, "Failed to delete $download.packageName's downloads", exception)
}
}
private fun notifyInstallation(context: Context, download: Download) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification = NotificationUtil.getInstallNotification(context, download)
notificationManager.notify(download.packageName.hashCode(), notification)
}
}