android 中处理崩溃异常并重启程序出现页面重叠的问题

来源:互联网 发布:php url encode 在线 编辑:程序博客网 时间:2024/05/18 03:50

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

人为的制造一个异常

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

尝试二:
通用 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());      }  } 

异常捕获 简单用法介绍:

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());  //结束进程之前可以把你程序的注销或者退出代码放在这段代码之前    }

成功解决问题。

0 0