当前位置: 移动技术网 > 科技>人工智能>机器学习 > Android集成Bugly热修复

Android集成Bugly热修复

2020年09月21日  | 移动技术网科技  | 我要评论
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考一、pandas是什么?示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数..

目录

前言

一、配置

1.添加插件依赖

2.集成SDK

3.初始化SDK

4.AndroidManifest.xml配置

5.混淆配置

二.使用

1.编译基准包

2.根据基准包生成补丁包

3.上传补丁包

四.多渠道打包

五.一点注意



前言

记录一下Bugly 热修复集成步骤,以及使用注意事项。Bugly目前采用微信Tinker方案。


一、配置

1.添加插件依赖

工程目录下 build.gradle

buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        // tinkersupport插件(1.0.3以上无须再配置tinker插件)
        classpath "com.tencent.bugly:tinker-support:1.2.0"
    }
}

2.集成SDK

app module下 build.gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.1"

    // recommend
    dexOptions {
        jumboMode = true
    }
    // 签名配置
    signingConfigs {
        release {
            try {
                storeFile file("./keystore/xxxx.jks")
                storePassword "xxxx"
                keyAlias "xxxx"
                keyPassword "xxxx"
            } catch (ex) {
                throw new InvalidUserDataException(ex.toString())
            }
        }

        debug {
            try {
                storeFile file("./keystore/xxxx.jks")
                storePassword "xxxx"
                keyAlias "xxxx"
                keyPassword "xxxx"
            } catch (ex) {
                throw new InvalidUserDataException(ex.toString())
            }
        }
    }
    defaultConfig {
        applicationId "com.xxxx.tinker"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0.1"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"  
        // 开启multidex
        multiDexEnabled true
        ndk {
            // 设置支持的SO库架构
            abiFilters 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'//,'armeabi'
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'

    
    implementation 'androidx.multidex:multidex:2.0.0'// 多dex配置
    implementation 'com.tencent.bugly:crashreport_upgrade:latest.release'
    //1. 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)
    implementation 'com.tencent.tinker:tinker-android-lib:1.9.14.3'
    implementation 'com.tencent.bugly:nativecrashreport:latest.release'
}


注意的地方:签名配置和多dex配置;com.tencent.tinker:tinker-android-lib:1.9.14.3 版本最好与 BuglyHotfixDemo 中保持一致。

在 app module下 build.gradle中添加

// 依赖插件脚本
apply from: 'tinker-support.gradle'

创建tinker-support.gradle文件

参考BuglyHotfixDemo 的配置

apply plugin: 'com.tencent.bugly.tinker-support'

def bakPath = file("${buildDir}/bakApk/")

/**
 * 此处填写每次构建生成的基准包目录 就是用于生成Patch 时才用到的有问题的基准包
 */
def baseApkDir = "app-0919-17-36-46"

/**
 * 对于插件各参数的详细解析请参考,如果没有特殊需求下面的参数都可以不用更改;如果apk需要加固等可以参考具体描述设置参数
 */
tinkerSupport {

    // 开启tinker-support插件,默认值true
    enable = true
    // 指定归档目录,默认值当前module的子目录tinker
    autoBackupApkDir = "${bakPath}"
    //建议设置true,用户就不用再自己管理tinkerId的命名,插件会为每一次构建的base包自动生成唯一的tinkerId,默认命名规则是versionname.versioncode_时间戳
    //具体参考https://github.com/BuglyDevTeam/Bugly-Android-Demo/wiki/Tinker-ID%E8%AF%A5%E6%80%8E%E4%B9%88%E8%AE%BE%E7%BD%AE
    autoGenerateTinkerId = true
    //tinkerId必须保证唯一性,如果两个base包的tinkerid是一样的,并且都联网激活了,那么后续补丁上传到后台的时候会出现匹配错误
    tinkerId = ""

    // 是否启用覆盖tinkerPatch配置功能,默认值false
    // 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
    //当overrideTinkerPatchConfiguration=true时,tinkerPatch可以省略不写,Bugly会加载默认的Tinker配置,但请注意,
    // 如果你的so文件不是存放在libs目录下(与src目录同级),又或者资源文件的存放在你自定义的目录中,
    // 那么这时候你要小心了,这些文件在制作补丁时不会被检测,
    // 也就是说这些so文件和资源文件将不会被热修复,这种情况下就需要将
    //overrideTinkerPatchConfiguration=false,并设置tinkerPatch的lib和res属性。
    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"

    //构建多渠道补丁时使用
    //    buildAllFlavorsDir = "${bakPath}/${baseApkDir}"

    // 是否开启加固模式,默认为false
    isProtectedApp = true

    enableProxyApplication = true

    supportHotplugComponent = true

    ignoreWarning = true

}

/**
 * 一般来说,我们无需对下面的参数做任何的修改
 * 对于各参数的详细介绍请参考:
 * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
 */
tinkerPatch {
    //oldApk ="${bakPath}/${appName}/app-debug.apk"
    ignoreWarning = false
    useSign = true
    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 = "1.0.1-patch"
        //applyMapping = "${bakPath}/${appName}/app-debug-mapping.txt" //  可选,设置mapping文件,建议保持旧apk的proguard混淆方式
        //applyResourceMapping = "${bakPath}/${appName}/app-debug-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
    }
}

3.初始化SDK

有两种初始化方式,结合项目实际场景选择,这里采用enableProxyApplication = true 的情况,在tinker-support.gradle中进行修改。需要接入SDK 1.2.2版本 和 插件版本 1.0.3以上。

MyApplication中appId替换成你的在Bugly平台申请的appId

