web-dev-qa-db-fra.com

Gestion des exceptions globales dans la plateforme Xamarin Cross

Pouvez-vous s'il vous plaît laissez-moi savoir comment gérer l'exception globale (sans crash d'application) dans le projet de plateforme Xamarin Cross.

19
Ashaar

Il n'y a pas de méthode 'Xamarin.Forms' à ma connaissance. Vous devez vous connecter à Android et iOS, ce que vous pourriez faire est de créer une méthode qui les gère tous les deux de la même manière.

Un bon post à ce sujet est de Peter Norman. Il décrit que pour l'implémenter dans Android vous pouvez le faire dans votre MainActivity.cs.

// 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‬

Et pour iOS, vous pouvez ajouter du code comme celui-ci dans votre AppDelegate.cs.

//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;  
    // Rest of your code...
}  

/// <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();
}

Il inclut également la possibilité d'afficher le journal lorsque vous déboguez l'application. Bien sûr, vous pouvez implémenter vos propres méthodes de journalisation ou de gestion. Une chose que vous pourriez regarder est HockeyApp . Cela gère les exceptions non gérées par défaut et vous les renvoie, entre autres.

Mettre à jour, car cela se trouve toujours sur Google: Pour les rapports de plantage et les analyses, vous voulez maintenant commencer à regarder App Center . Il s'agit de l'évolution de HockeyApp et Xamarin Insights (entre autres comme la création, la distribution et les notifications Push) et agit désormais comme le tableau de bord de la mission pour tout ce qui a à voir avec les applications, et pas seulement Xamarin.

Pour UWP et WinPhone 8.1, il devrait y avoir un gestionnaire UnhandledException dans l'objet Application. Consultez cette réponse pour plus d'informations. Je cite:

Pour les applications basées sur XAML, vous pouvez utiliser nhandledException ; cependant, cela ne capture que les exceptions qui surviennent via le framework XAML (UI) et vous n'obtenez pas toujours beaucoup d'informations sur la cause première, même dans InnerException.

Mise à jour pour Windows 8.1 : nhandledException capture également les exceptions qui sont créées par une méthode async void. Dans Windows 8, de telles exceptions ne feraient que planter l'application. LunarFrog en a une bonne discussion sur leur site Web.

Fondamentalement, vous devez ajouter un gestionnaire d'événements dans le constructeur de votre App() dans App.xaml.cs: this.UnhandledException += (o, s) => {}.

42
Gerald Versluis