【发布时间】:2017-01-23 00:34:57
【问题描述】:
能否请您告诉我如何处理 Xamarin 跨平台项目中的全局异常(无 App 崩溃)。
【问题讨论】:
-
查看 HockeyApp hockeyapp.net
标签: xamarin xamarin.ios xamarin.android xamarin.forms cross-platform
能否请您告诉我如何处理 Xamarin 跨平台项目中的全局异常(无 App 崩溃)。
【问题讨论】:
标签: xamarin xamarin.ios xamarin.android xamarin.forms cross-platform
据我所知,没有一种“Xamarin.Forms”的方法。你需要连接到 Android 和 iOS,你可以做的是创建一种方法来以相同的方式处理它们。
一个很好的post 来自彼得诺曼。他描述了要在 Android 中实现它,您可以在 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
对于 iOS,您可以在 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();
}
它还包括在您调试应用程序时显示日志的功能。当然,您可以实现自己的日志记录或处理方法。您可以查看的一件事是HockeyApp。默认情况下,这会处理未处理的异常并将它们发送回给您,等等。
更新,因为这仍然可以在 Google 上找到:对于崩溃报告和分析,您现在想开始查看 App Center。这是 HockeyApp 和 Xamarin Insights(其中包括构建、分发和推送通知等)的演变,现在充当与应用相关的所有事情的任务仪表板,而不仅仅是 Xamarin。
对于 UWP 和 WinPhone 8.1,Application 对象中应该有一个 UnhandledException 处理程序。查看this answer 了解更多信息。我引用:
对于基于 XAML 的应用,您可以使用UnhandledException;然而,那 仅捕获通过 XAML (UI) 框架出现的异常 你并不总是能得到很多关于根的信息 原因是,即使在 InnerException 中。
Windows 8.1 更新:UnhandledException 也将捕获 由 async void 方法创建的异常。在 Windows 8 中, 此类异常只会使应用程序崩溃。 LunarFrog 有一个很好的 discussion 在他们的网站上。
基本上你应该在App.xaml.csApp()的构造函数中添加一个事件处理程序:this.UnhandledException += (o, s) => {}。
【讨论】:
这就是我为 xamarin forms Android 全局异常处理和应用程序崩溃所做的。
此解决方案将同时处理后台和前台异常。
AppDomain.CurrentDomain.UnhandledException += (s,e)=>
{
System.Diagnostics.Debug.WriteLine("AppDomain.CurrentDomain.UnhandledException: {0}. IsTerminating: {1}", e.ExceptionObject, e.IsTerminating);
};
AndroidEnvironment.UnhandledExceptionRaiser += (s, e) =>
{
System.Diagnostics.Debug.WriteLine("AndroidEnvironment.UnhandledExceptionRaiser: {0}. IsTerminating: {1}", e.Exception, e.Handled);
e.Handled = true;
};
因此,我对两种类型的异常都有不同的行为:
前景:
背景:
【讨论】: