In Progress
Status Update
Comments
ra...@google.com <ra...@google.com> #2
Seems like it happens on API 21-22 too.
st...@deliveroo.co.uk <st...@deliveroo.co.uk> #3
This is expected. You are calling: enqueueUniquePeriodicWork() with an ExistingPeriodicWorkPolicy.REPLACE. This will cancel running work, and kick off new instances of all Workers.
https://github.com/rubensousa/WorkManagerKitkatBug/blob/master/app/src/main/java/com/github/rubensousa/workkitkatbug/MainActivity.kt#L24
da...@google.com <da...@google.com> #4
I just ran the sample again and now the behaviour is different for some weird reason. I forgot to mention that I only used REPLACE to test this properly. Because it also happens with KEEP.
ra...@google.com <ra...@google.com> #5
And shouldn't the behaviour be consistent across all Android versions?
st...@deliveroo.co.uk <st...@deliveroo.co.uk> #6
We don't see any issues with KEEP. If you have a way for us to reproduce any problems, please send us the appropriate instructions.
st...@deliveroo.co.uk <st...@deliveroo.co.uk> #7
Ok, I found something odd. Seems like setRequiredNetworkType(NetworkType.UNMETERED) causes this for some reason. I'm going to update the sample so you can review this again. Please, reopen this since it's not intended behavior.
va...@gmail.com <va...@gmail.com> #8
This happens on a fresh install with KEEP instead of REPLACE if the constraints have setRequiredNetworkType(NetworkType.UNMETERED). I've updated the sample
da...@google.com <da...@google.com> #9
"And shouldn't the behaviour be consistent across all Android versions?"
The behavior is actually consistent. Once your worker starts running, if we get a call to enqueueUniquePeriodicWork a new work request and with ExistingPeriodicWorkPolicy.REPLACE we will stop existing work.
If your Worker was not running, then there is nothing to cancel. This is just a matter of timing.
The behavior is actually consistent. Once your worker starts running, if we get a call to enqueueUniquePeriodicWork a new work request and with ExistingPeriodicWorkPolicy.REPLACE we will stop existing work.
If your Worker was not running, then there is nothing to cancel. This is just a matter of timing.
ap...@google.com <ap...@google.com> #10
I'm not arguing against the expected behavior of ExistingPeriodicWorkPolicy.REPLACE, since that's working as intended. But this is happening only when setRequiredNetworkType(NetworkType.UNMETERED) is used while having ExistingPeriodicWorkPolicy.KEEP.
ap...@google.com <ap...@google.com> #11
Can you send us an updated sample ?
rw...@gmail.com <rw...@gmail.com> #12
Looks like you have updated the sample, let me take another look.
Description
Version used: 2.9.0
Devices/Android versions reproduced on: API 34
When we target API 34, WorkManager is crashing our application on startup if the "location" permissions are removed whilst the application is running.
Everything works fine whilst the application has the "location" permissions. When the "location" permissions are removed (whilst the application is running), the OS is killing the application (OS behaviour) and because SystemForegroundService is a STICKY service, the OS tries to restart the service which causes a security exception because the "location" permissions are no longer present.
This is a realistic user scenario which will happen many times in our production app. We can not prevent our application from crashing as this relates to the STICKY SystemForegroundService. Our application, can check the "location" permissions before scheduling the "worker", but we have no control over the user removing the "location" permissions after the "worker" has been scheduled by the WorkManager.
This behaviour only happens with WorkManager when targeting API 34 as per the restrictions documented here:
Here is the crash we are seeing on application startup:
Java.lang.SecurityException: Starting FGS with type location callerApp=ProcessRecord{34bbf76 32120:com.deliveroo.driverapp.test/u0a190} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_LOCATION] any of the permissions allOf=false [android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION] and the app must be in the eligible state/exemptions to access the foreground only permission
We are using the WorkManager to run a CoroutineWorker which accesses the device location. We are scheduling the Worker as follows:
val request = OneTimeWorkRequest.Builder(worker.java)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(
ExistingWorkPolicy.KEEP,
request,
)
We are specifying FOREGROUND_SERVICE_TYPE_LOCATION in the ForegroundInfo:
ForegroundInfo(ONLINE_NOTIFICATION_ID, notificationsManager.onlineNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION)
Our Android manifest specifies the "location" foregroundServiceType:
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="location"/>
As stated above, everything works fine until the user removes the "location" permissions after the "worker" has started. Then the OS kills our application and the OS tries to recover the STICKY SystemForegroundService which crashes because the app no longer as "location" permissions.
Please can you advise how we can avoid WorkManager crashing our application in the above scenario.