热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

腾讯bugly热更新开发

bugly支持异常上报,应用升级与热更新;异常上报与应用升级使用较为简单,也没有什么难点。下面看一下热更新,官网的文档说的

bugly 支持异常上报,应用升级与热更新;异常上报与应用升级使用较为简单,也没有什么难点。

下面看一下热更新,官网的文档说的虽然非常明白,但是罗里吧嗦,看的让人头大。

下面给出一个特别简单的集成与使用方式。

 

打开下面 bugly 给出的 GitHub 示例,下面是链接:

https://github.com/BuglyDevTeam/Bugly-Android-Demo

 

下载完毕,会看到有两个 demo ,如下图所示:

 

可以看到里面有两个:官网推荐 BuglyHotfixDemo;一键接入 BuglyHotfixEasyDemo ;

我们直接打开第二个,也就是 BuglyHotfixEasyDemo ,这个 demo 是热更新一键接入示例,后续也不再更新这个;    

热更新sdk版本至1.3.6, tinker-support版本至1.1.5,对应tinker版本 1.9.9;

虽然不再更新这个,但是作为普通的用户,目前使用这个是完全够用的。

如果你想使用第一个 demo ,也建议先看第二个,因为这个非常简单,看完这个再看第一个会感觉并不复杂。

 

在接入热更新之前,我们要去申请 appid 过程很简单,打开官网登录 qq 账号申请即可,就不说了,下面是官网地址:

https://bugly.qq.com/

 

下面就看一下如何接入,我并不是按照官网来的,因为官网过于复杂;如果第一次使用建议新建一个 demo ,作为测试使用;

首先在项目的 build.gradle 中添加下面代码:

classpath 'com.tencent.bugly:tinker-support:1.1.5'

如下图:

 

 

在 app 下的 build.gradle 中添加:


// 依赖插件脚本,添加在最上面
apply from: 'tinker-support.gradle'

// 远程依赖集成方式(推荐)compile "com.tencent.bugly:crashreport_upgrade:1.3.6"// 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)compile 'com.tencent.tinker:tinker-android-lib:1.9.9'

如下图所示:

 

 

新建 tinker-support.gradle 与 app 的 build.gradle 同级,代码如下:

