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 ...
随机推荐
- Html和JS基础
1.body:bgcolor,background(背景图片),bgproperities=fixed(图片水印),text(正文颜色). 2.hr:水平分割线,正文标题<h?>自动换行了 ...
- CABAC
CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码.CABAC是H.264/AVC标准中两种熵编码中的一种, ...
- MFC窗口风格 WS_style/WS_EX_style(超详细)
窗口风格(Window style) WS_BORDER 有边框窗口 WS_CAPTION 必须和WS_BORDER风格配合,但不能与WS_DLGFRAME风格一起使用.指示窗口包含标题要部分 ...
- QPainter类学习
详细描述: QPainter类提供了许多高度优化的函数去做大部分的GUI绘制工作.它可以画从简单的线到复杂的形状.通常情况下,QPainter的使用是在widget当中的painter事件使用.记得在 ...
- Delphi消息的广播方式(先RegisterWindowMessage,后SendMessage HWND_BROADCAST,最后改写接收窗口的WndProc)
///////消息广播只能将消息传递到接收消息的主程序中,MDIChild窗体不能接收到广播消息:///////// unit Unit1; interface uses Windows, Messa ...
- 修改Delphi工具控件的默认字体
修改Delphi工具控件的默认字体: 注册表: Delphi 6: HKEY_CURRENT_USER\Software\Borland\Delphi\6.0Delphi 7: HKEY_ ...
- Android开源项目发现--- 安全篇(持续更新)
SQLCipher Sqlite加密工具 项目地址:https://github.com/sqlcipher/sqlcipher 帮助文档:http://sqlcipher.net/sqlcipher ...
- [cocos2d] 利用texture atlases生成动画
texturepacker可以方便地制作纹理贴图集(Texture Atlases),而且可以免费试用.(可在官网申请免费liscence) //利用软件将5帧png贴图生成1张大的png贴图和pli ...
- Android日志框架darks-logs使用教程
一.配置文件 在使用darks-logs之前,我们需要为它创建一个名叫logd.properties的配置文件.如果你是需要在JAVA或WEB上使用该组件,那么你可以像配置log4j一样将它放在cla ...
- 【转】linux 中dd命令使用详解
原文网址:http://xiaozhuang.blog.51cto.com/4396589/850657 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究 ...