Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

Commit efe4f71

Browse files
calrenMurat Yener
andauthored
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: Murat Yener <[email protected]>
1 parent 1c8fc23 commit efe4f71

File tree

9 files changed

+116
-79
lines changed

9 files changed

+116
-79
lines changed

WorkManagerSample/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ android {
2626
useSupportLibrary true
2727
}
2828
// Switching to Renderscript support provided by framework.
29-
minSdkVersion 18
29+
minSdkVersion build_versions.min_sdk
3030
targetSdkVersion build_versions.target_sdk
3131
versionCode 1
3232
versionName "1.0"

WorkManagerSample/app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,18 @@
3434
android:requestLegacyExternalStorage="true">
3535

3636
<provider
37-
android:name="androidx.work.impl.WorkManagerInitializer"
38-
android:authorities="${applicationId}.workmanager-init"
37+
android:name="androidx.startup.InitializationProvider"
38+
android:authorities="${applicationId}.androidx-startup"
3939
android:directBootAware="false"
4040
android:exported="false"
4141
android:multiprocess="true"
42-
tools:node="remove"
43-
tools:targetApi="n" />
42+
tools:targetApi="n"
43+
tools:node="merge">
44+
<meta-data
45+
android:name="androidx.work.WorkManagerInitializer"
46+
android:value="androidx.startup"
47+
tools:node="remove" />
48+
</provider>
4449

4550
<activity android:name=".SelectImageActivity">
4651
<intent-filter>

WorkManagerSample/lib/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ android {
2626
useSupportLibrary true
2727
}
2828
// Switching to Renderscript support provided by framework.
29-
minSdkVersion 18
29+
minSdkVersion build_versions.min_sdk
3030
targetSdkVersion build_versions.target_sdk
3131
versionCode 1
3232
versionName "1.0"