apply plugin: 'com.tencent.bugly.tinker-support'def bakPath = file("${buildDir}/bakApk/")/*** 此处填写每次构建生成的基准包目录*/
def baseApkDir = "app-1119-14-54-04"/*** 对于插件各参数的详细解析请参考*/
tinkerSupport {// 开启tinker-support插件,默认值trueenable = true// 自动生成tinkerId, 你无须关注tinkerId,默认为falseautoGenerateTinkerId = true// 指定归档目录,默认值当前module的子目录tinkerautoBackupApkDir = "${bakPath}"// 是否启用覆盖tinkerPatch配置功能,默认值false// 开启后tinkerPatch配置不生效,即无需添加tinkerPatchoverrideTinkerPatchConfiguration = true//测试baseApk = "${bakPath}/${baseApkDir}/app-debug.apk"baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt"baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-debug-R.txt"//正式
// baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"// 构建基准包跟补丁包都要修改tinkerId,主要用于区分
// tinkerId = "1.0.3-ccc"// 打多渠道补丁时指定目录buildAllFlavorsDir = "${bakPath}/${baseApkDir}"// 是否使用加固模式,默认为false// isProtectedApp = true// 是否采用反射Application的方式集成,无须改造ApplicationenableProxyApplication = true// 支持新增ActivitysupportHotplugComponent = true}/*** 一般来说,我们无需对下面的参数做任何的修改* 对于各参数的详细介绍请参考:* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97*/
tinkerPatch {tinkerEnable = trueignoreWarning = falseuseSign = falsedex {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"}
}

如下图,作为参考:

在 tinkerSupport { } 里面有很多参数,请不要修改,还有需要看一下里面每个参数的意义;

这里说明几个比较重要的参数:

// 自动生成tinkerId, 你无须关注tinkerId,默认为falseautoGenerateTinkerId = true

参数 autoGenerateTinkerId = ture 自动生成 tinkerId,无需手动填写,方便了很多,也是和官网推荐 BuglyHotfixDemo 的一个区别;

添加这个参数也无需指定 tinkerId = "1.0.3-ccc" 这个参数;

正式和测试切换:

//测试baseApk = "${bakPath}/${baseApkDir}/app-debug.apk"baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt"baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-debug-R.txt"//正式
// baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"

测试使用 debug ,正式使用 release;

参数 buildAllFlavorsDir,配置多渠道打包请打开,不需要请注释,最下面要配置多渠道打包,所有我就打开了;

// 打多渠道补丁时指定目录buildAllFlavorsDir = "${bakPath}/${baseApkDir}"

参数 isProtectedApp = true;测试千万不要开启,会引发不必要的 bug ,当应用需要加固时再开启;

// 是否使用加固模式,默认为false// isProtectedApp = true

参数 enableProxyApplication = true,无需改造 Application;

// 是否采用反射Application的方式集成,无须改造ApplicationenableProxyApplication = true

 

 

新建 MyApplication 加入下面代码:

public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();setStrictMode();// 设置是否开启热更新能力,默认为trueBeta.enableHotfix = true;// 设置是否自动下载补丁Beta.canAutoDownloadPatch = true;// 设置是否提示用户重启Beta.canNotifyUserRestart = false;// 设置是否自动合成补丁Beta.canAutoPatch = true;/*** 补丁回调接口,可以监听补丁接收、下载、合成的回调*/Beta.betaPatchListener = new BetaPatchListener() {@Overridepublic void onPatchReceived(String patchFileUrl) {//补丁包下载地址为patchFileUrl}@Overridepublic void onDownloadReceived(long savedLength, long totalLength) {//热修复回调成功}@Overridepublic void onDownloadSuccess(String patchFilePath) {//热修复下载成功}@Overridepublic void onDownloadFailure(String msg) {//热修复下载失败}@Overridepublic void onApplySuccess(String msg) {//补丁包应用成功}@Overridepublic void onApplyFailure(String msg) {//补丁包应用失败}@Overridepublic void onPatchRollback() {//补丁回滚}};long start = System.currentTimeMillis();Bugly.setUserId(this, "falue");Bugly.setUserTag(this, 123456);Bugly.putUserData(this, "key1", "123");Bugly.setAppChannel(this, "bugly");// 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId,调试时将第三个参数设置为trueBugly.init(this, "4bf2a8d8eb", true);long end = System.currentTimeMillis();Log.e("init time--->", end - start + "ms");
}@Overrideprotected void attachBaseContext(Context base) {super.attachBaseContext(base);// 热更新必须添加MultiDex.install(base);// 安装tinkerBeta.installTinker();}@TargetApi(9)protected void setStrictMode() {StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());}
}

别忘记在 AndroidManifest.xml 中使用:

需要注意的是,下面的代码中要换成你申请的 appId:

// 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId,调试时将第三个参数设置为trueBugly.init(this, "4bf2a8d8eb", true);

 

 

AndroidManifest.xml 文件中添加下面代码:

参考下图:

 

 

加入权限:

 

 

在 xml 中的 provider_paths 加入代码,没有请创建:


参考下图:

 

 

 

MainActivity 中加入代码:

public class MainActivity extends AppCompatActivity {private Button button; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "这是存在bug的", Toast.LENGTH_SHORT).show();}});}
}

里面只有一个 button ;

 

 

最后加入混淆:

# Bugly混淆规则
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# tinker
-dontwarn com.tencent.tinker.**
-keep class com.tencent.tinker.** { *; }

参考下图:

 

 

多渠道打包配置,暂时配置三个:

