android APP闪退后如何屏蔽自启动

最近应项目需求,需要实现在APP遇到内部bug闪退时,禁止自启动回到闪退界面

经测试,在 Android 的 API 21 ( Android 5.0 ) 以下,Crash 会直接退出应用,但是在 API 21 ( Android 5.0 ) 以上,系统会遵循以下原则进行重启:

  • 包含 Service,如果应用 Crash 的时候,运行着Service,那么系统会重新启动 Service。
  • 不包含 Service,只有一个 Activity,那么系统不会重新启动该 Activity。
  • 不包含 Service,但当前堆栈中存在两个 Activity:Act1 -> Act2,如果 Act2 发生了 Crash ,那么系统会重启 Act1。
  • 不包含 Service,但是当前堆栈中存在三个 Activity:Act1 -> Act2 -> Act3,如果 Act3 崩溃,那么系统会重启 Act2,并且 Act1 依然存在,即可以从重启的 Act2 回到 Act1。

看了上述解释,我们终于知道应用在什么种情况下才会重启。

面对这样的问题,我们提供两种解决思路,一是允许应用自动重启,并在重启时恢复应用在崩溃前的运行状态。二是禁止应用自动重启,而是让用户在应用发生崩溃后自己手动重启应用。

具体解决办法如下:

1.首选创建一个CrashHanler类

package com.pdl.mallpos.util;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;

import com.pdl.mallpos.PDLApplication;

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    public static CrashHandler mAppCrashHandler;

    private Thread.UncaughtExceptionHandler mDefaultHandler;

    private PDLApplication mAppContext;

    public void initCrashHandler(PDLApplication application) {
        this.mAppContext = application;
        // 获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    public static CrashHandler getInstance() {
        if (mAppCrashHandler == null) {
            mAppCrashHandler = new CrashHandler();
        }
        return mAppCrashHandler;
    }

    @Override
    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());
            System.exit(0);
            System.gc();
        }
    }

    /**
     * 错误处理,收集错误信息 发送错误报告等操作均在此完成.
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        // 自定义处理错误信息
        return true;
    }
}

2.在应用Application的onCreate()接口中调用,具体调用如下:

CrashHandler.getInstance().initCrashHandler(this);

此时可能查阅文档的小伙伴发现很多文档写到这里就结束了,但是执行后发现闪退后仍然会重启到闪退页面,别急,我们需要知道这是什么原因造成的。

退出栈内所有的Acitvity

如果应用在发生崩溃时,回退栈内依然存在没有退出的Activity,即使调用了System.exit(0)方法,应用依然会自动重启。因此我们就需要在应用退出之前,先清除栈内所有的Activity。

3.在Application中创建一个activityList,用来存储所有栈内的Activity,很简单,方法如下

public static List<Activity> activityList = new ArrayList<Activity>();

4.创建一个BaseActivity,让所有的Activity都继承BaseActivity,并在Activity中如下接口执行添加和删除

 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!PDLApplication.activityList.contains(this)){
            PDLApplication.activityList.add(this);
        }

 }





@Override
    protected void onDestroy() {
        super.onDestroy();
        if(PDLApplication.activityList.contains(this)){
            PDLApplication.activityList.remove(this);
        }

    }

5.在刚才的CrashHanler中执行如果Application中的activityList不为空,则手动关闭所有Activity

package com.pdl.mallpos.util;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;

import com.pdl.mallpos.PDLApplication;

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    public static CrashHandler mAppCrashHandler;

    private Thread.UncaughtExceptionHandler mDefaultHandler;

    private PDLApplication mAppContext;

    public void initCrashHandler(PDLApplication application) {
        this.mAppContext = application;
        // 获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    public static CrashHandler getInstance() {
        if (mAppCrashHandler == null) {
            mAppCrashHandler = new CrashHandler();
        }
        return mAppCrashHandler;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            // 如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            if(PDLApplication.activityList.size()>0){
                for(int i=0;i<PDLApplication.activityList.size();i++){
                    Activity activity = PDLApplication.activityList.get(i);
                    if(activity!=null){
                        activity.finish();
                    }
                }
            }
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(0);
            System.gc();
        }
    }

    /**
     * 错误处理,收集错误信息 发送错误报告等操作均在此完成.
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        // 自定义处理错误信息
        return true;
    }
}

好了大功告成,接下来小伙伴们试一下吧。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值