WorkManagerSample/lib/src/main/java/com/example/background/ImageOperations.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.work.ExistingWorkPolicy
2424
import androidx.work.ListenableWorker
2525
import androidx.work.OneTimeWorkRequest
2626
import androidx.work.OneTimeWorkRequestBuilder
27+
import androidx.work.OutOfQuotaPolicy
2728
import androidx.work.WorkContinuation
2829
import androidx.work.WorkManager
2930
import androidx.work.workDataOf
@@ -90,6 +91,7 @@ class ImageOperations(
9091
) =
9192
OneTimeWorkRequestBuilder<T>().apply {
9293
setInputData(inputData)
94+
setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
9395
if (!tag.isNullOrEmpty()) {
9496
addTag(tag)
9597
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (C) 2021 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:JvmName("NotificationUtils")
18+
19+
package com.example.background.workers
20+
21+
import android.annotation.TargetApi
22+
import android.app.Notification
23+
import android.app.NotificationChannel
24+
import android.app.NotificationManager
25+
import android.content.Context
26+
import android.os.Build
27+
import androidx.core.app.NotificationCompat
28+
import androidx.work.WorkManager
29+
import com.example.background.library.R
30+
import java.util.UUID
31+
32+
/**
33+
* Create the notification and required channel (O+) for running work in a foreground service.
34+
*/
35+
fun createNotification(context: Context, workRequestId: UUID, notificationTitle: String): Notification {
36+
val channelId = context.getString(R.string.notification_channel_id)
37+
val cancelText = context.getString(R.string.cancel_processing)
38+
val name = context.getString(R.string.channel_name)
39+
// This PendingIntent can be used to cancel the Worker.
40+
val cancelIntent = WorkManager.getInstance(context).createCancelPendingIntent(workRequestId)
41+
42+
val builder = NotificationCompat.Builder(context, channelId)
43+
.setContentTitle(notificationTitle)
44+
.setTicker(notificationTitle)
45+
.setSmallIcon(R.drawable.baseline_gradient)
46+
.setOngoing(true)
47+
.addAction(android.R.drawable.ic_delete, cancelText, cancelIntent)
48+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
49+
createNotificationChannel(context, channelId, name).also {
50+
builder.setChannelId(it.id)
51+
}
52+
}
53+
return builder.build()
54+
}
55+
56+
/**
57+
* Create the required notification channel for O+ devices.
58+
*/
59+
@TargetApi(Build.VERSION_CODES.O)
60+
fun createNotificationChannel(
61+
context: Context,
62+
channelId: String,
63+
name: String,
64+
notificationImportance: Int = NotificationManager.IMPORTANCE_HIGH
65+
): NotificationChannel {
66+
val notificationManager =
67+
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
68+
return NotificationChannel(
69+
channelId, name, notificationImportance
70+
).also { channel ->
71+
notificationManager.createNotificationChannel(channel)
72+
}
73+
}

WorkManagerSample/lib/src/main/java/com/example/background/workers/SaveImageToGalleryWorker.kt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ import android.net.Uri
2323
import android.provider.MediaStore
2424
import android.provider.MediaStore.Images.Media
2525
import android.util.Log
26+
import androidx.work.CoroutineWorker
2627
import androidx.work.Data
27-
import androidx.work.Worker
28+
import androidx.work.ForegroundInfo
2829
import androidx.work.WorkerParameters
2930
import com.example.background.Constants
31+
import com.example.background.library.R
3032
import java.text.SimpleDateFormat
3133
import java.util.Date
3234
import java.util.Locale
@@ -35,9 +37,10 @@ import java.util.Locale
3537
* Saves an output image to the [MediaStore].
3638
*/
3739
class SaveImageToGalleryWorker(appContext: Context, workerParams: WorkerParameters) :
38-
Worker(appContext, workerParams) {
40+
CoroutineWorker(appContext, workerParams) {
41+
42+
override suspend fun doWork(): Result {
3943

40-
override fun doWork(): Result {
4144
val resolver = applicationContext.contentResolver
4245
return try {
4346
val input = Uri.parse(inputData.getString(Constants.KEY_IMAGE_URI))
@@ -62,9 +65,19 @@ class SaveImageToGalleryWorker(appContext: Context, workerParams: WorkerParamete
6265
return Media.insertImage(
6366
resolver, bitmap, DATE_FORMATTER.format(Date()), TITLE
6467
)
68+
69+
}
70+
71+
override suspend fun getForegroundInfo(): ForegroundInfo {
72+
return ForegroundInfo(
73+
NOTIFICATION_ID, createNotification(applicationContext, id,
74+
applicationContext.getString(R.string.notification_title_saving_image)))
6575
}
6676

6777
companion object {
78+
// Use same notification id as BaseFilter worker to update existing notification. For a real
79+
// world app you might consider using a different id for each notification.
80+
private const val NOTIFICATION_ID = 1
6881
private const val TAG = "SvImageToGalleryWrkr"
6982
private const val TITLE = "Filtered Image"
7083
private val DATE_FORMATTER =

WorkManagerSample/lib/src/main/java/com/example/background/workers/filters/BaseFilterWorker.kt

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,17 @@
1616

1717
package com.example.background.workers.filters
1818

19-
import android.R.drawable
20-
import android.annotation.TargetApi
21-
import android.app.Notification
22-
import android.app.NotificationChannel
2319
import android.app.NotificationManager
2420
import android.content.Context
2521
import android.graphics.Bitmap
2622
import android.graphics.BitmapFactory
2723
import android.net.Uri
28-
import android.os.Build.VERSION
29-
import android.os.Build.VERSION_CODES
3024
import android.util.Log
31-
import androidx.annotation.StringRes
3225
import androidx.annotation.VisibleForTesting
33-
import androidx.core.app.NotificationCompat.Builder
34-
import androidx.work.ForegroundInfo
35-
import androidx.work.WorkManager
36-
import androidx.work.Worker
37-
import androidx.work.WorkerParameters
38-
import androidx.work.workDataOf
26+
import androidx.work.*
3927
import com.example.background.Constants
4028
import com.example.background.library.R
29+
import com.example.background.workers.createNotification
4130
import java.io.File
4231
import java.io.FileNotFoundException
4332
import java.io.FileOutputStream
@@ -46,16 +35,12 @@ import java.io.InputStream
4635
import java.util.UUID
4736

4837
abstract class BaseFilterWorker(context: Context, parameters: WorkerParameters) :
49-
Worker(context, parameters) {
38+
CoroutineWorker(context, parameters) {
5039

51-
private val notificationManager =
52-
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
53-
54-
override fun doWork(): Result {
40+
override suspend fun doWork(): Result {
5541
val resourceUri = inputData.getString(Constants.KEY_IMAGE_URI) ?:
5642
throw IllegalArgumentException("Invalid input uri")
5743
return try {
58-
setForegroundAsync(createForegroundInfo())
5944
val inputStream = inputStreamFor(applicationContext, resourceUri)
6045
val bitmap = BitmapFactory.decodeStream(inputStream)
6146
val output = applyFilter(bitmap)
@@ -109,58 +94,16 @@ abstract class BaseFilterWorker(context: Context, parameters: WorkerParameters)
10994
/**
11095
* Create ForegroundInfo required to run a Worker in a foreground service.
11196
*/
112-
private fun createForegroundInfo(): ForegroundInfo {
113-
// For a real world app you might want to use a different id for each Notification.
114-
val notificationId = 1
115-
return ForegroundInfo(notificationId, createNotification())
116-
}
117-
118-
/**
119-
* Create the notification and required channel (O+) for running work in a foreground service.
120-
*/
121-
private fun createNotification(): Notification {
122-
val channelId = getString(R.string.notification_channel_id)
123-
val title = getString(R.string.notification_title)
124-
val cancel = getString(R.string.cancel_processing)
125-
val name = getString(R.string.channel_name)
126-
// This PendingIntent can be used to cancel the Worker.
127-
val intent = WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
128-
129-
val builder = Builder(applicationContext, channelId)
130-
.setContentTitle(title)
131-
.setTicker(title)
132-
.setSmallIcon(R.drawable.baseline_gradient)
133-
.setOngoing(true)
134-
.addAction(drawable.ic_delete, cancel, intent)
135-
if (VERSION.SDK_INT >= VERSION_CODES.O) {
136-
createNotificationChannel(channelId, name).also {
137-
builder.setChannelId(it.id)
138-
}
139-
}
140-
return builder.build()
141-
}
142-
143-
144-
private fun getString(@StringRes id: Int) = applicationContext.getString(id)
145-
146-
/**
147-
* Create the required notification channel for O+ devices.
148-
*/
149-
@TargetApi(VERSION_CODES.O)
150-
private fun createNotificationChannel(
151-
channelId: String,
152-
name: String
153-
): NotificationChannel {
154-
return NotificationChannel(
155-
channelId, name, NotificationManager.IMPORTANCE_LOW
156-
).also { channel ->
157-
notificationManager.createNotificationChannel(channel)
158-
}
97+
override suspend fun getForegroundInfo(): ForegroundInfo {
98+
return ForegroundInfo(NOTIFICATION_ID, createNotification(applicationContext, id,
99+
applicationContext.getString(R.string.notification_title_filtering_image)))
159100
}
160101

161102
companion object {
162103
const val TAG = "BaseFilterWorker"
163104
const val ASSET_PREFIX = "file:///android_asset/"
105+
// For a real world app you might want to use a different id for each Notification.
106+
const val NOTIFICATION_ID = 1
164107

165108
/**
166109
* Creates an input stream which can be used to read the given `resourceUri`.

WorkManagerSample/lib/src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
<resources>
1919
<string name="notification_channel_id">WorkManagerSample</string>
20-
<string name="notification_title">WorkManager Sample</string>
20+
<string name="notification_title_filtering_image">WorkManager Sample: Filtering Image</string>
21+
<string name="notification_title_saving_image">WorkManager Sample: Saving Filtered Image</string>
2122
<string name="cancel_processing">Cancel processing</string>
2223
<string name="channel_name">WorkManager Sample</string>
2324
</resources>

WorkManagerSample/versions.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ versions.rxjava2 = "2.1.3"
6262
versions.timber = "4.7.1"
6363
versions.transition = "1.3.0"
6464
versions.truth = "1.0.1"
65-
versions.work = "2.6.0"
65+
versions.work = "2.7.0-rc01"
6666
ext.versions = versions
6767

6868
def build_versions = [:]
69-
build_versions.min_sdk = 14
70-
build_versions.compile_sdk = 29
69+
build_versions.min_sdk = 21
70+
build_versions.compile_sdk = 31
7171
build_versions.target_sdk = 29
7272
build_versions.build_tools = "29.0.3"
7373
ext.build_versions = build_versions

0 commit comments

Comments
 (0)