productFlavors {huawei {// applicationId "com.tencent.bugly.hotfix.huawei"manifestPlaceholders = [CHANNEL_VALUE: "huawei"]}qihu360 {
// applicationId "com.tencent.bugly.hotfix.qihu360"manifestPlaceholders = [CHANNEL_VALUE: "qihu360"]}oppo {
// applicationId "com.tencent.bugly.hotfix.oppo"manifestPlaceholders = [CHANNEL_VALUE: "oppo"]}}

 

 

作为参考我给出我的 build.gradle 所有代码:

apply plugin: 'com.android.application'// 依赖插件脚本
apply from: 'tinker-support.gradle'android {compileSdkVersion 26buildToolsVersion '26.0.2'defaultConfig {applicationId "com.tencent.bugly.hotfix.easy"minSdkVersion 14targetSdkVersion 26versionCode 3versionName "1.0"flavorDimensions "versionCode"// 开启multidexmultiDexEnabled true}// 签名配置signingConfigs {release {try {storeFile file("./keystore/release.keystore")storePassword "testres"keyAlias "testres"keyPassword "testres"} catch (ex) {throw new InvalidUserDataException(ex.toString())}}debug {storeFile file("./keystore/debug.keystore")}}buildTypes {release {minifyEnabled truesigningConfig signingConfigs.releaseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}debug {debuggable trueminifyEnabled false// signingConfig signingConfigs.debug}}sourceSets {main {jniLibs.srcDirs = ['libs']}}repositories {flatDir {dirs 'libs'}}// productFlavors 示例//flavorDimensions "tier"productFlavors {huawei {// applicationId "com.tencent.bugly.hotfix.huawei"manifestPlaceholders = [CHANNEL_VALUE: "huawei"]}qihu360 {
// applicationId "com.tencent.bugly.hotfix.qihu360"manifestPlaceholders = [CHANNEL_VALUE: "qihu360"]}oppo {
// applicationId "com.tencent.bugly.hotfix.oppo"manifestPlaceholders = [CHANNEL_VALUE: "oppo"]}}lintOptions {checkReleaseBuilds falseabortOnError false}
}dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])compile 'com.android.support:appcompat-v7:26.1.0'// 多dex配置compile "com.android.support:multidex:1.0.2"// 本地集成aar方式// compile(name: 'bugly_crashreport_upgrade-1.3.6', ext: 'aar')// 远程依赖集成方式(推荐)compile "com.tencent.bugly:crashreport_upgrade:1.3.6"// 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)compile 'com.tencent.tinker:tinker-android-lib:1.9.9'}

上面的签名配置是我从 BuglyHotfixEasyDemo 中直接复制过来的;

 

 

所有配置完毕,下面就测试打包,点击右侧 Gradle ==> app ==> Tasks ==> build ==>assembleDebug ,如下图:

打包完毕,在左侧 app ==> bakApk 可以看到躺着三个包,这就是基准包,如下图:

需要注意的是:一般在正式的情况下,需要将 bakApk 文件夹里面的内容保存到本地,方便以后打补丁包使用,如果不存在了,直接复制到 bakApk 文件夹下面就可以了。

记住上面的 app-1126-16-12-58,也就是 bakApk ==> app-1126-16-12-58 ,这个是随机生成的,下面会使用到这个;

 

 

打开 tinker-support.gradle,找到 baseApkDir 参数,将里面的内容替换为 app-1126-16-12-58 ;如下图:

需要注意的是:你生成的是什么就写什么,这个是每打一次基准包,需要填写一次,打补丁包不需要改变;

一定要保证该目录下面有对应的包,这也就是上面为什么让你把基准包保存到本地的原因,以防丢失;

 

 

为了方便测试,将 MainActivity 中的提示改为下面:

Toast.makeText(MainActivity.this, "修复了bug,以便测试", Toast.LENGTH_SHORT).show();

 

点击右侧 Gradle ==> app ==> Tasks ==> tinker-support ==>buildAllFlavorsTinkerPatchDebug ,如下图:

等待过后,补丁包就打完了,在左侧 app ==> outputs ==> patch 中可以看到三个补丁包,如下图:

上面以 7-zip 结尾就是我们的补丁包了,也就是 patch_signed_7zip.apk  ,也就是把这个包放到 bugly 官网就可以了;

 

下面就可以测试了,测试的时候需要注意:一定先将基本包安装到手机上,保证有网络的情况下打开 app ,让热更新代码走完补丁包才可以上传到 bugly 官网,否则上传不上去;

 

下面将基本包放到手机上面运行,因为打了三个包,就拿华为的包测试;

安装完毕,点击按钮可以发现,提示:这是存在bug的;与基本包一致,emmm;

 

打开 bugly 官网,将补丁包上传到官网,点击应用升级==>热更新==>发布新补丁,如下图所示:

 

不要上传错了,我们测试的是华为的基本包,所以补丁包也应该上传华为下面的 patch_signed_7zip.apk ;

上传如果提示,改包不合法,那么刷新页面再试一下,或者重新打开基本包的 app ;因为我也遇到过,是 bugly 后台的问题;

上传完毕,会自动识别版本,选择全量更新,写上备注,然后点击立即下发就可以了,如下图:

 

稍等片刻,就可以出现了,如下图:

我上面有两个,因为我已经测试过一次了,如果你们第一次测试,应该是一个。

 

热更新官网说是重启 app 就可以修复了,经过我测试,大概需要5分钟的时间,补丁才会生效,所以不必着急;

经过几分钟的重启 app ,点击按钮测试,发现提示语变成了:修复了bug,以便测试;

说明补丁包应用成功了,打开 bugly 官网,刷新页面,可以看到已经下发了一个了,如下图所示:

 

可以看到激活的数量为0,但我们已经应用成功了,因为有延迟,所以再过大概10分钟就可以看到激活量为1了,所以不用着急;

 

 

看完这个简单集成方式以后,再看 BuglyHotfixDemo 或者官网文档就会感觉简单多了。

如果你有什么问题,可以看下面我写的 demo ,或者留言;

https://github.com/wuqingsen/BuglyDemo

 

到这里就结束了。

 

 

记录一个bug,测试上没问题,但是我在正式上面先发成功,但是激活数量一直为0,如下图所示:

解决方法,在项目的 bulid.gradle 中的配置改为:

classpath "com.tencent.bugly:tinker-support:latest.release"

就好了,我之前用的是:

// classpath 'com.tencent.bugly:tinker-support:1.1.5' //之前配置classpath "com.tencent.bugly:tinker-support:latest.release" //修改后

做一下记录。

 


推荐阅读
  • 本文探讨了Android系统中支持的图像格式及其在不同版本中的兼容性问题,重点涵盖了存储、HTTP传输、相机功能以及SparseArray的应用。文章详细分析了从Android 10 (API 29) 到Android 11 的存储规范变化,并讨论了这些变化对图像处理的影响。此外,还介绍了如何通过系统升级和代码优化来解决版本兼容性问题,以确保应用程序在不同Android版本中稳定运行。 ... [详细]
  • 在尝试为 Unity 编译一个简单的 Java 库时,运行 `ant jar` 命令后遇到了 Java I/O 异常。具体错误信息为“无法启动程序 ${aAPT},错误代码 2”,这通常表示指定的文件或目录不存在。此问题可能是由于环境配置不正确或路径设置有误导致的。建议检查相关路径和环境变量,确保所有依赖项都已正确安装和配置。 ... [详细]
  • 深入解析 Android 中 EditText 的 getLayoutParams 方法及其代码应用实例 ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • 在探讨Hibernate框架的高级特性时,缓存机制和懒加载策略是提升数据操作效率的关键要素。缓存策略能够显著减少数据库访问次数,从而提高应用性能,特别是在处理频繁访问的数据时。Hibernate提供了多层次的缓存支持,包括一级缓存和二级缓存,以满足不同场景下的需求。懒加载策略则通过按需加载关联对象,进一步优化了资源利用和响应时间。本文将深入分析这些机制的实现原理及其最佳实践。 ... [详细]
  • 基于Dubbo与Zipkin的微服务调用链路监控解决方案
    本文提出了一种基于Dubbo与Zipkin的微服务调用链路监控解决方案。通过抽象配置层,支持HTTP和Kafka两种数据上报方式,实现了灵活且高效的调用链路追踪。该方案不仅提升了系统的可维护性和扩展性,还为故障排查提供了强大的支持。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • Docker入门指南:初探容器化技术
    Docker入门指南:初探容器化技术摘要:Docker 是一个使用 Go 语言开发的开源容器平台,旨在实现应用程序的构建、分发和运行的标准化。通过将应用及其依赖打包成轻量级的容器,Docker 能够确保应用在任何环境中都能一致地运行,从而提高开发和部署的效率。本文将详细介绍 Docker 的基本概念、核心功能以及如何快速上手使用这一强大的容器化工具。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • 探索聚类分析中的K-Means与DBSCAN算法及其应用
    聚类分析是一种用于解决样本或特征分类问题的统计分析方法,也是数据挖掘领域的重要算法之一。本文主要探讨了K-Means和DBSCAN两种聚类算法的原理及其应用场景。K-Means算法通过迭代优化簇中心来实现数据点的划分,适用于球形分布的数据集;而DBSCAN算法则基于密度进行聚类,能够有效识别任意形状的簇,并且对噪声数据具有较好的鲁棒性。通过对这两种算法的对比分析,本文旨在为实际应用中选择合适的聚类方法提供参考。 ... [详细]
  • 在CentOS 7上部署WebRTC网关Janus
    在CentOS 7上部署WebRTC网关Janus ... [详细]
  • Eclipse JFace Text框架中IDocument接口的getNumberOfLines方法详解与编程实例 ... [详细]
author-avatar
陈凯105_462
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有