Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when changing mainpage #17769

Open
Gekidoku opened this issue Oct 2, 2023 · 10 comments
Open

Crash when changing mainpage #17769

Gekidoku opened this issue Oct 2, 2023 · 10 comments
Labels
area-navigation NavigationPage migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert platform/android 🤖 s/duplicate 2️⃣ This issue or pull request already exists s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@Gekidoku
Copy link

Gekidoku commented Oct 2, 2023

Description

The following crash keeps arriving in my appcenter crash log.
So far i've been unable to reproduce it but customers are getting angry and want a solution.

Java.Interop.JniEnvironment.InstanceMethods.CallIntMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractInt32Method(String , IJavaPeerable , JniArgumentValue* )
AndroidX.Fragment.App.FragmentTransactionInvoker.Commit()
Microsoft.Maui.Platform.NavigationRootManager.SetContentView(IView view)
Microsoft.Maui.Platform.NavigationRootManager.Connect(IView view, IMauiContext mauiContext)
Microsoft.Maui.Handlers.WindowHandler.CreateRootViewFromContent(IWindowHandler handler, IWindow window)
Microsoft.Maui.Handlers.WindowHandler.MapContent(IWindowHandler handler, IWindow window)
Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.IWindow, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IWindowHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v)
Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView)
Microsoft.Maui.PropertyMapper.UpdateProperty(IElementHandler viewHandler, IElement virtualView, String property)
Microsoft.Maui.Handlers.ElementHandler.UpdateValue(String property)
Microsoft.Maui.Controls.Window.OnPropertyChanged(String propertyName)
Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
Microsoft.Maui.Controls.Window.set_Page(Page value)
Microsoft.Maui.Controls.Application.set_MainPage(Page value)
TRNSPRNTBeveiligerApp.App.<>c__DisplayClass29_0.<<LogoutUser>b__0>d.MoveNext()
System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object )
Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0()
Java.Lang.Thread.RunnableImplementor.Run()
Java.Lang.IRunnableInvoker.n_Run(IntPtr , IntPtr )
Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V , IntPtr , IntPtr )
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
androidx.fragment.app.FragmentManager.enqueueAction(SourceFile:38)
androidx.fragment.app.BackStackRecord.commitInternal(SourceFile:73)
androidx.fragment.app.BackStackRecord.commit(Unknown Source:1)
mono.java.lang.RunnableImplementor.n_run(Native Method)
mono.java.lang.RunnableImplementor.run(Unknown Source:0)
android.os.Handler.handleCallback Handler.java:938
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loop Looper.java:246
android.app.ActivityThread.main ActivityThread.java:8645
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:602
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1130

The one function i can find in this log thats my code is LogoutUser.
Its called by OnResume and both OnResume and LogoutUser are situated in the App.xaml.cs file in the root of my Maui project

 public static void LogoutUser()
 {
     //Clears the local User table in sqlite
     App.LocalDB.DeleteUser();

     LoginNew mPage;
    mPage = new LoginNew()
     {
         IconImageSource = ImageSource.FromFile("tab_feed.png"),
         Title = "Inloggen"
     };
     MainThread.BeginInvokeOnMainThread(async () =>
     {
         await Task.Delay(100);
         App.Current.MainPage = new NavigationPage(mPage) { Style = Application.Current.Resources["MyNavPage"] as Style };
     });
 }

Which is the following function called at the end of my OnResume if certain conditions are met.

Conditions are.

  • Regular logout crashes.
  • User has been inactive for longer than the endtime of their shift.

Both of these conditions happen in the onresume function
which is basically

protected override void OnResume()
{
  base.OnResume();
  //Get the current user i always clear the db and fill it when they login. so it only ever has 1 record. found this more stable than storing it in the appsettings

 User user = LocalDB.GetUser();
//Could do this cleaner but will do that later
if (user.StartTimeShift != null)
{
    if (user.EndTimeShift != null)
    {
        if (user.EndTimeShift.Value.AddHours(1) < DateTime.Now)
        {
              App.LocalDB.DeleteUser();
 LoginNew mPage;
 mPage = new LoginNew()
 {
     IconImageSource = ImageSource.FromFile("tab_feed.png"),
     Title = "Inloggen"
 };
 if (Helpers.Settings.RedirectToAlarm)
 {
     mPage.SetRedirect(Helpers.Settings.RedirectToAlarm, Helpers.Settings.RedirectToAlarmType);
 }

//Tried putting it in a begininvoke to see if that fixes it. it doesnt. This used to work in xamarin.forms just fine. dont know what changed
 MainThread.BeginInvokeOnMainThread( async() =>
 {
     try
     {
         await Task.Delay(100);
         App.Current.MainPage = new NavigationPage(mPage) { Style = Application.Current.Resources["MyNavPage"] as Style };
     }
     catch
     {
         App.LogoutUser();
     }
 });
        }
    }
}

}

So no weird things happen here. just a switch of the mainpage if a user shouldnt be logged in anymore (app contains customer info and a employee should only be able to access it when they are on a shift, they could be on a page with data when they resume the app so its handled in this way).

Ive done some digging to differences in MAUI and Xamarin.forms.
And ive spotted the following.
In MAUI in the navigation root manager at line 133 and 150 there is a .commit();
However in Xamarin.Forms i see that this had been changed to CommitAllowingStateLoss(); xamarin/Xamarin.Forms@b444ebb

