登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

查看: 346|回复: 5

Android实现多次闪退清除数据,android sdk闪退

[复制链接]

443

主题

861

帖子

1975

安币

手工艺人

发表于 2018-1-11 15:55:53 | 显示全部楼层 |阅读模式

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

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

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

[Java] 查看源文件 复制代码
public class crashhandler implements reportsender {
  @override
  public void send(context context, crashreportdata errorcontent) throws reportsenderexception {
    timber.i("闪退,检查是否需要清空数据");
    new crashmodel().checkandcleardata();
  }
}

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

[Java] 查看源文件 复制代码
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类中添加如下代码。

[Java] 查看源文件 复制代码
@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); //在闪退时检查是否要清空数据
    }

  }
}



0

主题

9563

帖子

1620

安币

Android大神

IT

Rank: 6Rank: 6

发表于 2018-1-13 03:09:36 | 显示全部楼层
不错不错,楼主辛苦了。。。

20

主题

8964

帖子

2365

安币

Android大神

Rank: 6Rank: 6

发表于 2018-1-14 04:57:03 | 显示全部楼层
每次我都积极回帖的,想要安币~

92

主题

9324

帖子

1995

安币

Android大神

Rank: 6Rank: 6

发表于 2018-1-14 21:50:05 | 显示全部楼层
感觉楼主很用心,辛苦啦~

11

主题

9132

帖子

1002

安币

Android大神

Rank: 6Rank: 6

发表于 2018-1-15 09:57:52 | 显示全部楼层
安卓巴士是个不错的网站,我来顶个贴~

0

主题

1万

帖子

2420

安币

Android大神

Rank: 6Rank: 6

发表于 2018-1-15 19:53:24 | 显示全部楼层
感谢分享,安卓巴士有你更精彩:lol
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表