maui icon indicating copy to clipboard operation
maui copied to clipboard

[Android] Fatal exception after adding modal window to navigation stack

Open okirkland-promiles opened this issue 1 year ago • 2 comments

Description

After adding a modal popup window to the main page's navigation stack, a fatal exception is generated (Android only):

Steps to Reproduce

  1. Create a standard .NET MAUI application (v8.0.6).
  2. Modify the App() constructor in App.xaml.cs to load the MainPage as a navigation page:

MainPage = new NavigationPage(new MainPage());

  1. Add a map control to the applications main page.
  2. Add the following to the MainPage() constructor in MainPage.xaml.cs:

Loaded += MainPage_Loaded;

  1. In the Loaded event handler, push a new page to the modal navigation stack:

Navigation.PushModalAsync(new Page());

The navigation causes a Fatal Exception (See Relevant log output).

Link to public reproduction project repository

No response

Version with bug

8.0.6

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

8.0.3

Affected platforms

Android

Affected platform versions

Android 14 (API 34)

Did you find any workaround?

No.

Relevant log output

[AndroidRuntime] Shutting down VM
[AndroidRuntime] FATAL EXCEPTION: main
[AndroidRuntime] Process: com.promiles.FuelFinder, PID: 2966
[AndroidRuntime] java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.view.ViewGroup
[AndroidRuntime] 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:537)
[AndroidRuntime] 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272)
[AndroidRuntime] 	at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943)
[AndroidRuntime] 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1839)
[AndroidRuntime] 	at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782)
[AndroidRuntime] 	at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:565)
[AndroidRuntime] 	at android.os.Handler.handleCallback(Handler.java:958)
[AndroidRuntime] 	at android.os.Handler.dispatchMessage(Handler.java:99)
[AndroidRuntime] 	at android.os.Looper.loopOnce(Looper.java:230)
[AndroidRuntime] 	at android.os.Looper.loop(Looper.java:319)
[AndroidRuntime] 	at android.app.ActivityThread.main(ActivityThread.java:8893)
[AndroidRuntime] 	at java.lang.reflect.Method.invoke(Native Method)
[AndroidRuntime] 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
[AndroidRuntime] 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

okirkland-promiles avatar Jan 26 '24 22:01 okirkland-promiles

@okirkland-promiles I'm not clear from your selections if this worked in 8.0.3 for you or not.

Not sure, did not test other versions

PureWeen avatar Jan 27 '24 17:01 PureWeen

Hi @okirkland-promiles. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jan 27 '24 17:01 ghost

What if you use a ContentPage instead of a Page? Or a page derived from it? That still works fine in my application on 8.0.6

(in my application I wait until Shell OnAppearing has been fired, then navigate to my ContentPage from App.xaml.cs, but it should be the same?)

jkommeren avatar Jan 30 '24 14:01 jkommeren

What if you use a ContentPage instead of a Page? Or a page derived from it? That still works fine in my application on 8.0.6

(in my application I wait until Shell OnAppearing has been fired, then navigate to my ContentPage from App.xaml.cs, but it should be the same?)

@jkommeren Thanks for the suggestion, I tried that but same result. I'm adding a sample project that demonstrates the issue.

okirkland-promiles avatar Jan 30 '24 15:01 okirkland-promiles

@okirkland-promiles I'm not clear from your selections if this worked in 8.0.3 for you or not.

Not sure, did not test other versions

@PureWeen Yes it did work fine in 8.0.3 (at least). I did not test prior versions.

okirkland-promiles avatar Jan 30 '24 16:01 okirkland-promiles

@okirkland-promiles I ran your sample on 8.0.3 and it crashes for me there as well.

I noticed you're not awaiting the modal push which will sometimes cause errors to get lost. If you await the push modal call for 8.0.3 do you start getting an exception?

 private async void MainPage_Loaded(object? sender, EventArgs e)
    {
        await Navigation.PushModalAsync(new ContentPage(){ Content = new Label(){ Text = "Hello World" }});
    }

PureWeen avatar Jan 31 '24 19:01 PureWeen

Hi @okirkland-promiles. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jan 31 '24 19:01 ghost

@okirkland-promiles I ran your sample on 8.0.3 and it crashes for me there as well.

I noticed you're not awaiting the modal push which will sometimes cause errors to get lost. If you await the push modal call for 8.0.3 do you start getting an exception?

 private async void MainPage_Loaded(object? sender, EventArgs e)
    {
        await Navigation.PushModalAsync(new ContentPage(){ Content = new Label(){ Text = "Hello World" }});
    }