Not that i know enough about the internals of maui just thought id find something that could function as a starting point.

Hope you can give me some help with this. As my customers are all security guards that call at impossible times at night because the app crashed due to this.

Steps to Reproduce

Cant reproduce it myself. but the crashlogs arrive in appcenter so it must be happening.

Link to public reproduction project repository

https://github.com/Gekidoku/UnfocusTest

Version with bug

7.0.92

Is this a regression from previous behavior?

Yes, this used to work in Xamarin.Forms

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

Android33

Did you find any workaround?

No

Relevant log output

No response

@Gekidoku Gekidoku added the t/bug Something isn't working label Oct 2, 2023
@Gekidoku
Copy link
Author

Gekidoku commented Oct 2, 2023

Added note.
It shouldnt be because of something on my LoginNew page. As this is the landing page when the app starts fresh.

@PureWeen PureWeen added the s/try-latest-version Please try to reproduce the potential issue on the latest public version label Oct 2, 2023
@ghost
Copy link

ghost commented Oct 2, 2023

Hi @Gekidoku. We have added the "s/try-latest-version" label to this issue, which indicates that we'd like you to try and reproduce this issue on the latest available public version. This can happen because we think that this issue was fixed in a version that has just been released, or the information provided by you indicates that you might be working with an older version.

You can install the latest version by installing the latest Visual Studio (Preview) with the .NET MAUI workload installed. If the issue still persists, please let us know with any additional details and ideally a reproduction project provided through a GitHub repository.

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.

@Gekidoku
Copy link
Author

Gekidoku commented Oct 2, 2023

What latest version?
7.0.92 is the workload version that im using which is the latest stable release.
Not really advisable to use preview builds on a release build that has over 2k users.

@ghost ghost removed the s/try-latest-version Please try to reproduce the potential issue on the latest public version label Oct 2, 2023
@samhouts samhouts added the migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert label Oct 3, 2023
@Gekidoku
Copy link
Author

Since this has been inactive for a while I was messing around for a bit.
Updated to a newer version of maui. (using .net8 now since .net7 has a horrible memory leak)
To my latest version of https://github.com/Gekidoku/UnfocusTest
I added three ways to crash the app when changing the mainpage in onresume.
and one way where it sometimes works.

Here are instructions to test each one,
Variant one,
Build app as is in the repo, deploy on android. wait for it to launch, click on SetMainPage in the menu, Bring app to background and back to foreground.
What this does it changes the mainpage to a navigationpage while the app is in the foreground and then tries to switch it back to a shell in the onresume.

Variant two,
Comment out MainPage = new AppShell(); in onresume, Line 16.
build app and deploy on android. wait for it to launch, then immediately go to the background and bring app back to foreground. it will crash.
What this scenario does. app goes to background with mainpage being a shell. then in onresume we try to make it a navigationpage.

Variant three,
Comment out Line 16. and line 19.
Uncomment Line 23 untill Line 28 (the entire mainthread thing.) But leave the task.delay commented.
build app and deploy on android. wait for it to launch, then immediately go to the background and bring app back to foreground. it will crash.
What this scenario does. app goes to background with mainpage being a shell. then in onresume we try to make it a navigationpage. but this time we try it on the mainthread.

Make variant three work. (sometimes)
Comment out Line 16. and line 19.
Uncomment Line 23 untill Line 28 (the entire mainthread thing.) But leave the task.delay commented.
build app and deploy on android. wait for it to launch, then immediately go to the background and bring app back to foreground. it will crash on slower devices.
What this scenario does. app goes to background with mainpage being a shell. then in onresume we try to make it a navigationpage. but this time we try it on the mainthread. and we add a small delay before we do the swap.

@Gekidoku
Copy link
Author

@PureWeen can you take a look at this again?
Happening in the latest version of maui .net8 as well.
see included repro in comment above this one.

@PureWeen
Copy link
Member

I think this is a duplicate of

#11501

@Gekidoku
Copy link
Author

One key difference for me, dont know how it works under the hood but it might be important to note.

In that issue it seems the crash happens while the app doesnt leave the foreground.
in mine its something that happens in onresume that causes it.

@pulmuone
Copy link

pulmuone commented Feb 1, 2024

I found the cause in Android.
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/FragmentManager.java

Error Message : "Can not perform this action after onSaveInstanceState"

private void checkStateLoss() {
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }
}

@jaosnz-rep
Copy link

Verified this issue with Visual Studio Enterprise 17.10 Preview 1.0, can use sample project to reproduce the errors in the above three scenarios on Android platform.
https://github.com/Gekidoku/UnfocusTest

@jaosnz-rep jaosnz-rep added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Mar 1, 2024
@jsuarezruiz jsuarezruiz added the s/duplicate 2️⃣ This issue or pull request already exists label Jun 6, 2024
@jsuarezruiz jsuarezruiz added this to the Backlog milestone Jun 6, 2024
@bzd3y
Copy link

bzd3y commented Jun 20, 2024

If other cases would help, I'm getting this on Page.Navigation.NavigationStack.PopModalAsync() when the app is being paused.

It looks like if false is passed in for animated then it doesn't happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-navigation NavigationPage migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert platform/android 🤖 s/duplicate 2️⃣ This issue or pull request already exists s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants