android 中处理崩溃异常

Android开发中经常会遇到程序异常,而已常常会遇到一出现异常APP就自动重启了,而已如果你的项目中应用到Fragment的切换的话,会出行页面重叠的现象。今天为了解决这个问题看了不少大牛的博客。最后终于把问题解决了,下面就把解决的方法做一个介绍。 
总的问题解决定向是处理崩溃异常的方法。先说说我前面尝试的不成功的方法。 
一、写一个类实现UncaughtExceptionHandler 接口


import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by willkong on 2016/12/14.
 */

public class UnCeHandler implements Thread.UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    public static final String TAG = "CatchExcep";
    MyApplication application;

    public UnCeHandler(MyApplication application){
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = application;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if(!handleException(ex) && mDefaultHandler != null){
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        }else{
            try{
                Thread.sleep(2000);
            }catch (InterruptedException e){
                Log.e(TAG, "error : ", e);
            }
            Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
            PendingIntent restartIntent = PendingIntent.getActivity(
                    application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
            //退出程序
            AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
                    restartIntent); // 1秒钟后重启应用
            application.finishActivity();
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则没有处理返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(application.getApplicationContext(), "很抱歉,程序出现异常,即将退出.",
                        Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        return true;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

二、通过在android Application 这个全局类中处理异常,一般我们都会重写一个我们自己的Application继承Application。


import android.app.Activity;
import android.app.Application;

import java.util.ArrayList;

/**
 * Created by willkong on 2016/12/14.
 */

public class MyApplication extends Application {
    ArrayList<Activity> list = new ArrayList<Activity>();

    @Override
    public void onCreate() {
        super.onCreate();
        //设置该CrashHandler为程序的默认处理器
        UnCeHandler catchExcep = new UnCeHandler(this);
        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
    }

    /**
     * Activity关闭时,删除Activity列表中的Activity对象*/
    public void removeActivity(Activity a){
        list.remove(a);
    }

    /**
     * 向Activity列表中添加Activity对象*/
    public void addActivity(Activity a){
        list.add(a);
    }

    /**
     * 关闭Activity列表中的所有Activity*/
    public void finishActivity(){
        for (Activity activity : list) {
            if (null != activity) {
                activity.finish();
            }
        }
        //杀死该应用进程
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

人为的制造一个异常


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    Button btn;
    TextView tv;
    private MyApplication application;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button)findViewById(R.id.btn);
        tv = (TextView)findViewById(R.id.tv);

        application = (MyApplication) getApplication();
        application.addActivity(this);

        btn.setOnClickListener(this);
    }

    /**
     * 人为制造的异常*/
    public void press(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                tv.setText("dfsd");
            }
        }).start();
    }
    @Override
    public void onClick(View v) {
        press();
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.testapplication.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

尝试二: 
通用 application 
1、收集所有 avtivity 用于彻底退出应用 
2、捕获崩溃异常,保存错误日志,并重启应用

public class HKBaseApplication extends Application {  
    // activity对象列表,用于activity统一管理  
    private List<Activity> activityList;  
    // 异常捕获  
    protected boolean isNeedCaughtExeption = true;// 是否捕获未知异常  
    private PendingIntent restartIntent;  
    private MyUncaughtExceptionHandler uncaughtExceptionHandler;  
    private String packgeName;  

    @Override  
    public void onCreate() {  
        super.onCreate();  

        activityList = new ArrayList<Activity>();  
        packgeName = getPackageName();  

        if (isNeedCaughtExeption) {  
            cauchException();  
        }  
    }  

    // -------------------异常捕获-----捕获异常后重启系统-----------------//  

    private void cauchException() {  
        Intent intent = new Intent();  
        // 参数1:包名,参数2:程序入口的activity  
        intent.setClassName(packgeName, packgeName + ".LoginActivity");  
        restartIntent = PendingIntent.getActivity(getApplicationContext(), -1, intent,  
                Intent.FLAG_ACTIVITY_NEW_TASK);  

        // 程序崩溃时触发线程  
        uncaughtExceptionHandler = new MyUncaughtExceptionHandler();  
        Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);  
    }  

    // 创建服务用于捕获崩溃异常  
    private class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {  
        @Override  
        public void uncaughtException(Thread thread, Throwable ex) {  
            // 保存错误日志  
            saveCatchInfo2File(ex);  

            // 1秒钟后重启应用  
            AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);  
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);  

            // 关闭当前应用  
            finishAllActivity();  
            finishProgram();  
        }  
    };  
    /** 
     * 保存错误信息到文件中 
     *  
     * @return 返回文件名称 
     */  
    private String saveCatchInfo2File(Throwable ex) {  
        Writer writer = new StringWriter();  
        PrintWriter printWriter = new PrintWriter(writer);  
        ex.printStackTrace(printWriter);  
        Throwable cause = ex.getCause();  
        while (cause != null) {  
            cause.printStackTrace(printWriter);  
            cause = cause.getCause();  
        }  
        printWriter.close();  
        String sb = writer.toString();  
        try {  
            DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");  
            String time = formatter.format(new Date());  
            String fileName = time + ".txt";  
            System.out.println("fileName:" + fileName);  
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {  
                String filePath = Environment.getExternalStorageDirectory() + "/HKDownload/" + packgeName  
                        + "/crash/";  
                File dir = new File(filePath);  
                if (!dir.exists()) {  
                    if (!dir.mkdirs()) {  
                        // 创建目录失败: 一般是因为SD卡被拔出了  
                        return "";  
                    }  
                }  
                System.out.println("filePath + fileName:" + filePath + fileName);  
                FileOutputStream fos = new FileOutputStream(filePath + fileName);  
                fos.write(sb.getBytes());  
                fos.close();  
                //文件保存完了之后,在应用下次启动的时候去检查错误日志,发现新的错误日志,就发送给开发者  
            }  
            return fileName;  
        } catch (Exception e) {  
            System.out.println("an error occured while writing file..." + e.getMessage());  
        }  
        return null;  
    }  

    // ------------------------------activity管理-----------------------//  

    // activity管理:从列表中移除activity  
    public void removeActivity(Activity activity) {  
        activityList.remove(activity);  
    }  

    // activity管理:添加activity到列表  
    public void addActivity(Activity activity) {  
        activityList.add(activity);  
    }  

    // activity管理:结束所有activity  
    public void finishAllActivity() {  
        for (Activity activity : activityList) {  
            if (null != activity) {  
                activity.finish();  
            }  
        }  
    }  

    // 结束线程,一般与finishAllActivity()一起使用  
    // 例如: finishAllActivity;finishProgram();  
    public void finishProgram() {  
        android.os.Process.killProcess(android.os.Process.myPid());  
    }  
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122

