先了解下Crash原理
其实android中有处理异常类问题的方法,请看下面Thread类中的一个方法#setDefaultUncaughtExceptionHandler
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
Thread.defaultUncaughtHandler = handler;
从方法的字面意义来看,这个方法好像是可以设置系统的默认异常处理器,其实,这个方法就可以解决应用常见的crash问题。当crash发生的时候,我们可以捕获到异常信息,把异常信息存储到SD卡中,然后在合适的时机通过网络将crash信息上传到服务器上,这样开发人员就可以分析用户crash的场景从而在后面的版本中修复此类crash。我们还可以在crash发生时,弹出一个通知告诉用户程序crash了,然后再退出,这样做比闪退要温和一点。
步骤
创建CrashHandler类,实现 Thread.UncaughtExceptionHandler 接口
编写崩溃处理逻辑,崩溃的时候回调用uncaughtException()方法
在自定义application中注册CrashHandler
Bugly热更新是基于Tinker使用的。
为什么使用Bugly呢,因为他目前还没有收费
费话不多说了,言归正传
使用教程,跟着步骤一步一步教你集成
因为集成应用升级的时候的包已经自动帮你基层了上报崩溃,所以直接从应用升级开始讲
gradle集成方式 具体配置参考官网链接
ndk {
//设置支持的SO库架构
abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
//注释掉原有bugly的仓库
//compile 'com.tencent.bugly:crashreport:latest.release'//其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.3.2
implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6'
//其中latest.release指代最新版本号,也可以指定明确的版本号,例如1.2.0
implementation 'com.tencent.bugly:nativecrashreport:3.6.0'
//其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.2.0
后续更新升级SDK时,只需变更配置脚本中的版本号即可。
注意: 升级SDK已经集成crash上报功能,已经集成Bugly的用户需要注释掉原来Bugly的jcenter库; 已经配置过符号表的Bugly用户保留原有符号表配置; Bugly SDK(2.1.5及以上版本)已经将Java Crash和Native Crash捕获功能分开,如果想使用NDK库,需要配置: compile 'com.tencent.bugly:nativecrashreport:latest.release'
在BaseApplication初始化sdk 自定义升级弹框
private void initUpgradeDialog() {
/**
* 自定义初始化开关
*/
Beta.autoInit = true;
/**
* true表示初始化时自动检查升级; false表示不会自动检查升级,需要手动调用Beta.checkUpgrade()方法;
*/
Beta.autoCheckUpgrade = true;
/**
* 设置升级检查周期为60s(默认检查周期为0s),60s内SDK不重复向后台请求策略);
*/
// Beta.upgradeCheckPeriod = 60 * 1000;
/**
* 设置启动延时为1s(默认延时3s),APP启动1s后初始化SDK,避免影响APP启动速度;
*/
Beta.initDelay = 1 * 1000;
/**
* 设置通知栏大图标,largeIconId为项目中的图片资源;
*/
Beta.largeIconId = R.mipmap.ic_launcher;
/**
* 设置状态栏小图标,smallIconId为项目中的图片资源Id;
*/
Beta.smallIconId = R.mipmap.ic_launcher;
/**
* 设置更新弹窗默认展示的banner,defaultBannerId为项目中的图片资源Id;
* 当后台配置的banner拉取失败时显示此banner,默认不设置则展示“loading“;
*/
Beta.defaultBannerId = R.mipmap.ic_launcher;
/**
* 设置sd卡的Download为更新资源保存目录;
* 后续更新资源会保存在此目录,需要在manifest中添加WRITE_EXTERNAL_STORAGE权限;
*/
Beta.storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
/**
* 已经确认过的弹窗在APP下次启动自动检查更新时会再次显示;
*/
Beta.showInterruptedStrategy = true;
/**
* 只允许在MainActivity上显示更新弹窗,其他activity上不显示弹窗; 不设置会默认所有activity都可以显示弹窗;
*/
Beta.canShowUpgradeActs.add(MainActivity.class);
/**
* 设置Wifi下自动下载
*/
Beta.autoDownloadOnWifi = true;
/*在application中初始化时设置监听,监听策略的收取*/
Beta.upgradeListener = new UpgradeListener() {
@Override
public void onUpgrade(int ret, UpgradeInfo strategy, boolean isManual, boolean isSilence) {
if (strategy != null) {
Intent i = new Intent();
i.setClass(getApplicationContext(), UpgradeActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else {
Toast.makeText(getApplicationContext(), "没有更新", Toast.LENGTH_SHORT).show();
}
}
};
/* 设置更新状态回调接口 */
Beta.upgradeStateListener = new UpgradeStateListener() {
@Override
public void onUpgradeSuccess(boolean isManual) {
Toast.makeText(getApplicationContext(), "UPGRADE_SUCCESS", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgradeFailed(boolean isManual) {
Toast.makeText(getApplicationContext(), "UPGRADE_FAILED", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrading(boolean isManual) {
Toast.makeText(getApplicationContext(), "UPGRADE_CHECKING", Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadCompleted(boolean b) {
Toast.makeText(getApplicationContext(), "onDownloadCompleted", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgradeNoVersion(boolean isManual) {
Toast.makeText(getApplicationContext(), "UPGRADE_NO_VERSION", Toast.LENGTH_SHORT).show();
}
};
Bugly.init(getApplicationContext(), "c45d2fc4ba", true);
}
发布新版本
进入内测分发页面选择注册的APP,点击发布新版本,上传要升级的APP的版本(上传APP的versioncode必须不低于外发版本的versiocode,否则用户检测不到更新)
因为没有用SDK自己的升级弹框,所以自己自定义了一个activity 来作为弹框
UpgradeActivity 具体代码参考源码