From 960d178bb198f6e94fc157f56637aa2d3380275d Mon Sep 17 00:00:00 2001 From: Richard Banasiak Date: Sun, 27 Dec 2020 16:33:15 -0600 Subject: [PATCH] Refactored to use JobIntentService for artwork download --- app/src/main/AndroidManifest.xml | 3 +- .../android/muzeisaver/MuzeiSaverApp.kt | 22 +++---- .../muzeisaver/download/DownloadActivity.kt | 4 +- .../muzeisaver/download/DownloadService.kt | 60 ++++++++++++------- .../quicksettings/QuickSettingsDialog.kt | 2 - app/src/main/res/values/strings.xml | 3 +- 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 28a9da6..874f690 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" package="com.banasiak.android.muzeisaver"> - + = Build.VERSION_CODES.M - private val isAndroidO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - - @SuppressLint("NewApi") override fun onCreate() { super.onCreate() - if (isAndroidO) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val notificationManager = NotificationManagerCompat.from(this) val notificationChannel = NotificationChannel( - DownloadService.NOTIFICATION_ID.toString(), - getString(R.string.download_service), - NotificationManager.IMPORTANCE_LOW) + DownloadService.DOWNLOAD_COMPLETE_ID.toString(), + getString(R.string.download_complete), + NotificationManager.IMPORTANCE_HIGH) notificationManager.createNotificationChannels(listOf(notificationChannel)) } @@ -32,16 +26,18 @@ class MuzeiSaverApp : Application() { Timber.plant(Timber.DebugTree()) StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() .detectNetwork() - .also { - if (isAndroidM) it.detectResourceMismatches() - if (isAndroidO) it.detectUnbufferedIo() + .apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) detectResourceMismatches() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) detectUnbufferedIo() } .penaltyLog() + .penaltyDeath() .build()) StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() + .penaltyDeath() .build()) } } diff --git a/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadActivity.kt b/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadActivity.kt index e8e3958..cd68504 100644 --- a/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadActivity.kt +++ b/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadActivity.kt @@ -37,12 +37,12 @@ class DownloadActivity : AppCompatActivity() { showErrorAndFinish(R.string.unable_to_save) return } - Intent(this, DownloadService::class.java) + val intent = Intent() .also { it.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION it.data = data?.data - startService(it) } + DownloadService.enqueueWork(this, intent) finish() } diff --git a/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadService.kt b/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadService.kt index 0a84450..96a45b5 100644 --- a/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadService.kt +++ b/app/src/main/java/com/banasiak/android/muzeisaver/download/DownloadService.kt @@ -1,37 +1,35 @@ package com.banasiak.android.muzeisaver.download -import android.app.IntentService +import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.ImageDecoder import android.net.Uri -import android.os.Handler -import android.os.Looper -import android.widget.Toast +import android.os.Build import androidx.annotation.StringRes +import androidx.core.app.JobIntentService import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat import androidx.core.content.res.ResourcesCompat import com.banasiak.android.muzeisaver.R import com.google.android.apps.muzei.api.MuzeiContract import timber.log.Timber -class DownloadService : IntentService("DownloadService") { - +class DownloadService : JobIntentService() { companion object { - const val NOTIFICATION_ID = 62180 + const val DOWNLOAD_COMPLETE_ID = 62181 + private const val JOB_ID = 1000 + private const val NOTIFICATION_TIMEOUT = 5 * 1000L //5 seconds + + fun enqueueWork(context: Context, intent: Intent) { + enqueueWork(context, DownloadService::class.java, JOB_ID, intent) + } } - override fun onHandleIntent(intent: Intent?) { - val data = requireNotNull(intent?.data) { "File URI must be provided" } - val notification = NotificationCompat.Builder(this, NOTIFICATION_ID.toString()) - .setSmallIcon(R.drawable.ic_file_download) - .setColor(ResourcesCompat.getColor(resources, R.color.ic_launcher_background, null)) - .setContentTitle(getString(R.string.downloading_artwork)) - .setProgress(0, 0, true) - .build() - startForeground(NOTIFICATION_ID, notification) + override fun onHandleWork(intent: Intent) { + val data = requireNotNull(intent.data) { "Content URI must be provided" } downloadArtwork(data) - stopForeground(true) } private fun downloadArtwork(fileUri: Uri) { @@ -39,12 +37,12 @@ class DownloadService : IntentService("DownloadService") { BitmapFactory.decodeStream(it) } if (bitmap == null) { - showToast(message = R.string.unable_to_save, isError = true) + notify(message = R.string.unable_to_save) return } when (saveBitmapToFile(fileUri, bitmap)) { - true -> showToast(message = R.string.success) - false -> showToast(message = R.string.unable_to_save, isError = true) + true -> notify(message = R.string.success, uri = fileUri) + false -> notify(message = R.string.unable_to_save) } } @@ -61,9 +59,25 @@ class DownloadService : IntentService("DownloadService") { } } - private fun showToast(@StringRes message: Int, isError: Boolean = false) { - if (isError) Timber.e(getString(message)) else Timber.i(getString(message)) - Handler(Looper.getMainLooper()).post { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } + private fun notify(@StringRes message: Int, uri: Uri? = null) { + if (uri == null) Timber.e(getString(message)) else Timber.i(getString(message)) + val notification = NotificationCompat.Builder(this, DOWNLOAD_COMPLETE_ID.toString()) + .setSmallIcon(R.drawable.ic_file_download) + .setColor(ResourcesCompat.getColor(resources, R.color.ic_launcher_background, null)) + .setContentTitle(getString(R.string.app_name)) + .setContentText(getString(message)) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setTimeoutAfter(NOTIFICATION_TIMEOUT) + .apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && uri != null) { + setLargeIcon(ImageDecoder.decodeBitmap(ImageDecoder.createSource(contentResolver, uri))) + } + } + .build() + + NotificationManagerCompat.from(this).apply { + notify(DOWNLOAD_COMPLETE_ID, notification) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/banasiak/android/muzeisaver/quicksettings/QuickSettingsDialog.kt b/app/src/main/java/com/banasiak/android/muzeisaver/quicksettings/QuickSettingsDialog.kt index 1bab683..c2d7be6 100644 --- a/app/src/main/java/com/banasiak/android/muzeisaver/quicksettings/QuickSettingsDialog.kt +++ b/app/src/main/java/com/banasiak/android/muzeisaver/quicksettings/QuickSettingsDialog.kt @@ -11,7 +11,6 @@ import androidx.appcompat.app.AppCompatDialogFragment import com.banasiak.android.muzeisaver.R class QuickSettingsDialog : AppCompatDialogFragment() { - interface DialogListener { fun onPositiveClick() fun onNegativeClick() @@ -34,7 +33,6 @@ class QuickSettingsDialog : AppCompatDialogFragment() { } dialogView = LayoutInflater.from(_context).inflate(R.layout.dialog, null) - val alertBuilder = AlertDialog.Builder(_context).apply { setView(dialogView) setPositiveButton(R.string.show) { _, _ -> listener.onPositiveClick() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1c3e07c..f0df86c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,8 +1,7 @@ Muzei Saver - Downloading Muzei Artwork - Download Service + Download Complete Hide Congrats on finding the quick settings tile! From now on tapping this tile will prompt you to save the current Muzei artwork.\n\nWould you like to remove the launcher icon from the app drawer? Long press this tile if you change your mind.\n\nNote: This may not work on all versions of Android and a device restart might be necessary for the change to take effect. Launcher Icon Disabled