ExportWorker: Show notification on export status when finished
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package com.aurora.store.data.work
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
@@ -11,6 +13,9 @@ import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.OutOfQuotaPolicy
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import com.aurora.gplayapi.data.models.App
|
||||
import com.aurora.store.data.room.download.Download
|
||||
import com.aurora.store.util.NotificationUtil
|
||||
import com.aurora.store.util.PackageUtil.getPackageInfo
|
||||
import com.aurora.store.util.PathUtil
|
||||
import dagger.assisted.Assisted
|
||||
@@ -35,17 +40,19 @@ class ExportWorker @AssistedInject constructor(
|
||||
private const val IS_DOWNLOAD = "IS_DOWNLOAD"
|
||||
private const val PACKAGE_NAME = "PACKAGE_NAME"
|
||||
private const val VERSION_CODE = "VERSION_CODE"
|
||||
private const val DISPLAY_NAME = "DISPLAY_NAME"
|
||||
|
||||
/**
|
||||
* Exports the installed package to the given URI
|
||||
* @param packageName packageName of the app to export
|
||||
* @param app App to export
|
||||
* @see [ExportWorker]
|
||||
*/
|
||||
fun exportInstalledApp(context: Context, packageName: String, uri: Uri) {
|
||||
fun exportInstalledApp(context: Context, app: App, uri: Uri) {
|
||||
val inputData = Data.Builder()
|
||||
.putBoolean(IS_DOWNLOAD, false)
|
||||
.putString(URI, uri.toString())
|
||||
.putString(PACKAGE_NAME, packageName)
|
||||
.putString(DISPLAY_NAME, app.displayName)
|
||||
.putString(PACKAGE_NAME, app.packageName)
|
||||
.build()
|
||||
|
||||
val oneTimeWorkRequest = OneTimeWorkRequestBuilder<ExportWorker>()
|
||||
@@ -53,22 +60,22 @@ class ExportWorker @AssistedInject constructor(
|
||||
.setExpedited(OutOfQuotaPolicy.DROP_WORK_REQUEST)
|
||||
.build()
|
||||
|
||||
Log.i(TAG, "Exporting $packageName")
|
||||
Log.i(TAG, "Exporting $app.packageName")
|
||||
WorkManager.getInstance(context).enqueue(oneTimeWorkRequest)
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the given download to the URI
|
||||
* @param packageName Name of the package to export
|
||||
* @param versionCode version of the package
|
||||
* @param download Download to export
|
||||
* @see [ExportWorker]
|
||||
*/
|
||||
fun exportDownloadedApp(context: Context, packageName: String, versionCode: Int, uri: Uri) {
|
||||
fun exportDownloadedApp(context: Context, download: Download, uri: Uri) {
|
||||
val inputData = Data.Builder()
|
||||
.putBoolean(IS_DOWNLOAD, true)
|
||||
.putString(URI, uri.toString())
|
||||
.putString(PACKAGE_NAME, packageName)
|
||||
.putInt(VERSION_CODE, versionCode)
|
||||
.putString(DISPLAY_NAME, download.displayName)
|
||||
.putString(PACKAGE_NAME, download.packageName)
|
||||
.putInt(VERSION_CODE, download.versionCode)
|
||||
.build()
|
||||
|
||||
val oneTimeWorkRequest = OneTimeWorkRequestBuilder<ExportWorker>()
|
||||
@@ -76,19 +83,27 @@ class ExportWorker @AssistedInject constructor(
|
||||
.setExpedited(OutOfQuotaPolicy.DROP_WORK_REQUEST)
|
||||
.build()
|
||||
|
||||
Log.i(TAG, "Exporting download for ${packageName}/${versionCode}")
|
||||
Log.i(TAG, "Exporting download for ${download.packageName}/${download.versionCode}")
|
||||
WorkManager.getInstance(context).enqueue(oneTimeWorkRequest)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var notificationManager: NotificationManager
|
||||
private val NOTIFICATION_ID = 500
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val isDownload = inputData.getBoolean(IS_DOWNLOAD, false)
|
||||
val uri = Uri.parse(inputData.getString(URI))
|
||||
val packageName = inputData.getString(PACKAGE_NAME)
|
||||
val displayName = inputData.getString(DISPLAY_NAME)
|
||||
val versionCode = inputData.getInt(VERSION_CODE, -1)
|
||||
|
||||
notificationManager =
|
||||
appContext.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (packageName.isNullOrEmpty() || isDownload && versionCode == -1) {
|
||||
Log.e(TAG, "Input data is corrupt, bailing out!")
|
||||
notifyStatus(displayName?: String(), uri, false)
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
@@ -98,14 +113,28 @@ class ExportWorker @AssistedInject constructor(
|
||||
} else {
|
||||
copyInstalledApp(packageName, uri)
|
||||
}
|
||||
notifyStatus(displayName ?: packageName, uri)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to export $packageName", exception)
|
||||
notifyStatus(displayName?: packageName, uri, false)
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun notifyStatus(packageName: String, uri: Uri, success: Boolean = true) {
|
||||
notificationManager.notify(
|
||||
NOTIFICATION_ID,
|
||||
NotificationUtil.getExportStatusNotification(
|
||||
appContext,
|
||||
packageName,
|
||||
uri,
|
||||
success
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun copyInstalledApp(packageName: String, uri: Uri) {
|
||||
val packageInfo = getPackageInfo(appContext, packageName, PackageManager.GET_META_DATA)
|
||||
val fileList: MutableList<File?> = mutableListOf()
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.PendingIntentCompat
|
||||
@@ -250,6 +251,64 @@ object NotificationUtil {
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getExportStatusNotification(
|
||||
context: Context,
|
||||
displayName: String,
|
||||
uri: Uri,
|
||||
success: Boolean
|
||||
): Notification {
|
||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||
setDataAndType(uri, "application/zip")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
putExtra(Intent.EXTRA_STREAM, uri)
|
||||
}
|
||||
val pendingIntent = PendingIntentCompat.getActivity(
|
||||
context,
|
||||
UUID.randomUUID().hashCode(),
|
||||
Intent.createChooser(intent, null),
|
||||
PendingIntent.FLAG_CANCEL_CURRENT,
|
||||
false
|
||||
)
|
||||
|
||||
val content = if (success) {
|
||||
context.getString(R.string.export_app_summary_success)
|
||||
} else {
|
||||
context.getString(R.string.export_app_summary_fail)
|
||||
}
|
||||
|
||||
val builder = NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT)
|
||||
.setSmallIcon(R.drawable.ic_file_copy)
|
||||
.setColor(context.getStyledAttributeColor(R.color.colorAccent))
|
||||
.setContentTitle(displayName).setContentText(content)
|
||||
.setContentIntent(getContentIntentForExport(context, uri))
|
||||
.setAutoCancel(true)
|
||||
|
||||
if (success) {
|
||||
builder.addAction(
|
||||
NotificationCompat.Action.Builder(
|
||||
R.drawable.ic_share,
|
||||
context.getString(R.string.action_share),
|
||||
pendingIntent
|
||||
).build()
|
||||
)
|
||||
}
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
private fun getContentIntentForExport(context: Context, uri: Uri): PendingIntent? {
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(uri, "application/zip")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
}
|
||||
return PendingIntentCompat.getActivity(
|
||||
context,
|
||||
UUID.randomUUID().hashCode(),
|
||||
intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
private fun getContentIntentForDetails(context: Context, packageName: String): PendingIntent {
|
||||
return NavDeepLinkBuilder(context)
|
||||
.setGraph(R.navigation.mobile_navigation)
|
||||
|
||||
@@ -57,7 +57,7 @@ class AppMenuSheet : BottomSheetDialogFragment(R.layout.sheet_app_menu) {
|
||||
private val requestDocumentCreation =
|
||||
registerForActivityResult(ActivityResultContracts.CreateDocument(exportMimeType)) {
|
||||
if (it != null) {
|
||||
viewModel.copyInstalledApp(requireContext(), args.app.packageName, it)
|
||||
viewModel.copyInstalledApp(requireContext(), args.app, it)
|
||||
} else {
|
||||
toast(R.string.failed_apk_export)
|
||||
}
|
||||
|
||||
@@ -59,12 +59,7 @@ class DownloadMenuSheet : BottomSheetDialogFragment(R.layout.sheet_download_menu
|
||||
private val requestDocumentCreation =
|
||||
registerForActivityResult(ActivityResultContracts.CreateDocument(exportMimeType)) {
|
||||
if (it != null) {
|
||||
viewModel.copyDownloadedApp(
|
||||
requireContext(),
|
||||
args.download.packageName,
|
||||
args.download.versionCode,
|
||||
it
|
||||
)
|
||||
viewModel.copyDownloadedApp(requireContext(), args.download, it)
|
||||
} else {
|
||||
toast(R.string.failed_apk_export)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.aurora.gplayapi.data.models.App
|
||||
import com.aurora.gplayapi.helpers.PurchaseHelper
|
||||
import com.aurora.store.data.event.BusEvent
|
||||
import com.aurora.store.data.providers.AuthProvider
|
||||
import com.aurora.store.data.room.download.Download
|
||||
import com.aurora.store.data.work.ExportWorker
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
@@ -45,11 +46,11 @@ class SheetsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun copyInstalledApp(context: Context, packageName: String, uri: Uri) {
|
||||
ExportWorker.exportInstalledApp(context, packageName, uri)
|
||||
fun copyInstalledApp(context: Context, app: App, uri: Uri) {
|
||||
ExportWorker.exportInstalledApp(context, app, uri)
|
||||
}
|
||||
|
||||
fun copyDownloadedApp(context: Context, packageName: String, versionCode: Int, uri: Uri) {
|
||||
ExportWorker.exportDownloadedApp(context, packageName, versionCode, uri)
|
||||
fun copyDownloadedApp(context: Context, download: Download, uri: Uri) {
|
||||
ExportWorker.exportDownloadedApp(context, download, uri)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user