异常捕获 简单用法介绍:

public class MyApplication extends Application implements  
        Thread.UncaughtExceptionHandler {  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        //设置Thread Exception Handler  
        Thread.setDefaultUncaughtExceptionHandler(this);  
    }  

    @Override  
    public void uncaughtException(Thread thread, Throwable ex) {  
        System.out.println("uncaughtException");  
        System.exit(0);  
        Intent intent = new Intent(this, MainActivity.class);  
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |  
        Intent.FLAG_ACTIVITY_NEW_TASK);  
        startActivity(intent);  
    }  

}  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

以上的尝试方法都没有成功,下面的一种方式成功了。 
步骤一、在你自己的Application类的onCreate()方法下 加入代码捕获异常,并且处理异常。Thread.setDefaultUncaughtExceptionHandler(restartHandler); // 程序崩溃时触发线程 以下用来捕获程序崩溃异常

@Override
    public void onCreate() {
        super.onCreate();
        Thread.setDefaultUncaughtExceptionHandler(restartHandler); // 程序崩溃时触发线程  以下用来捕获程序崩溃异常
        }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

步骤二、 编写方法创建服务用于捕获崩溃异常并且处理

// 创建服务用于捕获崩溃异常
    private UncaughtExceptionHandler restartHandler = new UncaughtExceptionHandler() {
        public void uncaughtException(Thread thread, Throwable ex) {
            restartApp();//发生崩溃异常时,重启应用
        }
    };
    //重启App
    public void restartApp(){
        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.startActivity(intent);
        android.os.Process.killProcess(android.os.Process.myPid());  //结束进程之前可以把你程序的注销或者退出代码放在这段代码之前
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值