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;
    }
}

二、通过在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 list = new ArrayList();

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

人为的制造一个异常


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

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

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

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

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

        activityList = new ArrayList();  
        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());  
    }  
} 

异常捕获 简单用法介绍:

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

}  

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

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

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

// 创建服务用于捕获崩溃异常
    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());  //结束进程之前可以把你程序的注销或者退出代码放在这段代码之前
    }

成功解决问题。

你可能感兴趣的:(android知识点)