未验证 提交 efe4f716 编写于 作者: C Caren 提交者: GitHub

Update WorkManager sample to 2.7-rc (#1025)

* WorkManager library updated to 2.7.0-alpha01

* Upgrade workmanager to 2.7-beta01 (#1017)

* Upgrade workmanager to 2.7-beta01

* Remove extra equal sign

* Fix rebase errors

* Update SaveImageToGalleryWorker to be CoroutineWorker

* Add NotificationUtils class

* Update WorkManager version to 2.7.0-rc01

* Move notification ID to companion object and use 31 as compile_sdk version

* Remove wildcard imports and implement more descriptive variable names in NotificationUtils

* Make notificationImportance an argument with default value when creating notification channel
Co-authored-by: NMurat Yener <yenerm@google.com>
上级 1c8fc23b
......@@ -26,7 +26,7 @@ android {
useSupportLibrary true
}
// Switching to Renderscript support provided by framework.
minSdkVersion 18
minSdkVersion build_versions.min_sdk
targetSdkVersion build_versions.target_sdk
versionCode 1
versionName "1.0"
......
......@@ -34,13 +34,18 @@
android:requestLegacyExternalStorage="true">
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:directBootAware="false"
android:exported="false"
android:multiprocess="true"
tools:node="remove"
tools:targetApi="n" />
tools:targetApi="n"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
<activity android:name=".SelectImageActivity">
<intent-filter>
......
......@@ -26,7 +26,7 @@ android {
useSupportLibrary true
}
// Switching to Renderscript support provided by framework.
minSdkVersion 18
minSdkVersion build_versions.min_sdk
targetSdkVersion build_versions.target_sdk
versionCode 1
versionName "1.0"
......
......@@ -24,6 +24,7 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.ListenableWorker
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkContinuation
import androidx.work.WorkManager
import androidx.work.workDataOf
......@@ -90,6 +91,7 @@ class ImageOperations(
) =
OneTimeWorkRequestBuilder<T>().apply {
setInputData(inputData)
setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
if (!tag.isNullOrEmpty()) {
addTag(tag)
}
......
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:JvmName("NotificationUtils")
package com.example.background.workers
import android.annotation.TargetApi
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.work.WorkManager
import com.example.background.library.R
import java.util.UUID
/**
* Create the notification and required channel (O+) for running work in a foreground service.
*/
fun createNotification(context: Context, workRequestId: UUID, notificationTitle: String): Notification {
val channelId = context.getString(R.string.notification_channel_id)
val cancelText = context.getString(R.string.cancel_processing)
val name = context.getString(R.string.channel_name)
// This PendingIntent can be used to cancel the Worker.
val cancelIntent = WorkManager.getInstance(context).createCancelPendingIntent(workRequestId)
val builder = NotificationCompat.Builder(context, channelId)
.setContentTitle(notificationTitle)
.setTicker(notificationTitle)
.setSmallIcon(R.drawable.baseline_gradient)
.setOngoing(true)
.addAction(android.R.drawable.ic_delete, cancelText, cancelIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(context, channelId, name).also {
builder.setChannelId(it.id)
}
}
return builder.build()
}
/**
* Create the required notification channel for O+ devices.
*/
@TargetApi(Build.VERSION_CODES.O)
fun createNotificationChannel(
context: Context,
channelId: String,
name: String,
notificationImportance: Int = NotificationManager.IMPORTANCE_HIGH
): NotificationChannel {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
return NotificationChannel(
channelId, name, notificationImportance
).also { channel ->
notificationManager.createNotificationChannel(channel)
}
}
......@@ -23,10 +23,12 @@ import android.net.Uri
import android.provider.MediaStore
import android.provider.MediaStore.Images.Media
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.Worker
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import com.example.background.Constants
import com.example.background.library.R
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
......@@ -35,9 +37,10 @@ import java.util.Locale
* Saves an output image to the [MediaStore].
*/
class SaveImageToGalleryWorker(appContext: Context, workerParams: WorkerParameters) :
Worker(appContext, workerParams) {
CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
override fun doWork(): Result {
val resolver = applicationContext.contentResolver
return try {
val input = Uri.parse(inputData.getString(Constants.KEY_IMAGE_URI))
......@@ -62,9 +65,19 @@ class SaveImageToGalleryWorker(appContext: Context, workerParams: WorkerParamete
return Media.insertImage(
resolver, bitmap, DATE_FORMATTER.format(Date()), TITLE
)
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID, createNotification(applicationContext, id,
applicationContext.getString(R.string.notification_title_saving_image)))
}
companion object {
// Use same notification id as BaseFilter worker to update existing notification. For a real
// world app you might consider using a different id for each notification.
private const val NOTIFICATION_ID = 1
private const val TAG = "SvImageToGalleryWrkr"
private const val TITLE = "Filtered Image"
private val DATE_FORMATTER =
......
......@@ -16,28 +16,17 @@
package com.example.background.workers.filters
import android.R.drawable
import android.annotation.TargetApi
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.util.Log
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.core.app.NotificationCompat.Builder
import androidx.work.ForegroundInfo
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import androidx.work.*
import com.example.background.Constants
import com.example.background.library.R
import com.example.background.workers.createNotification
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
......@@ -46,16 +35,12 @@ import java.io.InputStream
import java.util.UUID
abstract class BaseFilterWorker(context: Context, parameters: WorkerParameters) :
Worker(context, parameters) {
CoroutineWorker(context, parameters) {
private val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
override fun doWork(): Result {
override suspend fun doWork(): Result {
val resourceUri = inputData.getString(Constants.KEY_IMAGE_URI) ?:
throw IllegalArgumentException("Invalid input uri")
return try {
setForegroundAsync(createForegroundInfo())
val inputStream = inputStreamFor(applicationContext, resourceUri)
val bitmap = BitmapFactory.decodeStream(inputStream)
val output = applyFilter(bitmap)
......@@ -109,58 +94,16 @@ abstract class BaseFilterWorker(context: Context, parameters: WorkerParameters)
/**
* Create ForegroundInfo required to run a Worker in a foreground service.
*/
private fun createForegroundInfo(): ForegroundInfo {
// For a real world app you might want to use a different id for each Notification.
val notificationId = 1
return ForegroundInfo(notificationId, createNotification())
}
/**
* Create the notification and required channel (O+) for running work in a foreground service.
*/
private fun createNotification(): Notification {
val channelId = getString(R.string.notification_channel_id)
val title = getString(R.string.notification_title)
val cancel = getString(R.string.cancel_processing)
val name = getString(R.string.channel_name)
// This PendingIntent can be used to cancel the Worker.
val intent = WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
val builder = Builder(applicationContext, channelId)
.setContentTitle(title)
.setTicker(title)
.setSmallIcon(R.drawable.baseline_gradient)
.setOngoing(true)
.addAction(drawable.ic_delete, cancel, intent)
if (VERSION.SDK_INT >= VERSION_CODES.O) {
createNotificationChannel(channelId, name).also {
builder.setChannelId(it.id)
}
}
return builder.build()
}
private fun getString(@StringRes id: Int) = applicationContext.getString(id)
/**
* Create the required notification channel for O+ devices.
*/
@TargetApi(VERSION_CODES.O)
private fun createNotificationChannel(
channelId: String,
name: String
): NotificationChannel {
return NotificationChannel(
channelId, name, NotificationManager.IMPORTANCE_LOW
).also { channel ->
notificationManager.createNotificationChannel(channel)
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(NOTIFICATION_ID, createNotification(applicationContext, id,
applicationContext.getString(R.string.notification_title_filtering_image)))
}
companion object {
const val TAG = "BaseFilterWorker"
const val ASSET_PREFIX = "file:///android_asset/"
// For a real world app you might want to use a different id for each Notification.
const val NOTIFICATION_ID = 1
/**
* Creates an input stream which can be used to read the given `resourceUri`.
......
......@@ -17,7 +17,8 @@
<resources>
<string name="notification_channel_id">WorkManagerSample</string>
<string name="notification_title">WorkManager Sample</string>
<string name="notification_title_filtering_image">WorkManager Sample: Filtering Image</string>
<string name="notification_title_saving_image">WorkManager Sample: Saving Filtered Image</string>
<string name="cancel_processing">Cancel processing</string>
<string name="channel_name">WorkManager Sample</string>
</resources>
\ No newline at end of file
......@@ -62,12 +62,12 @@ versions.rxjava2 = "2.1.3"
versions.timber = "4.7.1"
versions.transition = "1.3.0"
versions.truth = "1.0.1"
versions.work = "2.6.0"
versions.work = "2.7.0-rc01"
ext.versions = versions
def build_versions = [:]
build_versions.min_sdk = 14
build_versions.compile_sdk = 29
build_versions.min_sdk = 21
build_versions.compile_sdk = 31
build_versions.target_sdk = 29
build_versions.build_tools = "29.0.3"
ext.build_versions = build_versions
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册