mirror of
https://github.com/whyorean/AuroraStore.git
synced 2026-06-16 03:31:02 -04:00
DownloadWorker: Move app installation logic to new onSuccess method
Move app installation logic to onSuccess method in worker under a NonCancellable context and convert the receiver class to be a generic status handler for anything except success which should be handled in PackageManagerReceiver. Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -135,7 +135,7 @@
|
||||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name=".data.receiver.InstallReceiver"
|
||||
android:name=".data.receiver.InstallerStatusReceiver"
|
||||
android:exported="false" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -28,7 +28,7 @@ import android.net.Uri
|
||||
import androidx.core.content.FileProvider
|
||||
import com.aurora.extensions.isSAndAbove
|
||||
import com.aurora.store.BuildConfig
|
||||
import com.aurora.store.data.receiver.InstallReceiver
|
||||
import com.aurora.store.data.receiver.InstallerStatusReceiver
|
||||
import com.aurora.store.util.Log
|
||||
import java.io.File
|
||||
|
||||
@@ -62,8 +62,8 @@ abstract class SessionInstallerBase(context: Context) : InstallerBase(context) {
|
||||
}
|
||||
}
|
||||
|
||||
val callBackIntent = Intent(context, InstallReceiver::class.java).apply {
|
||||
action = InstallReceiver.ACTION_INSTALL_STATUS
|
||||
val callBackIntent = Intent(context, InstallerStatusReceiver::class.java).apply {
|
||||
action = InstallerStatusReceiver.ACTION_INSTALL_STATUS
|
||||
setPackage(context.packageName)
|
||||
putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName)
|
||||
addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
|
||||
|
||||
@@ -25,91 +25,56 @@ import android.content.Intent
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.util.Log
|
||||
import androidx.core.content.IntentCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
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.util.CommonUtil.inForeground
|
||||
import com.aurora.store.util.NotificationUtil
|
||||
import com.aurora.store.util.PathUtil
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.io.File
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
@AndroidEntryPoint
|
||||
class InstallReceiver : BroadcastReceiver() {
|
||||
class InstallerStatusReceiver : 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 = InstallerStatusReceiver::class.java.simpleName
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when (intent.action) {
|
||||
ACTION_INSTALL_APP -> {
|
||||
val packageName = intent.extras?.getString(Constants.STRING_APP) ?: String()
|
||||
val version = intent.extras?.getInt(Constants.STRING_VERSION)
|
||||
if (packageName.isNotBlank() && version != null) {
|
||||
try {
|
||||
val downloadDir =
|
||||
File(PathUtil.getAppDownloadDir(context, packageName, version).path)
|
||||
AppInstaller.getInstance(context).getPreferredInstaller()
|
||||
.install(
|
||||
packageName,
|
||||
downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") }
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to install $packageName")
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intent.action == 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)
|
||||
|
||||
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)
|
||||
// Exit early if package was successfully installed, nothing to do
|
||||
if (status == PackageInstaller.STATUS_SUCCESS) return
|
||||
|
||||
if (inForeground() && status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
|
||||
promptUser(intent, context)
|
||||
} else {
|
||||
postStatus(status, packageName, extra, context)
|
||||
notifyInstallation(context, packageName!!, status)
|
||||
}
|
||||
if (inForeground() && status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
|
||||
promptUser(intent, context)
|
||||
} else {
|
||||
postStatus(status, packageName, extra, context)
|
||||
notifyUser(context, packageName!!, status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyInstallation(context: Context, packageName: String, status: Int) {
|
||||
private fun notifyUser(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(
|
||||
val notification = NotificationUtil.getInstallerStatusNotification(
|
||||
context,
|
||||
App(packageName).apply {
|
||||
if (status == PackageInstaller.STATUS_SUCCESS) {
|
||||
val appInfo = context.packageManager.getApplicationInfo(packageName, 0)
|
||||
displayName = context.packageManager.getApplicationLabel(appInfo).toString()
|
||||
}
|
||||
},
|
||||
content
|
||||
App(packageName),
|
||||
AppInstaller.getErrorString(context, status)
|
||||
)
|
||||
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 {
|
||||
IntentCompat.getParcelableExtra(intent, Intent.EXTRA_INTENT, Intent::class.java)?.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)
|
||||
@@ -153,8 +118,4 @@ class InstallReceiver : BroadcastReceiver() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun inForeground(): Boolean {
|
||||
return ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)
|
||||
}
|
||||
}
|
||||
@@ -3,24 +3,22 @@ package com.aurora.store.data.work
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
import android.util.Log
|
||||
import androidx.hilt.work.HiltWorker
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.WorkerParameters
|
||||
import com.aurora.Constants
|
||||
import com.aurora.extensions.copyTo
|
||||
import com.aurora.extensions.isQAndAbove
|
||||
import com.aurora.extensions.requiresObbDir
|
||||
import com.aurora.gplayapi.helpers.PurchaseHelper
|
||||
import com.aurora.store.data.installer.AppInstaller
|
||||
import com.aurora.store.data.model.DownloadInfo
|
||||
import com.aurora.store.data.model.DownloadStatus
|
||||
import com.aurora.store.data.model.Request
|
||||
import com.aurora.store.data.network.HttpClient
|
||||
import com.aurora.store.data.providers.AuthProvider
|
||||
import com.aurora.store.data.receiver.InstallReceiver
|
||||
import com.aurora.store.data.room.download.Download
|
||||
import com.aurora.store.data.room.download.DownloadDao
|
||||
import com.aurora.store.util.DownloadWorkerUtil
|
||||
@@ -143,17 +141,30 @@ class DownloadWorker @AssistedInject constructor(
|
||||
// Mark download as completed
|
||||
notifyStatus(DownloadStatus.COMPLETED)
|
||||
Log.i(TAG, "Finished downloading ${download.packageName}")
|
||||
|
||||
// Notify for installation
|
||||
Intent(appContext, InstallReceiver::class.java).also {
|
||||
it.action = InstallReceiver.ACTION_INSTALL_APP
|
||||
it.putExtra(Constants.STRING_APP, download.packageName)
|
||||
it.putExtra(Constants.STRING_VERSION, download.versionCode)
|
||||
appContext.sendBroadcast(it)
|
||||
}
|
||||
onSuccess()
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private suspend fun onSuccess() {
|
||||
withContext(NonCancellable) {
|
||||
try {
|
||||
val downloadDir = PathUtil.getAppDownloadDir(
|
||||
appContext,
|
||||
download.packageName,
|
||||
download.versionCode
|
||||
)
|
||||
AppInstaller.getInstance(appContext)
|
||||
.getPreferredInstaller()
|
||||
.install(
|
||||
download.packageName,
|
||||
downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") }
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to install ${download.packageName}", exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onFailure() {
|
||||
withContext(NonCancellable) {
|
||||
Log.i(TAG, "Cleaning up!")
|
||||
|
||||
@@ -163,7 +163,7 @@ object NotificationUtil {
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
fun getInstallNotification(context: Context, app: App, content: String?): Notification {
|
||||
fun getInstallerStatusNotification(context: Context, app: App, content: String?): Notification {
|
||||
val builder =
|
||||
NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT).apply {
|
||||
color = context.getStyledAttributeColor(R.color.colorAccent)
|
||||
|
||||
Reference in New Issue
Block a user