Xamarin.Android-捕获未处理异常(全局异常)

一、前言

android中如果出现了未处理的异常,程序会闪退,这是非常不好的用户体验,很多用户会因此卸载APP,因此未处理的异常是应该尽力避免的。

有些很难避免的异常(如:IO、网络等),应在代码中进行捕捉并做相应的处理,以阻止程序崩溃闪退。

但是“没有任何程序是完美的”,况且各式各样的android终端也大大增加了异常的出现概率,就连强大的QQ、微信等不也会闪退嘛!

这时就需要全局捕获未处理的异常,并进行处理。(注意:本文中的处理方式并不能阻止APP闪退

处理方式:收集异常信息、当前场景[时间、硬件参数],在合适的时机上传至服务端

作用:1、便于下一版本修复bug           2、便于帮助用户解决异常造成的困难

二、参照java android的方式(这是坑啊)

xamarin.android在很多时候都可以参考java android的代码,因此我按照java android的方式实现了一下“捕获未处理异常”

    [Obsolete]
    public class CrashHandler:Thread.IUncaughtExceptionHandler
    {
        //系统默认的UncaughtException处理类
        private Thread.IUncaughtExceptionHandler mDefaultHandler;
        //CrashHandler实例
        private static CrashHandler INSTANCE = new CrashHandler();
        //程序的Context对象
        private Context mContext;

        /// <summary>
        /// 保证只有一个CrashHandler实例
        /// </summary>
        private CrashHandler()
        {
        }

        /// <summary>
        /// 获取CrashHandler实例 ,单例模式
        /// </summary>
        /// <returns></returns>
        public static CrashHandler GetInstance()
        {
            return INSTANCE;
        }

        public IntPtr Handle
        {
            get { return Thread.CurrentThread().Handle; }
        }

        public void Dispose()
        {
            this.Dispose();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="context"></param>
        public void Init(Context context)
        {
            mContext = context;
            //获取系统默认的UncaughtException处理器
            mDefaultHandler = Thread.DefaultUncaughtExceptionHandler;
            //设置该CrashHandler为程序的默认处理器
            Thread.DefaultUncaughtExceptionHandler = this;
        }

        ///当UncaughtException发生时会转入该函数来处理
        public void UncaughtException(Thread thread, Throwable ex)
        {
            if (!HandleException(ex) && mDefaultHandler != null)
            {
                //如果用户没有处理则让系统默认的异常处理器来处理
                mDefaultHandler.UncaughtException(thread, ex);
            }
            else
            {
                //退出程序
                Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
                JavaSystem.Exit(1);
            }
        }

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="ex"></param>
        /// <returns>如果处理了该异常信息返回true; 否则返回false.</returns>
        private bool HandleException(Throwable ex)
        {
            if (ex == null)
            {
                return false;
            }

            //处理程序(记录 异常、设备信息、时间等重要信息)
            //************

            //提示
            Task.Run(() =>
            {
                Looper.Prepare();
                //可以换成更友好的提示
                Toast.MakeText(mContext, "很抱歉,程序出现异常,即将退出.", ToastLength.Long).Show();
                Looper.Loop();
            });

            //停一会,让前面的操作做完
            System.Threading.Thread.Sleep(2000);

            return true;
        }
    }

[Application(Label = "MyApplication")]
    public class MyApplication : Application
    {
        public MyApplication(IntPtr javaReference, JniHandleOwnership transfer)
            : base(javaReference, transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();

            CrashHandler crashHandler = CrashHandler.GetInstance();
            crashHandler.Init(ApplicationContext);
        }

    }

通过实现Java.Lang.Thread.IUncaughtExceptionHandler接口自定义一个异常处理类CrashHandler,并替换掉Java.Lang.Thread.DefaultUncaughtExceptionHandler,

当UncaughtException发生时会转入CrashHandler类中的UncaughtException方法中,在此处进行异常处理。

然后制造一个异常throw new Exception("我是异常!");,本以为程序会进入CrashHandler类中的UncaughtException方法中,结果却不是,也就是说这种方式失败了,为什么? google后发现,IUncaughtExceptionHandler只能捕获到Dalvik runtime的异常,mono runtime中的C#异常,这个不起作用。

因此这种方式不行,坑坑坑!

三、正确的捕捉方式

[Application(Label = "MyApplication")]
    public class MyApplication : Application
    {
        public MyApplication(IntPtr javaReference, JniHandleOwnership transfer)
            : base(javaReference, transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();

            //注册未处理异常事件
            AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;

            //CrashHandler crashHandler = CrashHandler.GetInstance();
            //crashHandler.Init(ApplicationContext);
        }

        protected override void Dispose(bool disposing)
        {
            AndroidEnvironment.UnhandledExceptionRaiser -= AndroidEnvironment_UnhandledExceptionRaiser;
            base.Dispose(disposing);
        }

        void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
        {
            UnhandledExceptionHandler(e.Exception, e);
        }

        /// <summary>
        /// 处理未处理异常
        /// </summary>
        /// <param name="e"></param>
        private void UnhandledExceptionHandler(Exception ex, RaiseThrowableEventArgs e)
        {
            //处理程序(记录 异常、设备信息、时间等重要信息)
            //**************

            //提示
            Task.Run(() =>
                {
                    Looper.Prepare();
                    //可以换成更友好的提示
                    Toast.MakeText(this, "很抱歉,程序出现异常,即将退出.", ToastLength.Long).Show();
                    Looper.Loop();
                });

            //停一会,让前面的操作做完
            System.Threading.Thread.Sleep(2000);

            e.Handled = true;
        }
    }

注册未处理异常事件AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser; 在AndroidEnvironment_UnhandledExceptionRaiser中进行异常处理。

制造一个异常throw new Exception("我是异常!");,妥妥的进入了AndroidEnvironment_UnhandledExceptionRaiser,OK,成功!

说明:捕获异常后的具体处理,无非就是读取硬件信息、时间、异常信息,并保存至本地,在合适的时机上传至服务端,为了突出重点,我在这里就不实现了。

源码下载

https://github.com/jordanqin/CatchException

参考:

http://forums.xamarin.com/discussion/4576/application-excepionhandler
http://blog.csdn.net/liuhe688/article/details/6584143

如果你觉得文章对你有帮助,可以点击旁边的“推荐”按钮,这样会让更多需要的人有机会看到

时间: 2024-08-06 01:34:12

Xamarin.Android-捕获未处理异常(全局异常)的相关文章

Xamarin.Android捕获全局未处理异常

大家可能尝试过使用原生比较普遍使用的方法: Java.Lang.Thread.DefaultUncaughtExceptionHandler = new UncaughtExceptionHanlder(UncaughtExceptionHandle); 但是发现没什么用,又会尝试使用c#的方法: AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 可能发现部分有用,我也是被这个问题折磨了

Application中捕获APP中的全局异常

1 package com.example.administrator.mystudent; 2 3 import android.app.Application; 4 import android.util.Log; 5 6 import org.xutils.x; 7 8 /** 9 * Created by hyang on 2016/8/23. 10 */ 11 public class MyApplication extends Application { 12 private sta

【Android】 -- 使用UncaughtExceptionHandler捕捉全局异常

在综合统计SDK(欧盟统计局的朋友,百度统计)之后.有一个非常有利的功能测试:错误分析.此功能可以在程序的执行中遇到崩溃(runtimeException)反馈给server,帮助开发者提高产品.多功能适配器机. 然而在公司android开发中不集成这些SDK,那应该怎么实现这种功能呢?以下让我们来看下怎样使用UncaughtExceptionHandler来捕获异常. 首先实现创建一个类,实现UncaughtExceptionHandler接口.代码例如以下: public class Cra

【spring】-- springboot配置全局异常处理器

一.为什么要使用全局异常处理器? 什么是全局异常处理器? 就是把错误异常统一处理的方法. 应用场景: 1.当你使用jsr303参数校验器,如果参数校验不通过会抛异常,而且无法使用try-catch语句直接捕获,这时可以使用全局异常处理器来捕捉该异常. 2.当你自定义了一个异常类,可以在全局异常处理器中来捕捉该异常.(当然也可以直接在抛出异常处直接捕获,但是这样需要在每一个抛出的地方都写一次捕获代码,看起来不够美观且复用性不强,其他异常同理). 所有异常都可以在全局异常处理器中捕获进行统一处理 二

MVC异常处理的7大场景 + MVC的异常处理的过滤器 + 全局异常

1.MVC中捕获异常的过滤器属性时[HandleError] 2. 可以扩展这个属性来捕获异常 3.注册这个过滤器 4.Mvc的异常捕获时:Filter + 全局异常捕获 5.异常处理的7大场景 /// <summary> /// 异常处理在MVC中可以用过滤器属性[HandleError]实现--->利用Aop扩展这个属性 /// /// 自定义异常处理--标记到方法---出现异常惠静如Filter---完成善后处理 /// /// /// 全局注册的异常处理的Filter,7大场景会

springmvc中拦截器与springmvc全局异常处理器的问题

最近在做一个练手的小项目, 系统架构中用了springmvc的全局异常处理器, 做了系统的统一异常处理. 后来加入了springmvc的拦截器, 为了一些需求, 在拦截器中的 preHandle 方法 中抛出了系统自定义异常, 当时有有个疑惑, 就是抛出的这个异常全局异常处理器怎么处理的. 这里的全局异常处理器时通过实现HandlerExceptionResolver这个借口实现的 要指出的是 resolveException方法 中 handler中代表的是什么,我没遇到这个问题之前我认为这玩

Android应用捕获全局异常自定义处理

[2016-06-30]最新的全局异常处理DRCrashHandler已经集成在DR_support_lib库中 具体请看: https://coding.net/u/wrcold520/p/DR_support_lib/git/tree/master [2016-06-28] 1 增加log4j的支持[2016-06-28] 2 增加全局异常处理(可自定义程序崩溃提示消息,自定义发送错误报告到服务器)[2016-06-28] 3 增加两种应用退出方法:① appExit,结束掉所有Acitiv

Android程序捕获未处理异常,处理与第三方方法冲突时的异常传递

自己的android程序对异常进行了处理,用的也是网上比较流行的CrashHandler,代码如下,就是出现了未处理的异常程序退出,并收集收集设备信息和错误信息仪器保存到SD卡,这里没有上传到服务器. public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; // CrashHandler 实例 private stat

Android应用源码之捕获全局异常

Android应用源码之捕获全局异常 本项目就是一个简单的全局异常捕捉例子,捕捉到异常以后可以把异常信息写入文件以供后来分析或者用友好的方式进行提示后再退出程序. 下载地址:http://www.devstore.cn/code/info/630.html