Bugly更新 与热更新
程序员文章站
2024-01-22 11:15:34
...
Bugly更新与热更新
App build.gradle
// 依赖插件脚本
apply from: 'tinker-support.gradle'
android{
defaultConfig{
versionCode 1
versionName "1.0"
// 开启multidex
multiDexEnabled true
}
// 签名配置
signingConfigs {
release {
try {
storeFile file("./keystore/buglytest.jks")
storePassword "123456"
keyAlias "bugly测试升级"
keyPassword "123456"
} catch (ex) {
throw new InvalidUserDataException(ex.toString())
}
}
debug {
storeFile file("./keystore/buglytest.jks")
}
}
buildTypes {
release {
minifyEnabled true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
// signingConfig signingConfigs.debug
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
repositories {
flatDir {
dirs 'libs'
}
}
// productFlavors 示例
/*flavorDimensions "tier"
productFlavors {
xiaomi {
dimension "tier"
}
yyb {
dimension "tier"
}
wdj {
dimension "tier"
}
}*/
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
// 多dex配置
implementation "com.android.support:multidex:1.0.2"
// 远程依赖集成方式(推荐)
implementation "com.tencent.bugly:crashreport_upgrade:1.3.6"
// 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)
implementation 'com.tencent.tinker:tinker-android-lib:1.9.9'
项目gradle 下添加依赖
dependencies{
classpath 'com.tencent.bugly:tinker-support:1.1.5'
}
项目下新建一个tinker- support.gradle
baseApkDir: 是目录名:apk打包目录名,用于热更新修复
apply plugin: 'com.tencent.bugly.tinker-support'
def bakPath = file("${buildDir}/bakApk/")
/**
* 此处填写每次构建生成的基准包目录
*/
def baseApkDir = "app-0603-10-05-19"
/**
* 对于插件各参数的详细解析请参考
*/
tinkerSupport {
// 开启tinker-support插件,默认值true
enable = true
// 指定归档目录,默认值当前module的子目录tinker
autoBackupApkDir = "${bakPath}"
// 是否启用覆盖tinkerPatch配置功能,默认值false
// 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
overrideTinkerPatchConfiguration = true
// 编译补丁包时,必需指定基线版本的apk,默认值为空
// 如果为空,则表示不是进行补丁包的编译
// @{link tinkerPatch.oldApk }
baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// 对应tinker插件applyMapping
baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// 对应tinker插件applyResourceMapping
baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
// 构建基准包和补丁包都要指定不同的tinkerId,并且必须保证唯一性
tinkerId = "patch-1.0.1"
// 构建多渠道补丁时使用
// buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
// 是否启用加固模式,默认为false.(tinker-spport 1.0.7起支持)
isProtectedApp = true
// 是否开启反射Application模式
enableProxyApplication = true
// 是否支持新增非export的Activity(注意:设置为true才能修改AndroidManifest文件)
supportHotplugComponent = true
}
/**
* 一般来说,我们无需对下面的参数做任何的修改
* 对于各参数的详细介绍请参考:
* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
tinkerEnable = true
ignoreWarning = false
useSign = false
dex {
dexMode = "jar"
pattern = ["classes*.dex"]
loader = []
}
lib {
pattern = ["lib/*/*.so"]
}
res {
pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
ignoreChange = []
largeModSize = 100
}
packageConfig {
}
sevenZip {
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
// path = "/usr/local/bin/7za"
}
buildConfig {
keepDexApply = false
// tinkerId = "base-2.0.1"
}
}
2;新建一个application
public class SampleApplication extends TinkerApplication {
public SampleApplication() {
super(ShareConstants.TINKER_ENABLE_ALL, "com.centuryepic.wudi_buglyup.SampleApplicationLike",
"com.tencent.tinker.loader.TinkerLoader", false);
}
}
SampleApplicationLike 是Application 的扩展
public class SampleApplicationLike extends DefaultApplicationLike {
public static final String TAG = "Tinker.SampleApplicationLike";
public static final String APP_ID ="70521ca927";
public static final String APP_CHANNEL = "自己测试"; // TODO 自定义渠道
public SampleApplicationLike(Application application, int tinkerFlags,
boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onCreate() {
super.onCreate();
// 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
// 调试时,将第三个参数改为true
// Bugly.init(getApplication(), "70521ca927", false);
/***** Beta高级设置 *****/
/**
* true表示app启动自动初始化升级模块; false不会自动初始化;
* 开发者如果担心sdk初始化影响app启动速度,可以设置为false,
* 在后面某个时刻手动调用Beta.init(getApplicationContext(),false);
*/
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);
/***** Bugly高级设置 *****/
BuglyStrategy strategy = new BuglyStrategy();
/**
* 设置app渠道号
*/
strategy.setAppChannel(APP_CHANNEL);
/***** 统一初始化Bugly产品,包含Beta *****/
Bugly.init(getApplication(), APP_ID, true, strategy);
setStrictMode();
// 设置是否开启热更新能力,默认为true
Beta.enableHotfix = true;
// 设置是否自动下载补丁
Beta.canAutoDownloadPatch = true;
// 设置是否提示用户重启
Beta.canNotifyUserRestart = true;
// 设置是否自动合成补丁
Beta.canAutoPatch = true;
/**
* 全量升级状态回调
*/
Beta.upgradeStateListener = new UpgradeStateListener() {
@Override
public void onUpgradeFailed(boolean b) {
}
@Override
public void onUpgradeSuccess(boolean b) {
}
@Override
public void onUpgradeNoVersion(boolean b) {
Toast.makeText(getApplication(), "最新版本", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrading(boolean b) {
Toast.makeText(getApplication(), "onUpgrading", Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadCompleted(boolean b) {
}
};
/**
* 补丁回调接口,可以监听补丁接收、下载、合成的回调
*/
Beta.betaPatchListener = new BetaPatchListener() {
@Override
public void onPatchReceived(String patchFileUrl) {
Toast.makeText(getApplication(), patchFileUrl, Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadReceived(long savedLength, long totalLength) {
Toast.makeText(getApplication(), String.format(Locale.getDefault(),
"%s %d%%",
Beta.strNotificationDownloading,
(int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)), Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadSuccess(String patchFilePath) {
Toast.makeText(getApplication(), patchFilePath, Toast.LENGTH_SHORT).show();
Beta.applyDownloadedPatch();
}
@Override
public void onDownloadFailure(String msg) {
Toast.makeText(getApplication(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onApplySuccess(String msg) {
Toast.makeText(getApplication(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onApplyFailure(String msg) {
Toast.makeText(getApplication(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onPatchRollback() {
Toast.makeText(getApplication(), "onPatchRollback", Toast.LENGTH_SHORT).show();
}
};
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
// you must install multiDex whatever tinker is installed!
MultiDex.install(base);
// 安装tinker
Beta.installTinker(this);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
getApplication().registerActivityLifecycleCallbacks(callbacks);
}
@TargetApi(9)
protected void setStrictMode() {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
}
}
MainActivity中:
/***** 检查更新 *****/
Beta.checkUpgrade();
/*********升级信息***********/
private void loadUpgradeInfo() {
if (upgradeInfoTv == null)
return;
/***** 获取升级信息 *****/
UpgradeInfo upgradeInfo = Beta.getUpgradeInfo();
if (upgradeInfo == null) {
upgradeInfoTv.setText("无升级信息");
return;
}
StringBuilder info = new StringBuilder();
info.append("id: ").append(upgradeInfo.id).append("\n");
info.append("标题: ").append(upgradeInfo.title).append("\n");
info.append("升级说明: ").append(upgradeInfo.newFeature).append("\n");
info.append("versionCode: ").append(upgradeInfo.versionCode).append("\n");
info.append("versionName: ").append(upgradeInfo.versionName).append("\n");
info.append("发布时间: ").append(upgradeInfo.publishTime).append("\n");
info.append("安装包Md5: ").append(upgradeInfo.apkMd5).append("\n");
info.append("安装包下载地址: ").append(upgradeInfo.apkUrl).append("\n");
info.append("安装包大小: ").append(upgradeInfo.fileSize).append("\n");
info.append("弹窗间隔(ms): ").append(upgradeInfo.popInterval).append("\n");
info.append("弹窗次数: ").append(upgradeInfo.popTimes).append("\n");
info.append("发布类型(0:测试 1:正式): ").append(upgradeInfo.publishType).append("\n");
info.append("弹窗类型(1:建议 2:强制 3:手工): ").append(upgradeInfo.upgradeType);
upgradeInfoTv.setText(info);
}
点击app.build 下assembleReleasae 下生成文件:
生成apk 在backApk目录下.对应的mapping.txt 和 R.txt文件
然后: 将tinker-support-build 下 base-1.0.1 更改为patch-1.0.1 ,baseApkDir 目录更改为生成的Apk 目录, 点击tinker-support下buildTinkerPatchRelease 生成的apk 在outputs/patch/release, 将Apk 放到热更新上去,下发后就会发生修复bug.
新的改变
上一篇: Python:手写数字识别