Status Update
Comments
sy...@google.com <sy...@google.com> #2
class FixDrawerLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
) : DrawerLayout(context, attrs) {
fun registerToFragmentLifecycle(fragment: Fragment) {
fragment.viewLifecycleOwner.launchOnLifecycleDestroy {
super.onDetachedFromWindow()
}
}
}
b....@gmail.com <b....@gmail.com> #3
With markdown the same:
I have a project on SingleActivity. And in manifest android:enableOnBackInvokedCallback="true". I have a Root Fragment with a toolbar to which I attach a DrawerLayout.
<!-- XML Root Fragment -->
<androidx.drawerlayout.widget.DrawerLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.MaterialToolbar />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<androidx.core.widget.NestedScrollView
android:layout_gravity="start">
</androidx.drawerlayout.widget.DrawerLayout>
On button click in DrawerLayout I change RootFragment and lose all View in this Xml after onDestroyView. I don't call close() or closeDrawer() because I need the old state when I return to this fragment. But!
The DrawerLayout calls onDetachedFromWindow() which calls updateBackInvokedCallbackState() where ViewCompat.isAttachedToWindow(this) returns true and all the following condition is also true.
boolean shouldBeRegistered = visibleDrawer != null
&& currentDispatcher != null
&& getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED
&& ViewCompat.isAttachedToWindow(this);
As a consequence, the following code cannot be executed:
} else if (!shouldBeRegistered && mBackInvokedDispatcher != null) {
Api33Impl.tryUnregisterOnBackInvokedCallback(
mBackInvokedDispatcher, mBackInvokedCallback);
mBackInvokedDispatcher = null;
}
Where mBackInvokedDispatcher != null is true, and shouldBeRegistered is true (but !shouldBeRegistered is false).
Consequently, my mechanical back button or slide (back gesture) is blocked and not called on a new Root fragment when the DrawerLayout is Destroyed.
<!-- new Root fragment -->
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.MaterialToolbar />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
There may be a workaround, but that's not all. The fact is that LeakCanary reacts to this error, which claims that after registerOnBackInvokedCallback and not called tryUnregisterOnBackInvokedCallback, a memory leak occurs.
fast fix: android:enableOnBackInvokedCallback="false" or downgrade DrawerLayout to 1.1.1 or
sy...@google.com <sy...@google.com> #4
What I've seen is that when I show a new fragment as a result of a drawer layout navigation view being selected, back gestures break with `enableOnBackInvokedCallback` on stop working - and I saw the same else if block you mentioned above _not_ get called and result in stale/stuck back handlers consuming the gestures in this scenario.
I was able to delay showing the fragment until after the drawer layout closed, and the issue did not exist there.
The odd thing is - when I try out older drawer layout versions, the bug still exists. So maybe it's something deeper? I'm working to get a sample app setup to demo this, will circle back soon but wanted to add my current observations.
b....@gmail.com <b....@gmail.com> #5
after the drawer layout closed
According to my requirements, it should not close, since there is a screen animation where you can see that it is open. So the hot fix only helps through custom view.
fun registerToFragmentLifecycle(fragment: Fragment) {
fragment.viewLifecycleOwner.launchOnLifecycleDestroy {
super.onDetachedFromWindow()
}
}
sa...@gmail.com <sa...@gmail.com> #6
related to `launchOnLifecycleDestroy` - what is that method? I don't see it anywhere in my repo/online. Is that a custom API? Would be curious what that does!
sy...@google.com <sy...@google.com> #7
Here's my sample app btw -
Again, I'm not sure if our issues are exactly the same, but I get "stuck" not being able to swipe back between fragments after navigating to a fragment starting from a menu item being selected in a Drawer Layout - so it sounds similar...
ty...@gmail.com <ty...@gmail.com> #8
launchOnLifecycleDestroy ->
fun(block: suspend CoroutineScope.(Lifecycle.Event) -> Unit) {
coroutineScope.launch {
val observer = LifecycleEventObserver { _, event -> launch { if (Event.ON_DESTROY == event) block(event) } }
addObserver(observer)
try {
awaitCancellation()
} catch (_: CancellationException) {
removeObserver(observer)
}
}
}
Description
Please answer all relevant questions below so that we have enough information to investigate your issue. Providing incomplete information will delay investigation of your issue.
Bug Report Template
Describe the issue: expected vs. observed behavior and/or appearance.
ReconnectionService is trying to start a service in the background. This is causing an IllegalStateException on Android 8+.
com.google.android.gms.cast.framework.ReconnectionService }: app is in background uid UidRecord{c51b1af u0a131 TPSL bg:+2m55s135ms idle change:cached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577)
at android.app.ContextImpl.startService(ContextImpl.java:1532)
at android.content.ContextWrapper.startService(ContextWrapper.java:664)
at com.google.android.gms.internal.cast.zzai.zzg$1385ff(Unknown Source:19000)
at com.google.android.gms.internal.cast.zzai.onStatusUpdated(Unknown Source)
at com.google.android.gms.cast.framework.media.zzr.onStatusUpdated(Unknown Source:30)
at com.google.android.gms.internal.cast.zzdh.onStatusUpdated(Unknown Source:6)
at com.google.android.gms.internal.cast.zzdh.zza(Unknown Source:14000)
at com.google.android.gms.cast.framework.media.RemoteMediaClient.zzb(Unknown Source:2)
at com.google.android.gms.internal.cast.zzct.run(Unknown Source:31)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
List steps to reproduce the issue, if known.
We have been unable to reproduce locally but it is our largest crash.
Which version of the Cast SDK are you using?
15.0.1
On which version(s) of the OS (iOS, Android) do you observe the problem?
Android
On which device type(s) such as phones, tablets or laptops (iPad, iPhone, etc.) do you observe the problem?
Android devices
Do you observe the problem when running on a physical device, or the simulator, or both?
We haven't reproduced, but it happens on user devices.
If this is a device discovery or device connectivity issue: Do you observe the problem over Cellular (using Guest Mode), WiFi (using either Guest Mode or local connection), or both?
If this is strictly a UI appearance/styling issue, please take screenshot(s) (for iOS, and Android) illustrating the problem and attach them to the bug report. Also mention whether the problem occurs in portrait orientation, landscape orientation, or both.
If this is not a UI appearance/styling issue, please capture logs from the SDK for a time interval leading up to and including the occurrence of the problem, and attach them to the bug report. For issues relating to device discovery, the log should cover at least 20 seconds. For issues relating to device connectivity, the log should cover the entire time during which you attempted to start a Casting session.
Obtaining iOS Cast SDK Logs:
Obtaining Android Cast SDK Logs: