Android实现多次闪退清除数据

很多时候由于后台返回的数据异常,可能会导致App闪退。而如果这些异常数据被App本地缓存下来,那么即使杀掉进程重新进入还是会发生闪退。唯一的解决方法就是清除App数据,但是用户可能没有这个意识或者嫌麻烦就直接不再使用了,这是我们无法接受的。在使用淘宝、追书神器等App时我发现有时候它们也会连续闪退,但是往往闪退三次后就恢复正常了,所以一般成熟的App都会做连续闪退三次后清除缓存数据的工作。而目前笔者搜不到有哪篇blog来讲这方面的事情,所以就姑且由我来讲讲此事,为希望提高App用户体验的朋友提供些许参考。

ACRA
为了能够在闪退的时候做一些事情,我们可以使用ACRA,这是Github上的一个开源项目,允许使用者设置一些Sender在App闪退的时候做一些事情。具体使用可以直接参考Github。如果不希望使用ACRA,那么也可以自己实现一个UncachedExceptionHandler并替换系统默认的Handler,并在这个Handler里面对数据进行处理。

实现清除数据
ACRA提供了自己的一些Sender,如使用系统邮件客户端向指定邮箱发送邮件的EmailIntentSender。而我们希望记录闪退次数和清除数据则需要implements ReportSender接口。

public class CrashHandler implements ReportSender {
  @Override
  public void send(Context context, CrashReportData errorContent) throws ReportSenderException {
    Timber.i("闪退,检查是否需要清空数据");
    new CrashModel().checkAndClearData();
  }
}

这里我们写了一个CrashModel用来记录闪退次数和时间决定是否需要清空数据,具体代码如下。 由于在ReportSender的时候无法打开其它线程,所以我们无法使用SharedPerferences来清理数据(打开SP的时候其实打开了一个新线程)。为此需要找到数据缓存的位置并将文件删除。同样道理,记录闪退时间也只能通过文件记录。当然,你可以选择一些文件不进行删除,如用户信息等不太容易出问题的数据。

public class CrashModel {

  private static final String KEY_CRASH_TIMES = "crash_times";
  private static final String CRASH_TIME_FILE_NAME = "crash_time";
  //不能通过App.getPackageName来获取包名,否则会有问题,只能默认为cn.campusapp.campus。所以对于debug或者运营版本,清数据会把release的清掉
  private static final String FILE_DIR = String.format("/data/data/%s/", BuildConfig.APPLICATION_ID);
  private static final String ACCOUNT_FILE_NAME = String.format("%s%s", FILE_DIR, "shared_prefs/account_pref.xml");
  private static ArrayList<String> FILES_DONTNEED_DELETE = new ArrayList<>(); //该目录中的文件不会被删除

  static {
    FILES_DONTNEED_DELETE.add(ACCOUNT_FILE_NAME); //目前账号信息文件不会被删除,但是会手动改变数据,只保留userId accessToken 和school
  }

  protected ArrayList<Long> mCrashTimes;
  Gson gson = new Gson();
  private File mFileDir;

  public CrashModel() {
    mFileDir = new File(FILE_DIR);
    mCrashTimes = readCrashTimes();
    if (mCrashTimes == null) {
      mCrashTimes = new ArrayList<>();
      storeCrashTimes(mCrashTimes);
    }
  }

  public void checkAndClearData() {
    long timeNow = System.currentTimeMillis();

    if (checkClearData(timeNow, new ArrayList<>(mCrashTimes))) {
      Timber.i("已经在5分钟之内有三次闪退,需要清理数据");
      try {
        clearData();
      } catch (Exception e) {
        Timber.e(e, "清空所有数据失败");
      }
    } else {
      mCrashTimes.add(timeNow);
      storeCrashTimes(mCrashTimes);
      Timber.i("此次不需要清空数据, %s", gson.toJson(mCrashTimes));
    }
  }

  private void storeCrashTimes(ArrayList<Long> crashTimes) {
    try {
      String str = gson.toJson(crashTimes);
      Files.writeToFile(mFileDir, CRASH_TIME_FILE_NAME, str);
    } catch (Exception e) {
      Timber.e(e, "保存闪退时间失败");
    }

  }

  private ArrayList<Long> readCrashTimes() {
    try {
      String timeStr = Files.readFileContent(mFileDir, CRASH_TIME_FILE_NAME);
      return gson.fromJson(timeStr, new TypeToken<ArrayList<Long>>() {
      }.getType());
    } catch (Exception e) {
      Timber.e(e, "读取闪退时间失败");
    }
    return null;
  }

