Xamarin.Android-捕獲未處理異常(全域異常)

來源:互聯網
上載者:User

標籤:

一、前言

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;        }    }
View Code
[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);        }    }
View Code

通過實現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;        }    }
View Code

註冊未處理例外狀況事件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

 

如果你覺得文章對你有協助,可以點擊旁邊的“推薦”按鈕,這樣會讓更多需要的人有機會看到

Xamarin.Android-捕獲未處理異常(全域異常)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.