11

I am using following code from here.

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                // Catch your exception
                // Without System.exit() this will not work.
                System.exit(2);
            }
        });

I want to use this in C#. But, I could not find equivalent methods to this approach in C#. I want to use Toast.makeText() to show the error to user.

Community
  • 1
  • 1
user2111639
  • 287
  • 2
  • 5
  • 15

2 Answers2

20

try something like this -

AppDomain.CurrentDomain.UnhandledException += <Put your own delegate or handler>;
TaskScheduler.UnobservedTaskException += <Put your own delegate or handler here>;

Ideally, you would like to do this in someplace which is executed not more than once during the execution of your program. In case of a Xamarin.Android App, you can put this in the Custom Application class onCreate method.

If you want a code sample, check this link (I have not run the code myself, so can't guarantee the correctness of it. Use it just as a reference) - Sample

// In MainActivity
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);  

    AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
    TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;  

    Xamarin.Forms.Forms.Init(this, bundle);  
    DisplayCrashReport();  

    var app = new App();  
    LoadApplication(app);
}  

‪#‎region‬ Error handling
private static void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs unobservedTaskExceptionEventArgs)
{
    var newExc = new Exception("TaskSchedulerOnUnobservedTaskException", unobservedTaskExceptionEventArgs.Exception);
    LogUnhandledException(newExc);
}  

private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
    var newExc = new Exception("CurrentDomainOnUnhandledException", unhandledExceptionEventArgs.ExceptionObject as Exception);
    LogUnhandledException(newExc);
}  

internal static void LogUnhandledException(Exception exception)
{
    try
    {
        const string errorFileName = "Fatal.log";
        var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // iOS: Environment.SpecialFolder.Resources
        var errorFilePath = Path.Combine(libraryPath, errorFileName);  
        var errorMessage = String.Format("Time: {0}\r\nError: Unhandled Exception\r\n{1}",
        DateTime.Now, exception.ToString());
        File.WriteAllText(errorFilePath, errorMessage);  

        // Log to Android Device Logging.
        Android.Util.Log.Error("Crash Report", errorMessage);
    }
    catch
    {
        // just suppress any error logging exceptions
    }
}  

/// <summary>
// If there is an unhandled exception, the exception information is diplayed 
// on screen the next time the app is started (only in debug configuration)
/// </summary>
[Conditional("DEBUG")]
private void DisplayCrashReport()
{
    const string errorFilename = "Fatal.log";
    var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    var errorFilePath = Path.Combine(libraryPath, errorFilename);

    if (!File.Exists(errorFilePath))
    {
        return; 
    }

    var errorText = File.ReadAllText(errorFilePath);
    new AlertDialog.Builder(this)
        .SetPositiveButton("Clear", (sender, args) =>
        {
            File.Delete(errorFilePath);
        })
        .SetNegativeButton("Close", (sender, args) =>
        {
            // User pressed Close.
        })
        .SetMessage(errorText)
        .SetTitle("Crash Report")
        .Show();
} 

‪#‎endregion‬  

//iOS: Different than Android. Must be in FinishedLaunching, not in Main.
// In AppDelegate
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary options)
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
    TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;  
    ...
}  

/// <summary>
// If there is an unhandled exception, the exception information is diplayed 
// on screen the next time the app is started (only in debug configuration)
/// </summary>
[Conditional("DEBUG")]
private static void DisplayCrashReport()
{
    const string errorFilename = "Fatal.log";
    var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Resources);
    var errorFilePath = Path.Combine(libraryPath, errorFilename);

    if (!File.Exists(errorFilePath))
    {
        return;
    }

    var errorText = File.ReadAllText(errorFilePath);
    var alertView = new UIAlertView("Crash Report", errorText, null, "Close", "Clear") { UserInteractionEnabled = true };
    alertView.Clicked += (sender, args) =>
    {
        if (args.ButtonIndex != 0)
        {
            File.Delete(errorFilePath);
        }
    };
    alertView.Show();
}
Dibzmania
  • 1,934
  • 1
  • 15
  • 32
  • Thank you Dibzmania. But I cannot open Sample link. It is possible that you put that code here? – user2111639 Jan 15 '17 at 14:40
  • Hey I added the code. IT's pretty straightforward. If you are worried only about catching the exception, those two lines (along with your delegate implementation would suffice). However feel free to use or refer the file logging code in the sample. If your query is answered, mark it as answered for other people to refer. – Dibzmania Jan 15 '17 at 14:46
  • Do I need to put this 2 lines in all my activity? AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException; – jase Oct 29 '18 at 01:49
  • 1
    even if you do that, app is still crashing – Emil Mar 29 '19 at 18:58
  • 3
    I tried this by throwing an exception on my app's login code but neither event is fired to handle the exception. – Ciaran Gallagher Jun 21 '19 at 12:56
  • I wish I could upvote this more than once. Thanks, this is incredibly helpful! – GabeFC Sep 13 '19 at 20:19
7

The below post is complete

Just in android platform you need to add "AndroidEnvironment.UnhandledExceptionRaiser" event to it

AndroidEnvironment.UnhandledExceptionRaiser += OnAndroidEnvironmentUnhandledExceptionRaiser;
private void OnAndroidEnvironmentUnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs unhandledExceptionEventArgs)
    {
        var newExc = new Exception("OnAndroidEnvironmentUnhandledExceptionRaiser", unhandledExceptionEventArgs.Exception);
        LogUnhandledException(newExc);
    }
user193679
  • 181
  • 2
  • 6
  • Is there anything else needed? I tried this but the event never fires when there is an unhandled exception in my Android app? – Ciaran Gallagher Jun 21 '19 at 12:59
  • This works in android Xamarin, AppDomain.CurrentDomain.UnhandledException and TaskScheduler.UnobservedTaskException never fire. – Marco Ortali Mar 25 '21 at 10:30
  • Android.Runtime.AndroidEnvironment don't have an UnhandledExceptionRaiser member anymore, now is only a class that implements some interfaces, so your code is obsolete – Windgate Sep 09 '22 at 13:45