Go back to MainPage if there is an unhandled exception?

I am completely lost after spending more than 8 hours for figuring out how to handle global exceptions in Xamarin Forms. How can I handle global exceptions, and gracefully show an alert about the error message and navigate back to my first landing page?

This is such as simple thing to do, yet I have no idea how I should be doing it. Please, help!

Answers

  • N_BauaN_Baua INMember ✭✭✭✭✭

    Hi @SarvarAbdullaev,

    Essentially if you are talking about generic exceptions, it should be like

    try
    {
    //Your code which met Dr.Evil
    }
    catch //(Exception Ex) -- Won't greet the Dr.Evil
    {
    //Redirect to some another view. Meet Mr.GoodFace
    }

    I do not know, if anything specific you wanted to accomplish. Please post some code or brief idea about wahat you are looking for.

    --- N Baua

  • JohnHardmanJohnHardman GBUniversity mod

    @SarvarAbdullaev - Unfortunately, it's not as easy as you would expect.

    To add handlers for exceptions not handled elsewhere:

    Android:

    // In OnCreate,
    
    AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
    TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
    AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironmentOnUnhandledException;
    

    iOS:

    // In FinishedLaunching:
    
    AppDomain.CurrentDomain.UnhandledException += async (sender, e) =>
    TaskScheduler.UnobservedTaskException += async (sender, e) =>
    

    UWP:

    // In OnLaunched:
    
    UnhandledException += OnUnhandledException;
    

    What you can actually do in those handlers depends on the target. On some, you can pop up a message for the user, on others you cannot (I think it was WinPhone 8.x that got most upset, if I remember correctly). Where popping up a message does not work, you may want to log details to persistent storage and then display them on next startup.

    Regarding navigating back to the first page from these handlers - I haven't tried that, but I suspect whether it works on a platform will probably tie in with with whether popping up a dialog works on that platform.

    If you haven't already, you might want to integrate HockeyApp or Mobile Center as well as doing the above.

    Does adding these handlers remove the need for exception handling elsewhere in your app? No. You will probably want to catch and handle exceptions anywhere in your app code where your code is called from XF or from the o/s. That includes the body of any new Tasks, event handlers, overrides of OnXXXX methods, custom renderers etc.

  • JohnHardmanJohnHardman GBUniversity mod

    @SarvarAbdullaev - Just realised I missed TaskScheduler off the list for UWP, but too late to edit previous post.

  • SarvarAbdullaevSarvarAbdullaev USMember
    edited September 2017

    @JohnHardman Yes, I saw this way handling exceptions in some other responses, but my concern was how to pop back to the Navigation Root from iOS or Android?

    My app uses a SOAP web service which gives a session token for certain period of time. Once this session expires, it returns an exception. So anywhere in my app if I use this service, it is further going to return that exception. I think the easiest way of handling this case is to handle the problem directly inside proxy classes. My proxy classes are implemented in native projects due to the limitations of PCL. I simply defined an interface on Xamarin Forms and use DependencyService to grab them.

    My solution is I will have a decorator class in Xamarin Form for that services interface where I do try/catch for each service request. Once I capture exception, I can move to the root and display alert right from my Xamarin Forms code. The problem with this solution is that the code flow will not be broken as I handle the exception on a service level.
    For ex, somewhere in my app I request list of users, but because session expired, it returns exception. Now I handle it on service level, meaning that the remaining code on a caller thread will continue its execution. This is what I don't want to happen too.

    Can I simply raise another custom exception from service decorator class in Xamarin Forms after I gracefully handled the exception and suppress it in native projects? That's the only way I am trying to handle this problem I guess.

  • SarvarAbdullaevSarvarAbdullaev USMember
    edited September 2017

    @JohnHardman - Thanks for your response. I just want to ask how do I suppress that unhandled exception in my iOS app? I don't want my iOS app to shut down once there is an exception.

  • JohnHardmanJohnHardman GBUniversity mod

    @SarvarAbdullaev - Re. "how do I suppress that unhandled exception" - it depends what you mean by suppress. You can silently swallow the unhandled exception by adding the handlers above and then doing nothing (not recommended). Or you can add try/catch blocks throughout your code to prevent any unhandled exceptions from occurring (recommended).

    The problem with silently swallowing exceptions reported as unhandled, is that your app is left in an unknown state. It may be safe to continue, or the app may really need terminating so that it is re-started to get back to a known state.

    Regarding navigating back to the root page - if the app is in a reasonable state, as opposed to having say a corrupted navigation stack, you could on iOS manipulate the navigation stack (directly, or via a navigation service), but I wouldn't recommend it - the unknown status of the app when an unhandled exception occurs means doing this could just be storing up problems.

  • NMackayNMackay GBInsider, University mod

    @JohnHardman said:
    @SarvarAbdullaev - Re. "how do I suppress that unhandled exception" - it depends what you mean by suppress. You can silently swallow the unhandled exception by adding the handlers above and then doing nothing (not recommended). Or you can add try/catch blocks throughout your code to prevent any unhandled exceptions from occurring (recommended).

    The problem with silently swallowing exceptions reported as unhandled, is that your app is left in an unknown state. It may be safe to continue, or the app may really need terminating so that it is re-started to get back to a known state.

    Regarding navigating back to the root page - if the app is in a reasonable state, as opposed to having say a corrupted navigation stack, you could on iOS manipulate the navigation stack (directly, or via a navigation service), but I wouldn't recommend it - the unknown status of the app when an unhandled exception occurs means doing this could just be storing up problems.

    Excellent advice.

  • batmacibatmaci DEMember ✭✭✭✭✭

    Is mobile center ready for production? how is it better comparing to hockeyapp?

  • RyanWatsonRyanWatson USMember ✭✭✭

    @JohnHardman said:
    @SarvarAbdullaev - Unfortunately, it's not as easy as you would expect.

    To add handlers for exceptions not handled elsewhere:

    Android:

    // In OnCreate,
    
    AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
    TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
    AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironmentOnUnhandledException;
    

    iOS:

    // In FinishedLaunching:
    
    AppDomain.CurrentDomain.UnhandledException += async (sender, e) =>
    TaskScheduler.UnobservedTaskException += async (sender, e) =>
    

    UWP:

    // In OnLaunched:
    
    UnhandledException += OnUnhandledException;
    

    What you can actually do in those handlers depends on the target. On some, you can pop up a message for the user, on others you cannot (I think it was WinPhone 8.x that got most upset, if I remember correctly). Where popping up a message does not work, you may want to log details to persistent storage and then display them on next startup.

    Regarding navigating back to the first page from these handlers - I haven't tried that, but I suspect whether it works on a platform will probably tie in with with whether popping up a dialog works on that platform.

    If you haven't already, you might want to integrate HockeyApp or Mobile Center as well as doing the above.

    Does adding these handlers remove the need for exception handling elsewhere in your app? No. You will probably want to catch and handle exceptions anywhere in your app code where your code is called from XF or from the o/s. That includes the body of any new Tasks, event handlers, overrides of OnXXXX methods, custom renderers etc.

    Put that code in iOS and still getting an app crash and the exception is not being caught.

  • JohnHardmanJohnHardman GBUniversity mod

    @RyanWatson - That's weird. Although I've seen other people mention that they have had exceptions that did not get caught anywhere, I've only ever seen that once - on Android, in Java code, where the Java exception did not trickle up through the C#/Java interface. I've never seen an uncatchable exception on iOS.

    Do you have any detail of the exception (gleaned from the output window of the IDE, or from iOS logs)?

  • RyanWatsonRyanWatson USMember ✭✭✭

    @JohnHardman After a few days, I finally tracked down last night where the exception was coming from. That took a bit of work as I was think it was something else. For some reason in this spot in my code if I have one ACR.UserDialogs.Instance.ShowLoading() call happen and then another one happens before the HideLoading is called then it will cause my code to crash. Seems to only happen in iOS and not Android though. Fixed the issue by calling HideLoading on iOS before another ShowLoading but here is the exception that I was getting that wasn't being caught:

    System.ArgumentOutOfRangeExceptionIndex was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
    Raw
    null
    System.ArgumentOutOfRangeExceptionIndex was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
    at System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) <0x1008b92e0 + 0x0004c> in <6314851f133e4e74a2e96356deaa0c6c#5a685c03a3db25e162ab061753febf6b>:0
    at System.ThrowHelper.ThrowArgumentOutOfRangeException () <0x1008b9150 + 0x00013> in <6314851f133e4e74a2e96356deaa0c6c#5a685c03a3db25e162ab061753febf6b>:0
    at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) <0x100a0c2c0 + 0x00053> in <6314851f133e4e74a2e96356deaa0c6c#5a685c03a3db25e162ab061753febf6b>:0
    at Xamarin.Forms.Application+NavigationImpl+d__2.MoveNext () <0x101481540 + 0x000a7> in <6e20d7af277949f4a7bb952d64b81cda#5a685c03a3db25e162ab061753febf6b>:0

  • JohnHardmanJohnHardman GBUniversity mod

    @RyanWatson - Curious. This was terminating the app, or was just something you saw in the logged output? If it was terminating your app, I'd check with the authors of ACR.UserDialogs to see whether there is anything you can do to catch this, or whether they need to make a change in their code. If they say there is something you should do to catch it, I'd undo your current fix so that the error occurs, implement whatever they suggest, and test the handling, and only then put your fix back in. That way, your code will be more resilient to what may be a third-party problem, and the exception handling around it tested.

  • RyanWatsonRyanWatson USMember ✭✭✭

    @JohnHardman This is what I was getting in Xamarin.Insights when my code would crash. There is a Try/Catch around the whole block so not sure why it wasn't being caught. Though I tried just calling two ShowLoading in succession and the issue doesn't happen. Only reason I didn't raise a case with them is I have no clue how to reproduce it outside of the code I have here as I have no clue what is really causing the problem. Though I might try to see if I can track it down and then report.

  • AndreaConteAndreaConte CHUniversity

    @JohnHardman

    What you can actually do in those handlers depends on the target. On some, you can pop up a message for the user, on others you cannot (I think it was WinPhone 8.x that got most upset, if I remember correctly). Where popping up a message does not work, you may want to log details to persistent storage and then display them on next startup.

    On App.xaml.cs (UWP platform):

    UnhandledException += async  (sender, e) =>
     {
                    e.Handled = true;  // the magic! required to show popup!
    
                    var dialog = new MessageDialog(e.Message, "UnhandledException caught!");
                    await dialog.ShowAsync();
    }
    

    If you miss e.Handled=true application is in "terminating mode" so no popup is shown.
    If you set e.Handled = true you can do whatever you need (alert, navigation and so on).

  • JohnHardmanJohnHardman GBUniversity mod

    @AndreaConte - Correct.

    I'm not 100% sure whether it's required, but I also make it explicit that the MessageDialog is invoked on the UI thread.

  • batmacibatmaci DEMember ✭✭✭✭✭

    @JohnHardman said:
    @SarvarAbdullaev - Re. "how do I suppress that unhandled exception" - it depends what you mean by suppress. You can silently swallow the unhandled exception by adding the handlers above and then doing nothing (not recommended). Or you can add try/catch blocks throughout your code to prevent any unhandled exceptions from occurring (recommended).

    The problem with silently swallowing exceptions reported as unhandled, is that your app is left in an unknown state. It may be safe to continue, or the app may really need terminating so that it is re-started to get back to a known state.

    Regarding navigating back to the root page - if the app is in a reasonable state, as opposed to having say a corrupted navigation stack, you could on iOS manipulate the navigation stack (directly, or via a navigation service), but I wouldn't recommend it - the unknown status of the app when an unhandled exception occurs means doing this could just be storing up problems.

    this is really great suggestion but I am wondering how some apps automatically restarts their application without requiring user to do it when there is an unexpected exception occurs.

  • RodrigoJuarez.1796RodrigoJuarez.1796 USMember ✭✭

    In my xamarin.forms project after adding the code to catch the android exceptions

        public class MainApplication : Application, Application.IActivityLifecycleCallbacks
        {
            public MainApplication(IntPtr handle, JniHandleOwnership transer)
              : base(handle, transer)
            {
            }
    
            public override void OnCreate()
            {
                base.OnCreate();
                RegisterActivityLifecycleCallbacks(this);
                //A great place to initialize Xamarin.Insights and Dependency Services!
    
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
                TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
                AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
    
            }
    

    I still get an unhandled android exception: Java.Lang.RuntimeException: Canvas: trying to draw too large (158703840bytes) bitmap.

    I think I know why is this happening (add too much data dynamically in a stack layout), but I want to catch this and show a proper message

    Anyone know why I can't catch the exception?

  • batmacibatmaci DEMember ✭✭✭✭✭

    @RodrigoJuarez.1796 Did you find a way to handle it? beside that is it better to have this in MainApplication instead of Mainactivity?

  • RodrigoJuarez.1796RodrigoJuarez.1796 USMember ✭✭

    @batmaci I didn't find a way to handle it, I ended changing a lot of stacklayouts added at runtime to a listview to avoid the exception

Sign In or Register to comment.