InstallReceiver: Notify package installation status as well

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-11-02 20:31:14 +05:30
parent 26c4749047
commit 5b60758347
5 changed files with 145 additions and 22 deletions

View File

@@ -134,6 +134,7 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-service:$lifeVersion") implementation("androidx.lifecycle:lifecycle-service:$lifeVersion")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifeVersion") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifeVersion")
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifeVersion") implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifeVersion")
implementation("androidx.lifecycle:lifecycle-process:$lifeVersion")
//Arch Navigation //Arch Navigation
val navVersion = "2.7.5" val navVersion = "2.7.5"

View File

@@ -28,6 +28,7 @@ import android.net.Uri
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import com.aurora.extensions.isSAndAbove import com.aurora.extensions.isSAndAbove
import com.aurora.store.BuildConfig import com.aurora.store.BuildConfig
import com.aurora.store.data.receiver.InstallReceiver
import com.aurora.store.util.Log import com.aurora.store.util.Log
import java.io.File import java.io.File
@@ -61,12 +62,17 @@ abstract class SessionInstallerBase(context: Context) : InstallerBase(context) {
} }
} }
val callBackIntent = Intent(context, InstallerService::class.java) val callBackIntent = Intent(context, InstallReceiver::class.java).apply {
action = InstallReceiver.ACTION_INSTALL_STATUS
setPackage(context.packageName)
putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName)
addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
}
val flags = if (isSAndAbove()) val flags = if (isSAndAbove())
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE else PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE else
PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_UPDATE_CURRENT
val pendingIntent = PendingIntent.getService( val pendingIntent = PendingIntent.getBroadcast(
context, context,
sessionId, sessionId,
callBackIntent, callBackIntent,

View File

@@ -18,35 +18,148 @@
*/ */
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 android.content.pm.PackageInstaller
import android.util.Log import android.util.Log
import androidx.core.content.IntentCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
import com.aurora.Constants import com.aurora.Constants
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
import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PathUtil import com.aurora.store.util.PathUtil
import java.io.File import java.io.File
import org.greenrobot.eventbus.EventBus
import kotlin.io.path.pathString import kotlin.io.path.pathString
class InstallReceiver : BroadcastReceiver() { class InstallReceiver : BroadcastReceiver() {
companion object {
const val ACTION_INSTALL_APP = "com.aurora.store.data.receiver.InstallReceiver.INSTALL_APP"
const val ACTION_INSTALL_STATUS =
"com.aurora.store.data.receiver.InstallReceiver.INSTALL_STATUS"
}
private val TAG = InstallReceiver::class.java.simpleName private val TAG = InstallReceiver::class.java.simpleName
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val packageName = intent.extras?.getString(Constants.STRING_APP) ?: String() when (intent.action) {
val version = intent.extras?.getInt(Constants.STRING_VERSION) ACTION_INSTALL_APP -> {
if (packageName.isNotBlank() && version != null) { val packageName = intent.extras?.getString(Constants.STRING_APP) ?: String()
try { val version = intent.extras?.getInt(Constants.STRING_VERSION)
val downloadDir = if (packageName.isNotBlank() && version != null) {
File(PathUtil.getAppDownloadDir(context, packageName, version).pathString) try {
AppInstaller.getInstance(context).getPreferredInstaller() val downloadDir =
.install( File(
packageName, PathUtil.getAppDownloadDir(
downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") } context,
) packageName,
} catch (exception: Exception) { version
Log.e(TAG, "Failed to install $packageName") ).pathString
)
AppInstaller.getInstance(context).getPreferredInstaller()
.install(
packageName,
downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") }
)
} catch (exception: Exception) {
Log.e(TAG, "Failed to install $packageName")
}
}
}
ACTION_INSTALL_STATUS -> {
val packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)
val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)
val extra = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
if (inForeground() && status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
promptUser(intent, context)
} else {
postStatus(status, packageName, extra, context)
notifyInstallation(context, packageName!!, status)
}
} }
} }
} }
private fun notifyInstallation(context: Context, packageName: String, status: Int) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val content = if (status == PackageInstaller.STATUS_SUCCESS) {
context.getString(R.string.installer_status_success)
} else {
AppInstaller.getErrorString(context, status)
}
val notification = NotificationUtil.getInstallNotification(
context,
App(packageName).apply {
if (status == PackageInstaller.STATUS_SUCCESS) {
val appInfo = context.packageManager.getApplicationInfo(packageName, 0)
displayName = context.packageManager.getApplicationLabel(appInfo).toString()
}
},
content
)
notificationManager.notify(packageName.hashCode(), notification)
}
private fun promptUser(intent: Intent, context: Context) {
val confirmationIntent =
IntentCompat.getParcelableExtra(intent, Intent.EXTRA_INTENT, Intent::class.java)
confirmationIntent?.let {
it.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
it.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, "com.android.vending")
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
context.startActivity(it)
} catch (exception: Exception) {
Log.e(TAG, "Failed to trigger installation!", exception)
}
}
}
private fun postStatus(status: Int, packageName: String?, extra: String?, context: Context) {
when (status) {
PackageInstaller.STATUS_SUCCESS -> {
EventBus.getDefault().post(
InstallerEvent.Success(
packageName,
context.getString(R.string.installer_status_success)
)
)
}
PackageInstaller.STATUS_FAILURE_ABORTED -> {
EventBus.getDefault().post(
InstallerEvent.Cancelled(
packageName,
AppInstaller.getErrorString(context, status)
)
)
}
else -> {
EventBus.getDefault().post(
InstallerEvent.Failed(
packageName,
AppInstaller.getErrorString(context, status),
extra
)
)
}
}
}
private fun inForeground(): Boolean {
return ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)
}
} }

View File

@@ -135,10 +135,10 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
// Notify for installation // Notify for installation
Intent(appContext, InstallReceiver::class.java).also { Intent(appContext, InstallReceiver::class.java).also {
it.action = InstallReceiver.ACTION_INSTALL_APP
it.putExtra(Constants.STRING_APP, app.packageName) it.putExtra(Constants.STRING_APP, app.packageName)
it.putExtra(Constants.STRING_VERSION, app.versionCode) it.putExtra(Constants.STRING_VERSION, app.versionCode)
appContext.sendBroadcast(it) appContext.sendBroadcast(it)
} }
// Remove the app from the list // Remove the app from the list

View File

@@ -268,12 +268,15 @@ object NotificationUtil {
} }
fun getInstallNotification(context: Context, app: App, content: String?): Notification { fun getInstallNotification(context: Context, app: App, content: String?): Notification {
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT) val builder =
builder.color = context.getStyledAttributeColor(R.color.colorAccent) NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT).apply {
builder.setSmallIcon(R.drawable.ic_install) color = context.getStyledAttributeColor(R.color.colorAccent)
builder.setContentTitle(app.displayName) setSmallIcon(R.drawable.ic_install)
builder.setContentText(content) setContentTitle(app.displayName)
builder.setSubText(app.packageName) setContentText(content)
setContentIntent(getContentIntentForDetails(context, app))
setSubText(app.packageName)
}
return builder.build() return builder.build()
} }