  /**
   * 检查是否需要清空数据,目前的清空策略是在5分钟之内有三次闪退的就清空数据,也就是从后往前遍历,只要前两次闪退发生在5分钟之内,就清空数据
   *
   * @return
   */
  private boolean checkClearData(long time, ArrayList<Long> crashTimes) {
    Timber.i(gson.toJson(crashTimes));
    int count = 0;
    for (int i = crashTimes.size() - 1; i >= 0; i--) {
      long crashTime = crashTimes.get(i);
      if (time - crashTime <= 5 * 60 * 1000) {
        count++;
        if (count >= 2) {
          break;
        }
      }
    }
    if (count >= 2) {
      //在5分钟之内有三次闪退,这时候需要清空数据
      return true;
    } else {
      return false;
    }
  }

  /**
   * 清空数据,包括数据库中的和SharedPreferences中的
   *
   * @throws Exception
   */
  private void clearData() throws Exception {
    Timber.i("开始清理数据");
    Files.deleteFilesExceptSomeInDirectory(mFileDir, FILES_DONTNEED_DELETE);
  }

}

然后我们需要将CrashHandler 添加到ACRA的异常处理Sender列表中。在你的Application类中添加如下代码。

@ReportsCrashes(
  //一些ACRA的设置,具体参考ACRA文档,因为我们使用自定义Sender,所以这里完全可以不用设置
    //mailTo = "bugs@treeholeapp.cn",
    //mode = ReportingInteractionMode.TOAST,
    //resToastText = R.string.crash_toast_text
)
public class App extends Application {

  @Override
  public void onCreate() {
   if (!BuildConfig.DEBUG) { //这里我判断只有在非DEBUG下才清除数据,主要是为了在开发过程中能够保留线程。
        ACRA.init(APPLICATION_CONTEXT);
        CrashHandler handler = new CrashHandler();
        ACRA.getErrorReporter().setReportSender(handler); //在闪退时检查是否要清空数据
    }

  }
}

总结
以上即为实现多次闪退后清除数据的实现,希望大家开发的App Bug越来越少。

(0)

