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越来越少,鲁棒性越来越强。
Android实现多次闪退清除数据的更多相关文章
- Android中处理崩溃闪退错误
Android中处理崩溃闪退异常 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试, ...
- android app启动就闪退怎么办?
开发过程中,如遇到android app启动就闪退,不要急,直接进入调试模式运行app,就会取得出错的原因. http://blog.sina.com.cn/s/blog_44fa172f0102wg ...
- Android常见崩溃或闪退的问题描述及原因总结、及与性能相关的模块——持续更新
1.nullpointer——就是使用一个对象的时候还没有对其进行初始化导致该问题 一般在何种情况下容易出现呢? (1)父窗口+子窗口同时出现的,父窗口因为某种原因消掉了,子窗口还在,操作子窗口找不到 ...
- Android存储扩展学习-----应用的清除数据和清除缓存
前几天和朋友聊到了APP清除数据这块,聊到了清除数据都会清掉哪些数据,我们每个人的手机在”设置–>应用管理”里面,选择任意一个App,都会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我 ...
- Android Studio Activity Intent 闪退崩溃 Toolbar
今天写登录注册页面,点击登录页面的“注册”按钮后软件突然崩溃,直接闪退,因为是新手,只能去网上搜.虽然网上解决方法众多,但也没找到可行的.想起来可以看Logcat,马上重新运行应用,查看崩溃时的日志, ...
- JAVA Eclipse开发Android程序会经常闪退是怎么回事
类没有new就直接用会闪退,比如下面我在前面声明了ClientSocket的类,点击连接按钮之后,如果不先new就直接Connect就会闪退 你在当前页面创建findViewById的时候,如果找 ...
- Android 防止切换横屏闪退
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...
- 开发android过程中eclipse闪退解决
有一次eclipse崩溃了,然后再双击就无法打开了.换了几个版本也是如此. 后来找到了这个方法:删除文件 [workspace]/.metadata/.plugins/org.eclipse.e4.w ...
- 升级iOS8系统后,保险箱Pro、私人保险箱、私密相冊打开就闪退的官方解决方式
升级iOS8系统后,保险箱Pro.私人保险箱.私密相冊打开就闪退的官方解决方式 写在前面的话: 1. 本文适用条件 适用于:您的保险箱Pro.私人保险箱.私密相冊在iPhone或iPad ...
随机推荐
- [BZOJ 2127] happiness 【最小割】
题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建 ...
- C语言中.h和.c文件解析
整理自C语言中.h和.c文件解析(很精彩) Part.1(林锐<高质量C/C++编程>) 通过头文件来调用库功能.在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的 ...
- 使用lombok
Lombok是一种JavaArchive(JAR)文件,可用来消除Java代码的冗长.通过在开发环境中实现Lombok,开发人 员可以节省构建诸如hashCode()和equals()这样的方法以及以 ...
- java中基本类型封装对象所占内存的大小(转)
这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字. 实现的想法是这样的:java.lang.Runt ...
- 算法-KMP模式匹配算法
1朴素算法:逐个比较 2 主要是解决多余比较的麻烦,通过处理比较字符串是否含有重复的字符的问题.
- Say To ME
每天都要有计划,无计划不生活. 计划包括天计划和月计划. 每个月应该有月主题. 避免大概,可能,貌似,等不肯定的词语.增强自信心,增强给别人的自信心. 不熬夜,早睡. 多运动,每周应该至少出门一次,运 ...
- BZOJ2083: [Poi2010]Intelligence test
2083: [Poi2010]Intelligence test Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 241 Solved: 96[Sub ...
- 每天一个linux命令:mkdir
linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命令 ...
- 解决导入lib,关联源码问题
关联源代码:在libs目录下新建文件,以jar包全名(包括.jar)为文件名称,以.properties结尾 在文件中新建键值对:src=jar包源代码绝对路径:根据提示将单斜线变成双斜线, 然后cl ...
- CSS3 概览 更新时间 2014-0412-1317
CSS3 概览 CSS3可以划分为:文字.边框模型.背景.动画等. CSS3颜色模块 CSS2.1的时候可以使用4种颜色方式,直接使用颜色名,如 redRGB值,如 rgb(0,90,255)RGB百 ...