Xamarin.AndroidX.Fragment FragmentManager Java.Lang.AbstractMethodError crash
Android framework version
net8.0-android
Affected platform version
VS for Mac 17.6.14, .NET 8.0.404
Description
I am getting this crash after adding IOnBackStackChangedListener to my activity:
Java.Lang.AbstractMethodError: abstract method "void androidx.fragment.app.FragmentManager$OnBackStackChangedListener.onBackStackChangeStarted(androidx.fragment.app.Fragment, boolean)"
at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:20830
at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:75
at AndroidX.Fragment.App.FragmentManager.IOnBackStackChangedListener.OnBackStackChangeStarted(Fragment fragment, Boolean pop) in D:\a\_work\1\s\generated\androidx.fragment.fragment\obj\Release\net8.0-android\generated\src\AndroidX.Fragment.App.FragmentManager.cs:986
at AndroidX.Fragment.App.FragmentManager.IOnBackStackChangedListener.n_OnBackStackChangeStarted_Landroidx_fragment_app_Fragment_Z(IntPtr jnienv, IntPtr native__this, IntPtr native_fragment, Boolean pop) in D:\a\_work\1\s\generated\androidx.fragment.fragment\obj\Release\net8.0-android\generated\src\AndroidX.Fragment.App.FragmentManager.cs:973
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLZ_V(_JniMarshal_PPLZ_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, Boolean p1) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:187
at java.lang.AbstractMethodError: abstract method "void androidx.fragment.app.FragmentManager$OnBackStackChangedListener.onBackStackChangeStarted(androidx.fragment.app.Fragment, boolean)
at at onBackStackChangeStarted(Native Method)
at at onBackStackChangeStarted(MainView.java:211)
at at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2131)
at at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2058)
at at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2001)
at at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:702)
at at android.os.Handler.handleCallback(Handler.java:938)
at at android.os.Handler.dispatchMessage(Handler.java:99)
at at android.os.Looper.loopOnce(Looper.java:226)
at at android.os.Looper.loop(Looper.java:313)
at at android.app.ActivityThread.main(ActivityThread.java:8751)
at at java.lang.reflect.Method.invoke(Native Method)
at at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Looks like it expects me to override method onBackStackChangeStarted(), but I can't do it.
Steps to Reproduce
- On activity add IOnBackStackChanged interface inheritance
- Add this activity as listener to SupportFragmentManager - SupportFragmentManager.AddOnBackStackChangedListener(this);
- Do actions to invoke onBackStackChangeStarted method.
Did you find any workaround?
No response
Relevant log output
I can confirm this issue. It makes it hard or impossible to implement AndroidX based preference screens properly.
@RoNko72 @PhilippC
Thanks for the feedback. I will look into the issue.
I am experiencing the same issue, is there any update regarding its resolution?
If someone could share a sample project showing the issue, that would help a lot. @moljac likely won't be spending much time on this project in the future.
Brief check[s]. No deep dive.
Bindings seem to be OK.
Search 1:
find . -type f -exec grep -Hni "OnBackStackChangedListener" {} \;
Result:
./source/androidx.fragment/fragment/Transforms/Metadata.ParameterNames.xml:3: <attr path="/api/package[@name='androidx.fragment.app']/class[@name='FragmentManager']/method[@name='addOnBackStackChangedListener' and count(parameter)=1 and parameter[1][@type='androidx.fragment.app.FragmentManager.OnBackStackChangedListener']]/parameter[1]" name="managedName">listener</attr>
./source/androidx.fragment/fragment/Transforms/Metadata.ParameterNames.xml:26: <attr path="/api/package[@name='androidx.fragment.app']/class[@name='FragmentManager']/method[@name='removeOnBackStackChangedListener' and count(parameter)=1 and parameter[1][@type='androidx.fragment.app.FragmentManager.OnBackStackChangedListener']]/parameter[1]" name="managedName">listener</attr>
Only parameter name change.
Search 2:
find . -type f -exec grep -Hni "onBackStackChangeStarted" {} \;
No results.
Further stpes:
- check
api.xml - check decompiled artifacts
We had this exact same crash when calling addToBackStack(null), the workaround was just to roll some of the Android libraries back.
Our csproj lists these dependencies now and everything is back in a working state, this leads me to believe the issue is somewhere in the bindings.
<ItemGroup>
<!-- had to upgrade 'Xamarin.AndroidX.Browser' to work with Xamarin Essentials we have referenced in a different library -->
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.3.0.5" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0-rc1" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.1.0-rc1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0-rc1" />
</ItemGroup>
EDIT: As an alternative, you can add the other missing methods. The compiler will not complain that you haven't implemented the full interface, but after adding these it'll recognize them and stop crashing.
public void OnBackStackChanged() { }
public void OnBackStackChangeCancelled() { }
public void OnBackStackChangeCommitted(Fragment fragment, bool pop) { }
public void OnBackStackChangeProgressed(BackEventCompat backEventCompat) { }
public void OnBackStackChangeStarted(Fragment fragment, bool pop) { }
I wonder if this is a result of the OnBackStackChangeListener being deprecated, and the support library version having a different interface?