相关推荐

  • Android实现分享微信好友及出现闪退的解决办法

     1.申请微信APPID 要实现分享到微信的功能,首先要到微信开放平台申请一个APPID.但在申请APPID的时候需要填写一个应用签名和应用包名.需要注意的是包名必须与开发应用时的包名一致,应用签名也必须去掉冒号而且字母为小写. 2.应用签名的获取 开发android应用的人很多,很有可能类名.包名起成了同一个名字,签名这时候就起到区分的作用. 所有的Android应用都必须有数字签名,不存在没有数字签名的应用,包括模拟器运行的.模拟器开发环境,开发时,通过ADB接口上传的程序会自动被签有Deb

  • Android 清除SharedPreferences 产生的数据(实例代码)

    复制代码 代码如下: 定义:        SharedPreferences preferences = null; SharedPreferences.Editor editor = null; preferences = getSharedPreferences(TAG, Activity.MODE_PRIVATE);  editor = preferences.edit();在onstop里面保存播放位置 @Override protected void onStop() {  edit

  • Android去除烦人的默认闪退Dialog

    安卓应用闪退后总会出现一个"抱歉,App已经停止运行"的弹窗,这样的用户体验并不好.很多大厂的App都去除了这个弹窗,因此本文主要介绍如何去除默认闪退弹窗,以及在闪退时做一些必要的善后工作. UnCaughtExceptionHandler UnCaughtExceptionHandler能够在Thread遇到未catch住的Exception而终止前做一些善后工作.但是它无法阻止线程停止运行,线程最后还是要退出. Thread.setDefaultUncaughtExceptionH

  • Android系统设置中的清除数据会清除哪些数据?

    What will be removed If you click Clear Data Button in the System Application 今天中的一个story突然提到了系统设置中的清理数据,后来开始思考究竟系统的应用的这个清理功能,究竟会清理那些数据. 于是开始研究,以com.mx.browser为例,思路大概为首先为/data/data/com.mx.browser下的每一个文件夹下建立一个标志文件,这里为1.txt,然后执行清理数据操作,最后对比结果. 首先,进行清楚数据

  • android开发教程之清除android数据缓存示例(清除本地数据缓存)

    复制代码 代码如下: /*  * 文 件 名:  DataCleanManager.java  * 描    述:  主要功能有清除内/外缓存,清除数据库,清除sharedPreference,清除files和清除自定义目录  */ import java.io.File;import android.content.Context;import android.os.Environment; /** * 本应用数据清除管理器 */public class DataCleanManager { 

  • Android实现多次闪退清除数据

    很多时候由于后台返回的数据异常,可能会导致App闪退.而如果这些异常数据被App本地缓存下来,那么即使杀掉进程重新进入还是会发生闪退.唯一的解决方法就是清除App数据,但是用户可能没有这个意识或者嫌麻烦就直接不再使用了,这是我们无法接受的.在使用淘宝.追书神器等App时我发现有时候它们也会连续闪退,但是往往闪退三次后就恢复正常了,所以一般成熟的App都会做连续闪退三次后清除缓存数据的工作.而目前笔者搜不到有哪篇blog来讲这方面的事情,所以就姑且由我来讲讲此事,为希望提高App用户体验的朋友提供

  • Android apk无法安装及闪退问题解决办法

    Android apk无法安装及闪退问题 app在部分手机上(低版本)打不开或打开就闪退的问题 之前做项目集成的是 环信的sdk ,环信的sdk 确实很好,客服 也很给力.但是在集成的过程中发现,apk 在手机上发布不了,要么就是,安装了 打不开,打开就闪退:问题有一下两方面 1.之前做过一个环信的即时通讯,集成好环信的sdk之后在4.x的手机上就打开就闪退,,只能在5.x和6.x手机上打开app 2.最近又碰到了同样的问题不过这次和上次不一样,这次是因为我的 as升级到了 2.3 之后出现的这

  • Android使用百度地图出现闪退及定位时显示蓝屏问题的解决方法

    使用百度地图出现闪退 一般情况下出现闪退是在AndroidManifest.xml文件中未在application标签中配置 <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="D9Lh8MrrLMUuXdWMU8tRLtDsta6PoaYN" /> 但是,有些同学会发现,所有配置都是按照官网或者教程上的步骤来配置依旧会出现闪退问题.此时,不要盲目直接去网上搜索使用百度地图出

  • Android6.0蓝牙出现无法扫描设备或闪退问题解决办法

    Android6.0蓝牙出现无法扫描设备或闪退问题解决办法 前言: 目前待的这家公司是做智能家居的,最近客户那边有反馈说为什么我的手机蓝牙也打开了,设备的蓝牙也打开了,为啥总是扫描不到呢,但是我们公司的测试人员几经排查,并未发现客户的所描述的扫描不到设备,但客户所说的问题确实又存在,几经周折,找到了原因,原来是现在市场上出来的android6.0手机需要添加两个权限,Android官网也已经说明了, 直接上图 具体权限官网说的很清楚了 解决办法 Android6.0设备通过蓝牙和Wi-Fi扫描访

  • ubuntu上在androidstudio中启动emulator闪退的解决方法

    阅读目录(Content) 平台 现象 解决 一.查看模拟器的信息 二.命令行运行模拟器 平台 Ubuntu14.04 64 现象 在AndrodStudio中点击模拟器的启动按钮后,模拟器界面弹出后,又立刻闪退. 解决 一.查看模拟器的信息 从上面可以看到模拟器的存放路径以及名称: 路径:/home/pengdonglin/.android/avd/4_WVGA_Nexus_S_API_24.avd 名称:4_WVGA_Nexus_S_API_24 架构:x86_64 二.命令行运行模拟器 在

  • react native android6+拍照闪退或重启的解决方案

    前言 android 6+权限使用的时候需要动态申请,那么在使用rn的时候要怎么处理拍照权限问题呢?本文提供的是一揽子rn操作相册.拍照的解决方案,请看正文的提高班部分. 解决步骤 1.AndroidManifest.xml设置拍照权限: <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="andr

  • Android 获取应用缓存大小与清除缓存的方法

    如下所示: package com.lucasey.littleant.frame; /** * 文 件 名: FileCacheUtils.java * 描 述: 主要功能有清除内/外缓存,清除数据库,清除sharedPreference,清除files和清除自定义目录 * */ import java.io.File; import java.math.BigDecimal; import android.content.Context; import android.os.Environm

  • react native打包apk文件安装好之后进入应用闪退的解决方案

    目录 react native打包apk文件安装好之后进入应用闪退 可以试试下面的方法 react-native程序出现闪退原因之一 原因 react native打包apk文件安装好之后进入应用闪退 这个是我一个前端前辈帮我弄的,自己解决的时候不行,她去官网找了相关的问题,然后发给我的. react-native android 的release安装包运行闪退,但是debug运行正常 环境:0.63.3 安卓集成react-native时根据官网提供的文档配置后,跳转到rn页面时闪退,或者页面

随机推荐