In our activity we use WorkManager to run a quick syncronization job through a coroutineworker:
WorkManager.getInstance(this@MainActivity)
.enqueue(MySyncWorker.getWorkRequest())
The workrequest in CoroutineWorker:
class MySyncWorker(
private val context: Context,
parameters: WorkerParameters,
private val mySynchronizer: MySynchronizer,
) : CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
try {
// setforeground is not needed for expedited work.
// Older SDKs cannot run jobs as expedited and needs the foreground call.
setForeground(createForegroundInfo())
mySynchronizer.sync()
} catch (e: Exception) {
//log failure
return Result.failure()
}
return Result.success()
}
//Required for expedited work
override suspend fun getForegroundInfo(): ForegroundInfo {
return createForegroundInfo()
}
private fun createForegroundInfo(): ForegroundInfo {
// skipping details on notification stuff
return ForegroundInfo(NOTIFICATION_ID, notification)
}
companion object {
fun getWorkRequest() : OneTimeWorkRequest {
return OneTimeWorkRequestBuilder<MySyncWorker>()
.setExpedited(OutOfQuotaPolicy.DROP_WORK_REQUEST)
.build()
}
}
}
This was working ok on compile/target v 31 and with work version 2.7.1.
We did some upgrades to after upgrade to compileVersion = 34 targetVersion = 33
implementation "androidx.work:work-runtime-ktx:2.8.1"`
After this, building on an Android11 gives the following when the sync is called:
WM-WorkerWrapper Work failed because it threw an exception/error
java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.SecurityException: Neither user 10363 nor current process has android.permission.WAKE_LOCK.
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:317)
at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.util.concurrent.ExecutionException: java.lang.SecurityException: Neither user 10363 nor current process has android.permission.WAKE_LOCK.
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$1.run(WorkerWrapper.java:298)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8653)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: java.lang.SecurityException: Neither user 10363 nor current process has android.permission.WAKE_LOCK.
at android.os.Parcel.createExceptionOrNull(Parcel.java:2386)
at android.os.Parcel.createException(Parcel.java:2370)
at android.os.Parcel.readException(Parcel.java:2353)
at android.os.Parcel.readException(Parcel.java:2295)
at android.os.IPowerManager$Stub$Proxy.acquireWakeLock(IPowerManager.java:1354)
at android.os.PowerManager$WakeLock.acquireLocked(PowerManager.java:3449)
at android.os.PowerManager$WakeLock.acquire(PowerManager.java:3415)
at androidx.work.impl.Processor.startForeground(Processor.java:199)
at androidx.work.impl.utils.WorkForegroundUpdater$1.run(WorkForegroundUpdater.java:100)
at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: android.os.RemoteException: Remote stack trace:
at android.app.ContextImpl.enforce(ContextImpl.java:2115)
at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:2143)
at com.android.server.power.PowerManagerService$BinderService.acquireWakeLock(PowerManagerService.java:8357)
at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:630)
at android.os.Binder.execTransactInternal(Binder.java:119
The manifest contains the line:
<uses-permission android:name="android.permission.WAKE_LOCK" />
However, the merged manifest file shows
<uses-permission
android:maxSdkVersion = 25
android:name="android.permission.WAKE_LOCK" />
Our minSdk is 26. Why are we seeing this missing permission error, and how can we get our sync to work? On an Android13 test device, this error is not seen.
As stated in question, the merged manifest had a maxSdkVersion set on the WAKE_LOCK permission. Turns out this had nothing to do with implementation of worker, a permission override was introduced from Chucker library:
debugImplementation 'com.github.chuckerteam.chucker:library:4.0.0'
releaseImplementation 'com.github.chuckerteam.chucker:library-no-op:4.0.0'
Apparently, a maxSdkVersion for this permission set in Chucker manifest overrides the permission setting from app manifest. Solution is to add to app manifest:
<uses-permission
android:name="android.permission.WAKE_LOCK"
tools:node="replace"/>
See also this issue reported to Chucker repo.