@PureWeen I updated the code as you suggested. Same result, no extra details sorry to say. The error originally showed up in one my apps that pushes modal pages on top of the map from time to time, and that code has always used await, it was just missing from my sample project.

okirkland-promiles avatar Jan 31 '24 20:01 okirkland-promiles

@okirkland-promiles can you create a branch with your working 8.0.3 version?

PureWeen avatar Jan 31 '24 23:01 PureWeen

@okirkland-promiles can you create a branch with your working 8.0.3 version?

@PureWeen I tried creating an 8.0.3 version of the test project, and it breaks just like yours. I can't even get a 7.0.101 version of the test project working.

I also ran tests against my main project (FuelFinder) for both of those versions, and it works in both. Both use the same exact frameworks, nuget package versions and Android API versions in each comparison. So it must be more complicated than different package versions only. I do know it was during the transition from 8.0.3 to 8.0.6 in my main project when it broke, but there were other minor changes too. The modal popup does not work in the main project with 8.0.6, even though the code that opens it is just the same.

I'll look into it more as soon as I get time.

okirkland-promiles avatar Feb 01 '24 15:02 okirkland-promiles

Can reproduce on 8.0.3 and 8.0.6.

jsuarezruiz avatar Feb 12 '24 12:02 jsuarezruiz

Duplicate of #20317

PureWeen avatar Feb 13 '24 15:02 PureWeen

Running some tests here, this seems to work in a Shell app. Looking further as to why there is some image view that needs to be cast at all.

mattleibow avatar Feb 13 '24 19:02 mattleibow

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

ghost avatar Mar 05 '24 21:03 ghost

Issue still occurs on 8.0.40 and it's pretty inconvenient since there are no workarounds...

awasilik avatar May 17 '24 12:05 awasilik

Been struggling with this also (MAUI version 8.0.40)... In my case I'm migrating from Xamarin.Forms. No Shell used, page hierarchy as follows:

  • NavigationPage
    • TabbedPage
      • MapPage : ContentPage
      • OtherContentPage: ContentPage

In MapPage, i have a element that opens modal (with Navigation.PushModalAsync() ) when tapped.

Crash occures if I call PushModalAsync first thing after app start. If i navigate to OtherContentPage, return to MapPage and request to PushModalAsync(), the modal will open with no issues.

It seems to be related to the maps element, because if I change the OtherContentPage as default, same modal opens flawlessly, and there is nothing maps related in the modal. Only way to trigger fault is when MapPage is first shown when app starts and the modal is being opened within that page. Even when I call OpenModal on separate button outside map it fails.

Update: Navigation.PushAsync() works, and I'm currently using that as workaround.

To me it seems that some type within Google maps api conflicts with MAUI type?🤔

Stack: java.lang.ClassCastException: com.google.maps.api.android.lib6.impl.as cannot be cast to android.view.ViewGroup at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:537) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1839) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782) at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:565) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

eerojaaskelainen avatar Jun 11 '24 13:06 eerojaaskelainen

Ok, the Navigation.PushAsync did not work, at least in my case (messed up the navigation stack). On further investigation, i found out similar issue with Xamarin Forms / Maps prior version 2.4.0.91020: Spanish SO thread Of course link to original discussion was broken, but SO had enough data for me to do a another work-around.

So basically what I did was to drop the map component from view just before call to PushModalAsync, and restore it when Modal was popped out. No need to dispose the Map component, just take it out from Layout, push modal, and put it back when done.

protected void RemoveMap() {
#if ANDROID
            if (MapContainer == null) // MapContainer contains the Map (Grid in my case)
                return;
            if (MapComponent == null) // MapComponent is a reference to Map
                return;
            if (MapComponent.Parent != null)
            {
                try
                {
                    MapContainer.Remove(MapComponent);
                }
                catch (Exception ex)
                {
                    // Show error to user
                }
            }
#endif
}
 
protected void InsertMap() {
#if ANDROID

            if (MapContainer == null || MapComponent == null)
                return;

            if (MapComponent.Parent == null)
            {
                try
                {
                    MapContainer.Insert(0, MapComponent);
                }
                catch (Exception ex)
                {
                    // Show error to user
                }
            }
#endif
        }

Call the RemoveMap() before call to Navigation.PushModalAsync(), and InsertMap after Navigation.PopModalAsync().

eerojaaskelainen avatar Jul 01 '24 10:07 eerojaaskelainen