PackageManagerReceiver: Rework package install actions

Notify on package installation and delete the downloaded directory

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-12-27 20:51:38 +05:30
parent e0cda7eadf
commit 87dc309d35
3 changed files with 84 additions and 22 deletions

View File

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

View File

@@ -19,29 +19,53 @@
package com.aurora.store.data.receiver package com.aurora.store.data.receiver
import android.app.NotificationManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.aurora.store.BuildConfig import android.util.Log
import com.aurora.extensions.goAsync
import com.aurora.store.data.event.BusEvent.InstallEvent import com.aurora.store.data.event.BusEvent.InstallEvent
import com.aurora.store.data.event.BusEvent.UninstallEvent import com.aurora.store.data.event.BusEvent.UninstallEvent
import com.aurora.store.data.installer.AppInstaller 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.PathUtil import com.aurora.store.util.PathUtil
import com.aurora.store.util.Preferences import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.firstOrNull
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import java.io.File
@AndroidEntryPoint @AndroidEntryPoint
open class PackageManagerReceiver : BroadcastReceiver() { open class PackageManagerReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { private val TAG = PackageManagerReceiver::class.java.simpleName
@Inject
lateinit var downloadWorkerUtil: DownloadWorkerUtil
override fun onReceive(context: Context, intent: Intent) = goAsync {
if (intent.action != null && intent.data != null) { if (intent.action != null && intent.data != null) {
val packageName = intent.data!!.encodedSchemeSpecificPart val packageName = intent.data!!.encodedSchemeSpecificPart
when (intent.action) { when (intent.action) {
Intent.ACTION_PACKAGE_ADDED -> { Intent.ACTION_PACKAGE_ADDED -> {
Log.i(TAG, "Installed $packageName")
EventBus.getDefault().post(InstallEvent(packageName, "")) EventBus.getDefault().post(InstallEvent(packageName, ""))
downloadWorkerUtil.downloadsList.filter { it.isNotEmpty() }.firstOrNull()
?.find { it.packageName == packageName && it.status == DownloadStatus.COMPLETED }
?.let {
notifyInstallation(context, it)
if (Preferences.getBoolean(context, PREFERENCE_AUTO_DELETE)) {
clearDownloads(context, it)
}
}
} }
Intent.ACTION_PACKAGE_REMOVED -> { Intent.ACTION_PACKAGE_REMOVED -> {
@@ -53,29 +77,22 @@ open class PackageManagerReceiver : BroadcastReceiver() {
AppInstaller.getInstance(context) AppInstaller.getInstance(context)
.getPreferredInstaller() .getPreferredInstaller()
.removeFromInstallQueue(packageName) .removeFromInstallQueue(packageName)
val isAutoDeleteAPKEnabled = Preferences.getBoolean(
context,
Preferences.PREFERENCE_AUTO_DELETE
)
if (isAutoDeleteAPKEnabled)
clearDownloads(context, packageName)
//Clear self update apk
if (packageName == BuildConfig.APPLICATION_ID)
clearDownloads(context, packageName)
} }
} }
private fun clearDownloads(context: Context, packageName: String) { private fun clearDownloads(context: Context, download: Download) {
try { try {
val rootDirPath = PathUtil.getPackageDirectory(context, packageName) PathUtil.getAppDownloadDir(context, download.packageName, download.versionCode)
val rootDir = File(rootDirPath) .deleteRecursively()
if (rootDir.exists()) } catch (exception: Exception) {
rootDir.deleteRecursively() Log.e(TAG, "Failed to delete $download.packageName's downloads", exception)
} catch (e: 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)
}
} }

View File

@@ -163,6 +163,25 @@ object NotificationUtil {
return builder.build() return builder.build()
} }
fun getInstallNotification(context: Context, download: AuroraDownload): Notification {
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT)
// Set big icon for download
try {
val bitmap = BitmapFactory.decodeStream(URL(download.iconURL).openStream())
builder.setLargeIcon(bitmap)
} catch (exception: Exception) {
Log.i(TAG, "Failed to set big icon", exception)
}
return builder.setSmallIcon(R.drawable.ic_install)
.setColor(context.getStyledAttributeColor(R.color.colorAccent))
.setContentTitle(download.displayName)
.setContentText(context.getString(R.string.installer_status_success))
.setContentIntent(getContentIntentForDetails(context, download.packageName))
.build()
}
fun getInstallerStatusNotification(context: Context, app: App, content: String?): Notification { fun getInstallerStatusNotification(context: Context, app: App, content: String?): Notification {
val builder = val builder =
NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT).apply { NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT).apply {