public class MyApplication extends Application {

    private static final String TAG ="MyApplication" ;

    @Override
    public void onCreate() {
        super.onCreate();
        // 设置是否开启热更新能力,默认为true
        Beta.enableHotfix = true;
        // 设置是否自动下载补丁,默认为true
        Beta.canAutoDownloadPatch = true;
        // 设置是否自动合成补丁,默认为true
        Beta.canAutoPatch = true;
        // 设置是否提示用户重启,默认为false
        Beta.canNotifyUserRestart = true;
        // 补丁回调接口
        Beta.betaPatchListener = new BetaPatchListener() {
            @Override
            public void onPatchReceived(String patchFile) {
                Log.d(TAG,"补丁下载地址" + patchFile);
//                Toast.makeText(getApplication(), "补丁下载地址" + patchFile, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDownloadReceived(long savedLength, long totalLength) {
                Log.d(TAG,String.format(Locale.getDefault(), "%s %d%%",
                        Beta.strNotificationDownloading,
                        (int) (totalLength == 0 ? 0 : savedLength * 100 / 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 msg) {
                Log.d(TAG,"补丁下载成功");

//                Toast.makeText(getApplication(), "补丁下载成功", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDownloadFailure(String msg) {
                Log.d(TAG,"补丁下载失败");
//                Toast.makeText(getApplication(), "补丁下载失败", Toast.LENGTH_SHORT).show();

            }

            @Override
            public void onApplySuccess(String msg) {
                Log.d(TAG,"补丁应用成功");
//                Toast.makeText(getApplication(), "补丁应用成功", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onApplyFailure(String msg) {
                Log.d(TAG,"补丁应用失败");
//                Toast.makeText(getApplication(), "补丁应用失败", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPatchRollback() {

            }
        };
        //设置开发设备,默认false。可用于调试,后台下发补丁时会有选择
        // Bugly.setIsDevelopmentDevice(getApplicationContext(), true);//开发设备
        // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
        // 调试时,将第三个参数改为true
        Bugly.init(this, "xxxxx", true);

    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base);
        // 安装tinker
        Beta.installTinker();
    }

}

4.AndroidManifest.xml配置

注:1.3.1及以上版本,可以不用配置

5.混淆配置

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

# 避免影响升级功能,需要keep住support包的类
-keep class android.support.**{*;}

二.使用

可以先了解下bugly上的接入流程

  • 打基准包安装并上报联网(注:填写唯一的tinkerId),基准包需要在有网下打开一次,后面上传补丁包才能匹配上
  • 对基准包的bug修复(可以是Java代码变更,资源的变更)
  • 修改基准包路径、修改补丁包tinkerId、mapping文件路径(如果开启了混淆需要配置)、resId文件路径
  • 执行buildTinkerPatchRelease打Release版本补丁包
  • 选择app/build/outputs/patch目录下的补丁包并上传(注:不要选择tinkerPatch目录下的补丁包,不然上传会有问题
  • 编辑下发补丁规则,点击立即下发
  • 杀死进程并重启基准包,请求补丁策略(SDK会自动下载补丁并合成)
  • 再次重启基准包,检验补丁应用结果
  • 查看页面,查看激活数据的变化

1.编译基准包

需要对tinkerId进行修改,在 tinker-support.gradle 中tinkerId="1.0.1.1-base",可以根据versionNme,versionCode,时间戳等生成,需要保证唯一。

建议使用插件替我们自动生成,配置 autoGenerateTinkerId = true (手动修改的tinkerId 就没用了)。这样就不必太关注于怎样命名了,规则是versionname.versioncode_时间戳 ,将编译好的apk 拖入AS 中分析可以查看

正常编译release包,就会在app/build/bakApk 下生成基准包,注意:正式发版生成的基准包要保留保留!!保留!!!用于以后生成补丁包。

2.根据基准包生成补丁包

进行bug 修复后,同样需要对 tinker-support.gradle 文件中一些配置做修改。

如果配置了 autoGenerateTinkerId = true 就不用去管 tinkerId 了。不然仍需要修改tinkerId,例如tinkerId="1.0.1.1-patch",注意与打基准包时的tinkerId不一样。

执行task buildTinkerPatchRelease 生成补丁包 

补丁包生成路径build/outputs/patch

 

3.上传补丁包

在bugly --》 应用升级 --》热更新 发布新补丁,将patch_signed_7zip.apk 进行上传

开发设备选项,对应MyApplication 中设置了Bugly.setIsDevelopmentDevice(getApplicationContext(), true);的设备

 


四.多渠道打包

Bugly多渠道热更新解决方案

productFlavors 方式需要为所有渠道生成补丁包,因为这种打包方式会修改buildConfig类中的FLAVOR字段,导致生成的不同渠道包的dex是不一样的,无法实现一个补丁包覆盖所有渠道。

Walle(瓦力):Android Signature V2 Scheme签名下的新一代渠道包打包神器:

https://github.com/Meituan-Dianping/walle

Walle通过修改APK Signature Block来添加自定义的渠道信息来生成渠道包,不会改变dex结构。

实际项目中使用Walle正常打多渠道包就行,基于基准包生成的补丁包也只需要一个,就可以实现多渠道覆盖。


五.一点注意

在开发阶段可以把插件脚本  //apply from: 'tinker-support.gradle' 注释,避免每次编译都会在build/bakApk下生成很多基准包文件

遇到这个错误:

在gradle.properties 中加入

android.enableR8.libraries = false  
android.enableR8 = false 

 

本文地址:https://blog.csdn.net/Woolle/article/details/108704541

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网