Status Update
Comments
al...@google.com <al...@google.com> #2
I have read that WorkManager 2.7.0 is needed if an app targets API 31/Android 12, and in order to do that, I have added setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
to my OneTimeWorkRequestBuilder
and added the necessary changes in the AndroidManifest as well. Now running my app I've encountered the following error:
java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Expedited WorkRequests require a ListenableWorker to provide an implementation for `getForegroundInfoAsync()`
So I tried looking up info on how to do implement this, and found no examples available from official Google sources (Github, developers.android.com, changelog, etc), but found this
My question is how do you implement the said getForegroundInfoAsync
for RxWorker
when getForegroundInfoAsync
has to return ListenableFuture<ForegroundInfo
>--reading the docs it seems I have to add Guava to my app to do this? Since the docs for ListenableFuture says to Avoid implementing ListenableFuture from scratch. If you can't get by with the standard implementations, prefer to derive a new Future instance with the methods in Futures or, if necessary, to extend AbstractFuture
.
py...@gmail.com <py...@gmail.com> #3
I also have tried adding a SettableFuture
but it is annotated with @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
ap...@google.com <ap...@google.com> #4
Nvm, I just annotated my implementation of getForegroundInfoAsync
with @SuppressLint("RestrictedApi")
and created a SettableFuture
. It seems to work well.
lb...@gmail.com <lb...@gmail.com> #5
You're right, we should add Rx support for this method.
In meanwhile, you can use SettableFuture
and allows you avoid dependency on restricted APIs.
ch...@gmail.com <ch...@gmail.com> #6
Thanks for showing that callback. Honestly this whole getForegroundInfoAsync
is still unclear to me--since I'm using RxWorker, I usually create a notification inside createWork
and when the work is ongoing, I display a notification with progress bar via doOnSubscribe
, something like this:
api.doSomeWork()
.doOnSubscribe {
// display notification with progress bar
setForegroundAsync(ForegroundInfo(notificationId, notificationBuilder.build()))
}
So how getForegroundInfoAsync
fits into this, I don't understand. The effect of implementing getForegroundInfoAsync
is that I actually get two notifications, the one that displays a progress bar that's already full, and another one that's actually updated.
Edit: actually never mind, getForegroundInfoAsync
has nothing to do with having two notifs. Just figured it out and getForegroundInfoAsync
is called before createWork
.
al...@google.com <al...@google.com> #7
Branch: androidx-main
commit 4d0b5f22951dd44cd4c4ba646fe5ad7a3e87c280
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Fri Nov 05 17:00:43 2021
RxJava2: RxJava wrapper around getForegroundInfoAsync
Test: RxForegroundInfoTest
bug:203851459
Relnote: "
RxWorker has now `getForegroundInfo` returing`Single` that
can be used instead of `getForegroundInfoAsync` that returns
`ListenableFuture`.
"
Change-Id: I21c91cd5db57e85bf1aaa7e1596e2287ab44675c
M work/work-rxjava2/src/main/java/androidx/work/RxWorker.java
M work/work-rxjava2/build.gradle
M work/work-rxjava2/api/public_plus_experimental_current.txt
M work/work-rxjava2/api/current.txt
M work/work-rxjava2/api/restricted_current.txt
M work/work-rxjava2/src/test/java/androidx/work/RxForegroundInfoTest.kt
py...@gmail.com <py...@gmail.com> #8
Branch: androidx-main
commit 66303e797f590d88fd50d1c68caee02c1bfac077
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Fri Nov 05 17:43:16 2021
RxJava3: RxJava wrapper around setForegroundInfoAsync
Test: RxForegroundInfoTest
bug:203851459
Relnote: "
RxWorker now has `setForeground` returning `Completable` that
can be used instead of `setForegroundInfoAsync` that returns
`ListenableFuture`.
"
Change-Id: I992a32849600b8c3bb37fa362e9775bc46a6462b
M work/work-rxjava3/src/main/java/androidx/work/rxjava3/RxWorker.java
M work/work-rxjava3/src/test/java/androidx/work/rxjava3/RxForegroundInfoTest.kt
M work/work-rxjava3/api/public_plus_experimental_current.txt
M work/work-rxjava3/api/current.txt
M work/work-rxjava3/api/restricted_current.txt
al...@google.com <al...@google.com> #9
py...@gmail.com <py...@gmail.com> #10
Yep. That's what got this issue filed after all ;-)
al...@google.com <al...@google.com> #11
Heh, of course.
Is there a way the internal code can keep a ref to that new callback once its set, and reference it instead of installing or unwrap?
This goes beyond my familiarity with (and available time to invest in understanding) the existing codebase -- I'd have to defer to Chris.
ch...@google.com <ch...@google.com> #12
I don't think there's a perfect solution here to be honest. I'm thinking that reverting to the previous solution is the only 'correct' way forward for the 80% case.
If apps want to change the window callback, they can override setSupportActionBar()
and do it in there, after calling super.
py...@gmail.com <py...@gmail.com> #13
That won't work for libraries. The callback delegation allows libraries to play nice together. We shouldn't one library (appcompat) break all othee libraries.
py...@gmail.com <py...@gmail.com> #14
Looking into this a bit more, it seems that what we really need to do is:
- Install the callback only once and keep a ref to it.
- Decouple the callback from ToolbarActionBar, so that we can swap the ToolbarActionBar instance receiving things (or set it to null)
Maybe 1) and 2) means actually killing the callback and adding a nullable ToolbarActionBar to the default callback already install? That'd simplify things a lot it seems.
Thoughts? I can maybe take a stab in between 2 diaper changes.
ch...@google.com <ch...@google.com> #15
Yeah, that should be do-able. Looking now.
ap...@google.com <ap...@google.com> #17
Branch: androidx-main
commit 32144c85d339f680dbffd6ce9d16d57d15cdd65b
Author: Chris Banes <chrisbanes@google.com>
Date: Thu May 06 12:07:14 2021
Re-work support action bar window callback handling
Instead of wrapping the Window.Callback when an action bar
is set, we now just updated our existing callback so
that it receives the necessary events.
Follow-on from Ie43eedf8322caa44e7b201a95cbc64197953e020.
Test: SupportActionBarTestCase
Fixes: 186791590
Change-Id: I091cb6826ce4896cd5a500da7aa741cef862fc64
M appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
M appcompat/appcompat/src/main/java/androidx/appcompat/app/ToolbarActionBar.java
Description
Summary
Calling
AppCompatActivity.setSupportActionBar()
replaces the window callback with a delegate callback that delegates to a previously installedAppCompatWindowCallback
instead of delegating to the current window callback, thus breaking developers expectations around window callback delegation.Root cause
android.view.Window
instance can have a singleandroid.view.Window.Callback
set (viaAppCompatActivity.onCreate()
, as we can see inAppCompatActivity.setSupportActionBar()
does not follow that correct pattern. It replaces the callback but then delegates to the previously installedAppCompatWindowCallback
instead of the current window callback, as we can see inRepro
This bug was originally reported square/curtains#14 . After investigating, I determined this is actually an AppCompat bug. I'm attaching the repro project and video demonstrating the bug from that ticket.
Here's an example activity that reproduces the issue:
The fix is likely that
AppCompatDelegateImpl.setSupportActionBar()
should passmWindow.getCallback()
to theToolbarActionBar
constructor, instead ofmAppCompatWindowCallback
.