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越来越少。

时间: 2024-10-29 13:07:07

Android实现多次闪退清除数据的相关文章

图片-Android手机应用程序闪退

问题描述 Android手机应用程序闪退 自己是Android初学新手,按照课本上的示例敲代码,结果安装程序成功后,打开其闪退...问了好多次度娘,还是没有着落,还请各位前辈帮帮小弟,不胜感激... 解决方案 代码如下,还请各位前辈帮帮我... package com.example.myfirstapplycation; import android.app.Activity; import android.os.Bundle; import android.view.View; import

android 为啥父类不闪退,但我重新写了个子类后,程序闪退?

问题描述 android 为啥父类不闪退,但我重新写了个子类后,程序闪退? 求教各位大神,下面的是我的一个ViewPager的安卓小程序,如大家所见现在这个android代码是能正常运行的,但当我将代码中所有父类 "ViewPager" 换成 子类 "NoScrollViewPager" 后,程序一打开就闪退... 为啥换了个子类就会闪退啊... package com.example.testviewpagerandtabhost; public class Ma

Android去除烦人的默认闪退Dialog_Android

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

Android去除烦人的默认闪退Dialog

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

Android Studio闪退问题

问题描述 Android Studio闪退问题 近几天android studio动不动就闪退了,弄的我现在项目都开发不了,郁闷至极!求大神帮忙解决! 解决方案 Android Studio问题收集[疑难杂症]Android studio 问题总结Android Studio 那些事|( /** */ )不显示问题 解决方案二: 什么操作系统,重装试了吗?

app-自学Android开发 在模拟器运行闪退

问题描述 自学Android开发 在模拟器运行闪退 初学者自写的程序 ,但是在模拟器下运行闪退!!该怎么改呀?? package com.example.work3; import java.util.ArrayList; import java.util.List; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4

后台-android应用在按Listview时闪退

问题描述 android应用在按Listview时闪退 这是应用的界面 按下ListView中的一条记录后闪退 后台报错的文字 报错所对应的源码 解决方案 空指针,你访问的对象为空,你调试一下就行了 解决方案二: 同意楼上,一般listView都会出现空指针这种问题,在适配器里面做个判断,防止其出现空就好了 解决方案三: 看一下cursor是不是被关闭或者没初始化,空指针了. 解决方案四: 59行,cursor是空值 解决方案五: 一种过来人的意见,遇到这种常见的错误类型,而且自己找不到错误原因

移动-android http连接问题。编译不报错,真机运行闪退

问题描述 android http连接问题.编译不报错,真机运行闪退 public class MainActivity extends Activity { private static String url="www.baidu.com"; private TextView a1 = null; private HttpResponse httpResponse=null; private HttpEntity httpEntity=null; @Override public v

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

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