bugly_bugly 热更新 - CSDN
精华内容
参与话题
  • Bugly的使用

    万次阅读 多人点赞 2017-04-15 16:24:14
    Bugly为解决开发者紧急修复线上bug,而无需重新发版让用户无感知就能把问题修复的一项能力。Bugly目前采用微信Tinker的开源方案,开发者只需要集成我们提供的SDK就可以实现自动下载补丁包、合成、并应用补丁的功能,...

    Bugly为解决开发者紧急修复线上bug,而无需重新发版让用户无感知就能把问题修复的一项能力。Bugly目前采用微信Tinker的开源方案,开发者只需要集成我们提供的SDK就可以实现自动下载补丁包、合成、并应用补丁的功能,我们也提供了热更新管理后台让开发者对每个版本补丁进行管理。

    第一步:添加插件依赖
    工程根目录下“build.gradle”文件中添加:

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            // tinkersupport插件, 其中lastest.release指拉取最新版本,也可以指定明确版本号,例如1.0.4
            classpath "com.tencent.bugly:tinker-support:latest.release"
        }
    }

    第二步:集成SDK
    gradle配置

    在app module的“build.gradle”文件中添加(示例配置):

     android {
            defaultConfig {
              ndk {
                //设置支持的SO库架构
                abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
              }
            }
          }
          dependencies {
              compile "com.android.support:multidex:1.0.1" // 多dex配置
              //注释掉原有bugly的仓库
              //compile 'com.tencent.bugly:crashreport:latest.release'//其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.3.2
              compile 'com.tencent.bugly:crashreport_upgrade:latest.release'//其中latest.release指代最新版本号,也可以指定明确的版本号,例如1.2.0
              compile 'com.tencent.bugly:nativecrashreport:latest.release' //其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.2.0
          }

    在app module的“build.gradle”文件中添加:

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

    tinker-support.gradle内容如下所示(示例配置):

    apply plugin: 'com.tencent.bugly.tinker-support'
    
    def bakPath = file("${buildDir}/bakApk/")
    /*在本类中需要修改:
    * 1.baseApkDir
    * 2-4名称的修改
    * 2.baseApk
    * 3.baseApkProguardMapping
    * 4.baseApkResourceMapping
    * 5.tinkerId  编号必须一致
    * */
    /**
     * 此处填写每次构建生成的基准包目录  app/build/bakApk/app-0412-18-01-33
     */
    def baseApkDir = "app-0413-11-40-46"
    
    /**
     * 对于插件各参数的详细解析请参考
     */
    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,并且必须保证唯一性 base  patch
        tinkerId = "base-1.0.3"  //base-1.0.3 错误版本  patch-1.0.3 补丁版本   (1.0.3基准包和补丁包版本要一致)
    
        // 构建多渠道补丁时使用
        // buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
    
        // 是否开启反射Application模式
        enableProxyApplication = false//使用SampleApplication和SampleApplicationLike
        //enableProxyApplication = true//使用MyApplication
    
    }
    
    /**
     * 一般来说,我们无需对下面的参数做任何的修改
     * 对于各参数的详细介绍请参考:
     * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
     */
    tinkerPatch {
        //oldApk ="${bakPath}/${appName}/app-release.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-base"
            //applyMapping = "${bakPath}/${appName}/app-release-mapping.txt" //  可选,设置mapping文件,建议保持旧apk的proguard混淆方式
            //applyResourceMapping = "${bakPath}/${appName}/app-release-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
        }
    }
    

    第三步:初始化SDK
    enableProxyApplication = false 的情况
    这是Tinker推荐的接入方式,一定程度上会增加接入成本,但具有更好的兼容性。

    集成Bugly升级SDK之后,我们需要按照以下方式自定义ApplicationLike来实现Application的代码(以下是示例):

    自定义Application

    public class SampleApplication extends TinkerApplication {
        public SampleApplication() {
            super(ShareConstants.TINKER_ENABLE_ALL, "xxx.xxx.SampleApplicationLike",
                    "com.tencent.tinker.loader.TinkerLoader", false);
        }
    }

    注意:这个类集成TinkerApplication类,这里面不做任何操作,所有Application的代码都会放到ApplicationLike继承类当中
    参数解析
    参数1:tinkerFlags 表示Tinker支持的类型 dex only、library only or all suuport,default: TINKER_ENABLE_ALL
    参数2:delegateClassName Application代理类 这里填写你自定义的ApplicationLike
    参数3:loaderClassName Tinker的加载器,使用默认即可
    参数4:tinkerLoadVerifyFlag 加载dex或者lib是否验证md5,默认为false

    我们需要您将以前的Applicaton配置为继承TinkerApplication的类:
    这里写图片描述

    自定义ApplicationLike

    public class SampleApplicationLike extends DefaultApplicationLike {
    
        public static final String TAG = "Tinker.SampleApplicationLike";
    
        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(), "900029763", false);
        }
    
    
        @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
            // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法
            Beta.installTinker(this);
        }
    
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
            getApplication().registerActivityLifecycleCallbacks(callbacks);
        }
    
    }

    注意:tinker需要你开启MultiDex,你需要在dependencies中进行配置compile “com.android.support:multidex:1.0.1”才可以使用MultiDex.install方法; SampleApplicationLike这个类是Application的代理类,以前所有在Application的实现必须要全部拷贝到这里,在onCreate方法调用SDK的初始化方法,在onBaseContextAttached中调用Beta.installTinker(this);。

    enableProxyApplication = true 的情况

    public class MyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
            // 调试时,将第三个参数改为true  900029763自己申请的ID
            Bugly.init(this, "900029763", false);
        }
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            // you must install multiDex whatever tinker is installed!
            MultiDex.install(base);
    
    
            // 安装tinker
            Beta.installTinker();
        }
    
    }

    第四步:AndroidManifest.xml配置
    1. 权限配置

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

    第五步:混淆配置

    为了避免混淆SDK,在Proguard混淆文件中增加以下配置:

    -dontwarn com.tencent.bugly.**
    -keep public class com.tencent.bugly.**{*;}

    如果你使用了support-v4包,你还需要配置以下混淆规则:

    -keep class android.support.**{*;}

    bugly地址:https://bugly.qq.com/docs/user-guide/instruction-manual-android-hotfix/?v=20170322165254
    Github Demo
    https://github.com/BuglyDevTeam/Bugly-Android-Demo

    普通打包
    1、编译基准包
    配置基准包的tinkerId
    这里写图片描述
    tinkerId最好是一个唯一标识,例如git版本号、versionName等等。 如果你要测试热更新,你需要对基线版本进行联网上报。

    这里强调一下,基线版本配置一个唯一的tinkerId,而这个基线版本能够应用补丁的前提是集成过热更新SDK,并启动上报过联网,这样我们后台会将这个tinkerId对应到一个目标版本,例如tinkerId
    = “bugly_1.0.0” 对应了一个目标版本是1.0.0,基于这个版本打的补丁包就能匹配到目标版本。

    执行assembleRelease编译生成基准包:
    这里写图片描述

    这个会在build/outputs/bakApk路径下生成每次编译的基准包、混淆配置文件、资源Id文件,如下图所示:
    这里写图片描述

    实际应用中,请注意保存线上发布版本的基准apk包、mapping文件、R.txt文件,如果线上版本有bug,就可以借助我们tinker-support插件进行补丁包的生成。

    启动apk,上报联网数据

    我们每次冷启动都会请求补丁策略,会上报当前版本号和tinkerId,这样我们后台就能将这个唯一的tinkerId对应到一个版本,大家测试的时候可以打开logcat查看我们的日志,如下图所示:
    这里写图片描述

    如果看不到log,您需要将bugly初始化的第三个参数设置为true才能看到。
    2、对基线版本的bug修复
    未修复前
    这里写图片描述
    这个类有一个会造成空指针的方法。

    修复后
    这里写图片描述

    对产生bug的类进行修复,作为补丁下次覆盖基线版本的类。

    3、根据基线版本生成补丁包
    修改待修复apk路径、mapping文件路径、resId文件路径
    这里写图片描述

    执行构建补丁包的task

    这里写图片描述
    如果你要生成不同编译环境的补丁包,只需要执行TinkerSupport插件生成的task,比如buildTinkerPatchRelease就能生成release编译环境的补丁包。 注:TinkerSupport插件版本低于1.0.4的,需要使用tinkerPatchRelease来生成补丁包 。

    生成的补丁包在build/outputs/patch目录下:
    这里写图片描述

    大家这里可能会有一个疑问,补丁版本是怎么匹配到目标版本的,可以双击patch包,我们提供的插件会在tinker生成的patch包基础上插入一个MF文件:
    这里写图片描述
    这里写图片描述

    4、上传补丁包到平台
    上传补丁包到平台并下发编辑规则
    这里写图片描述
    这里写图片描述
    这里写图片描述

    点击发布新补丁,上传前面生成的patch包,我们平台会自动为你匹配到目标版本,你可以选择下发范围(开发设备、全量设备、自定义),填写完备注之后,点击立即下发让补丁生效,这样你就可以在客户端当中收到我们的策略,SDK会自动帮你把补丁包下到本地。

    5、测试补丁应用效果
    启动app应用patch
    这里写图片描述
    如果匹配到目标版本,后台就会下发补丁策略,可以在logcat看到如下日志:
    这里写图片描述

    下载成功之后,我们会立即去合成补丁,可以看到patch合成的日志:
    这里写图片描述

    重启app查看效果
    这里写图片描述
    注:我们方案是基于Tinker方案的实现,需要下次启动才能让补丁生效。

    多渠道打包

    tinker是支持我们打多渠道的,建议大家按照以下步骤进行最佳实践:

    1. 配置productFlavors

    android {
        ...
    
        // 多渠道打包(示例配置)
        productFlavors {
            xiaomi {
                applicationId 'com.tencent.bugly.hotfix.xiaomi'
            }
    
            yyb {
                applicationId 'com.tencent.bugly.hotfix.yyb'
            }
        }
    
      ...
    
    }

    2. 执行assembleRelease生成基线apk
    按照普通打包方式正常配置基线版本的tinkerId,然后执行assembleRelease生成不同渠道的apk,会在工程中build/bakApk/生成如下图所示文件:

    这里写图片描述

    3. 打渠道补丁包配置
    这里写图片描述
    4.执行buildAllFlavorsTinkerPatchRelease生成所有渠道补丁包
    如下图所示:
    这里写图片描述

    5.测试应用补丁包
    与普通打包一致。

    加固打包(仅支持tinker 1.7.5及以下)

    tinker的一般模式需要Dex的合成,它并不支持加固,一定要使用加固的app可以使用usePreGeneratedPatchDex模式。由于加固会改变apk的dex结构,所以生成补丁包时我们务必要使用加固前的apk。
    但是需要注意的是,某些加固工具会将非exported的四大组件的类名替换,对于这部分类即使使用usePreGeneratedPatchDex也无法修改。对于360加固,MainActivity由于被提前加载,也无法修复。大家对于加固的情况,请仔细测试,能否支持与加固的方式有关联。

    1.提前生成dex配置
    tinker是支持加固模式的,但需要你回退到Qzone方案 ,将usePreGeneratedPatchDex设置为true。
    这里写图片描述

    是否提前生成dex,而非合成的方式。这套方案即回退成Qzone的方案,对于需要使用加固或者多flavor打包(建议使用其他方式生成渠道包)的用户可使用。但是这套方案需要插桩,会造成Dalvik下性能损耗以及Art补丁包可能过大的问题,务必谨慎使用。另外一方面,这种方案在Android
    N之后可能会产生问题,建议过滤N之后的用户。

    2.将基准包进行加固
    如果你的app需要进行加固,你需要将你打出的基准包上传到具体的加固平台进行加固,例如乐固,加固完成之后需要对apk进行重签名:

    jarsigner -verbose -keystore <YOUR_KEYSTORE> -signedjar <SIGNED_APK> <UNSIGNED_APK> <KEY_ALIAS>
    以上命令说明:
    -verbose:指定生成详细输出
    -keystore:指定证书存储路径
    -signedjar:改选项的三个参数分别为签名后的apk包、未签名的apk包、数字证书别名

    3.根据加固的基准包生成补丁包
    打patch包的操作跟普通打包方式一致。

    demo下载自己测试:http://download.csdn.net/detail/u011531708/9812942

    详解:
    https://bugly.qq.com/docs/user-guide/instruction-manual-android-hotfix-demo/?v=20170322165254

    展开全文
  • 腾讯Bugly详解带你们跳坑

    千次阅读 2018-08-09 16:45:03
    现在才

    第一步、Bugly的接入

     

     

    1. 1、工程根目录下“build.gradle”文件中添加: 

    注意:在高版本的时候一定要指明依赖的版本号 否则找不到TinkerApplication类

     

     

     

     

    android {
    
            ndk {
                // 设置支持的SO库架构
                abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
            }
    
        }
    
    
    dependencies {
        implementation "com.android.support:multidex:1.0.3" // 多dex配置
        implementation 'com.tencent.bugly:crashreport_upgrade:1.3.5'
        implementation 'com.tencent.tinker:tinker-android-lib:1.9.6'
        implementation 'com.tencent.bugly:nativecrashreport:3.3.1'
    }

     

    2、在app module的“build.gradle”文件中添加:

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

    3、配置 tinker-support.gradle

    apply plugin: 'com.tencent.bugly.tinker-support'
    
    def bakPath = file("${buildDir}/bakApk/")
    /*在本类中需要修改:
    * 1.baseApkDir 
    * 2-4名称的修改
    * 2.baseApk
    * 3.baseApkProguardMapping
    * 4.baseApkResourceMapping
    * 5.tinkerId  编号必须一致
    * */
    /**
     * 此处填写每次构建生成的基准包目录  app/build/bakApk/app-0412-18-01-33
     */
    def baseApkDir = "app-0809-14-53-23"
    
    /**
     * 对于插件各参数的详细解析请参考
     */
    tinkerSupport {
    
        // 开启tinker-support插件,默认值true
         enable = true
        // tinkerEnable功能开关  官方资料中没有要要加上
        tinkerEnable = true
        // 指定归档目录,默认值当前module的子目录tinker
        autoBackupApkDir = "${bakPath}"
    
        // 是否启用覆盖tinkerPatch配置功能,默认值false
        // 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
        overrideTinkerPatchConfiguration = true
    
        // 编译补丁包时,必需指定基线版本的apk :baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
        // 基准包,则表示不是进行补丁包的编译   : baseApk = "${bakPath}/${baseApkDir}/"
        baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
    
        // 混淆会生成该文件 基准包  baseApkProguardMapping = "${bakPath}/${baseApkDir}/"
                       // 补丁包   baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
        
        baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
    
        // 对应tinker插件applyResourceMapping   
        baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
    
        // 构建基准包和补丁包都要指定不同的tinkerId,并且必须保证唯一性 base  patch
        tinkerId = "1.0.3-patch"  //base-1.0.3 错误版本  patch-1.0.3 补丁版本   (1.0.3基准包和补丁包版本要一致)
    
        // 构建多渠道补丁时使用
        // buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
    
        // 是否开启反射Application模式
        enableProxyApplication = false//使用SampleApplication和SampleApplicationLike
        //enableProxyApplication = true//使用MyApplication
    
    }
    
    /**
     * 一般来说,我们无需对下面的参数做任何的修改
     * 对于各参数的详细介绍请参考:
     * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
     */
    tinkerPatch {
        //oldApk ="${bakPath}/${appName}/app-release.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-base"
            //applyMapping = "${bakPath}/${appName}/app-release-mapping.txt" //  可选,设置mapping文件,建议保持旧apk的proguard混淆方式
            //applyResourceMapping = "${bakPath}/${appName}/app-release-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
        }
    }

    4、初始化Tinker分为两种情况

         enableProxyApplication = false 的情况  和为true的情况 此处只讲解为false的情况

        自定义Application 继承 TinkerApplication ,并且在清单文件中配置 SampleApplication

     

    
    public class SampleApplication extends TinkerApplication {
        /**
         *  tinkerFlags           tinkerFlags 表示Tinker支持的类型 dex only、library only or all suuport,default: TINKER_ENABLE_ALL
         *  delegateClassName     delegateClassName Application代理类 这里填写你自定义的ApplicationLike
         *  loaderClassName       loaderClassName Tinker的加载器,使用默认即可
         *  tinkerLoadVerifyFlag  tinkerLoadVerifyFlag 加载dex或者lib是否验证md5,默认为false
         */
        public SampleApplication(){
            super(ShareConstants.TINKER_ENABLE_ALL, "com.example.user.myapplication.SampleApplicationLike"
                    ,"com.tencent.tinker.loader.TinkerLoader", false);
        }
    }
    

     

    自当以ApplicationLike 继承DefaultApplicationLike 所有的初始化操作都在这里进行

     

    public class SampleApplicationLike extends DefaultApplicationLike{
    
        public static final String TAG = "Tinker.SampleApplicationLike";
    
        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(),"4945332601",true);
        }
    
    
        @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
            // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法
            Beta.installTinker(this);
        }
    
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
            getApplication().registerActivityLifecycleCallbacks(callbacks);
        }
    
    }

     

    清单文件中配置权限

     

     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_LOGS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

     

    5、配置混淆

     

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

     

     

    一、普通打包

     1、编译基准包

    配置基准包的 tinkerId 和当前app版本一样  例如 tinkerId ="1.0.0-base" 是唯一值不能重复,如果要进行热更新测试,一定要联网上报(就是把基准包在手机上跑一偏,看log日志如果有success  843的字样就说明成功)

    这里强调一下,基线版本配置一个唯一的tinkerId,而这个基线版本能够应用补丁的前提是集成过热更新SDK,并启动上报过联网,这样我们后台会将这个tinkerId对应到一个目标版本,例如tinkerId = "bugly_1.0.0" 对应了一个目标版本是1.0.0,基于这个版本打的补丁包就能匹配到目标版本。

    2、点击边测的gradle下的assembleRelase生成基准包

    这个会在build/outputs/bakApk路径下生成每次编译的基准包、混淆配置文件、资源Id文件,

    3、对基准版本的bug修复

    4、根据基准包生成一个补丁包    点击边测的gradle下 tinker-support \ buildTinkerpathRelase

    要修改tinkerId 为 tinkerId = "1.0.0-path"   生成补丁包后上传一定要山传patch目录下的patch_signed_7zip.apk

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 文章目录一、使用Bugly对移动应用进行崩溃监控二、我们看到的崩溃堆栈1、Java崩溃2、Native崩溃 一、使用Bugly对移动应用进行崩溃监控 Unity项目中接入了腾讯的Bugly,通过Bugly后台,我们可以对移动应用进行异常...

    一、使用Bugly对移动应用进行崩溃监控

    Unity项目中接入了腾讯的Bugly,通过Bugly后台,我们可以对移动应用进行异常监控、崩溃分析等。
    在这里插入图片描述

    Bugly官网: https://bugly.qq.com/v2/index
    腾讯 Bugly,是腾讯公司为移动开发者开放的服务之一,面向移动开发者提供专业的 Crash 监控、崩溃分析等质量跟踪服务。Bugly 能帮助移动互联网开发者更及时地发现掌控异常,更全面的了解定位异常,更高效的修复解决异常。

    二、崩溃类型

    1、Java崩溃

    这种情况我们可以比较完整的看到java的调用堆栈,比较好定位问题。
    在这里插入图片描述

    2、Native崩溃

    这种情况的奔溃,如果没有上传符号表,我们看到的堆栈信息就是这样的
    在这里插入图片描述
    蓝色的部分就是崩溃的地方,没有符号表,我们是看不到具体是哪个文件哪一行异常。

    三、Bugly上传符号表解析崩溃堆栈

    1、关于符号表

    符号定义的本质是:指被分配了存储空间。如果是函数名则指代码所在区;如果是变量名则指其所在的静态数据区。
    所有定义的符号的值就是其目标所在的首地址。
    符号表是内存地址与函数名、文件名、行号的映射表。符号表元素如下所示:
    <起始地址> <结束地址> <函数> [<文件名:行号>]

    2、上传符号表

    根据上面的信息,是在libunity.so中崩溃的,我们需要上传libunity.so的符号表。

    这个libunity.soUnity的引擎库,它的符号表在Unity安装目录中,具体位置如下:
    在这里插入图片描述
    具体哪个,要看具体的平台(比如AndroidiOS)、编译后端(比如il2cppmono)、发布环境(比如DevelopmentRelease)。
    在Mac上,符号表的路径是:
    /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Symbols
    /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Symbols
    在windows上,符号表的路径是:
    C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Symbols\armeabi-v7a\libunity.sym.so
    C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Symbols\armeabi-v7a\libunity.sym.so

    我们将符号表上传到Bugly
    在这里插入图片描述
    在这里插入图片描述

    3、Native崩溃堆栈解析

    上传完符号表,我们就能看到清晰的调用堆栈了,如下
    在这里插入图片描述

    四、通过NDK的addr2line解析崩溃堆栈

    我们也可以自己通过NDKaddr2line工具,配合符号表解析崩溃堆栈。
    首先,找到NDKaddr2line工具,NDK目录中有个toolchains文件夹,里面有各个CPU平台的工具
    在这里插入图片描述
    我们搜索一下addr2line.exe,如下,由于我是Android arm架构的,所以使用arm-linux-androideabi-addr2line.exe
    在这里插入图片描述
    进入arm-linux-androideabi-addr2line.exe所在的目录,将符号表拷贝到当前目录
    在这里插入图片描述
    假设我们要查00e437cc这个地址的堆栈,通过如下命令行

    arm-linux-androideabi-addr2line.exe -f -C -e libunity.sym.so 00e437cc
    

    在这里插入图片描述
    可以看到,输出的堆栈信息为

    __gnu_cxx::__verbose_terminate_handler()
    ??:?
    

    与上面bugly自动解析的结果一致
    在这里插入图片描述

    展开全文
  • bugly框架记录

    千次阅读 2018-09-17 15:42:53
    最开始的时候是为了使用腾讯的bugly框架来抓取app中的crash,后来又看到了腾讯的bugly框架之后续,比如自动更新,热修复等等,这篇文章记录的主要是bugly介入的流程和遇见的坑(本篇文章不包括集成crash时的符号表...

     

    最开始的时候是为了使用腾讯的bugly框架来抓取app中的crash,后来又看到了腾讯的bugly框架之后续,比如自动更新,热修复等等,这篇文章记录的主要是bugly介入的流程和遇见的坑(本篇文章不包括集成crash时的符号表插入和热更的so更新,这些功能会在下篇文章中去更新)

     首先来说一下集成bugly中crash的流程

    https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=20180709165613

    腾讯官方地址,这个是比较简单的,按照这个流程一步一步走下去就可以完全搞定。

    如果自动集成NDK之后出现以下的错误信息

    NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.

    则在项目根目录的gradle.properties文件中添加:

    android.useDeprecatedNdk=true

    注意 :集成Bugly NDK时,需要同时集成Bugly SDK。但是集成SDK的时候不一定要集成NDK

    注:如果您的App需要上传到google play store,您需要将READ_PHONE_STATE权限屏蔽掉或者移除,否则可能会被下架。

    • 请避免混淆Bugly,在Proguard混淆文件中增加以下配置:
    -dontwarn com.tencent.bugly.**
    -keep public class com.tencent.bugly.**{*;}

     

    最简单的初始化

    获取APP ID并将以下代码复制到项目Application类onCreate()中,Bugly会为自动检测环境并完成配置:

    CrashReport.initCrashReport(getApplicationContext(), "注册时申请的APPID", false); 
    

    为了保证运营数据的准确性,建议不要在异步线程初始化Bugly。

    第三个参数为SDK调试模式开关,调试模式的行为特性如下:

    • 输出详细的Bugly SDK的Log;
    • 每一条Crash都会被立即上报;
    • 自定义日志将会在Logcat中输出。

    建议在测试阶段建议设置成true,发布时设置为false。

    增加上报进程控制

    UserStrategy strategy = new UserStrategy(context);

    //strategy.xxx()设置需要控制的属性   具体属性如下

    https://bugly.qq.com/docs/user-guide/advance-features-android/?v=20180709165613

    CrashReport.initCrashReport(context, "注册时申请的APPID", isDebug, strategy);

    以上就是crash的功能的简单使用,

    如果你嫌弃这个过程太麻烦了,恭喜你,你可以不用看这个了 ,因为下面的自动更新和热修复已经及把Crash功能合并在其中了,当然要增加上报进程控制一样可以如此

    UserStrategy strategy = new UserStrategy(context);

    //strategy.xxx()设置需要控制的属性   具体属性如下

    https://bugly.qq.com/docs/user-guide/advance-features-android/?v=20180709165613

    Bugly.init(getApplication(),"注册时申请的APPID",true,strategy );

    =============================================分割线=============================================

    基于bugly的自动更新

    https://bugly.qq.com/docs/user-guide/instruction-manual-android-upgrade/?v=20180709165613

    腾讯官方文档 

    按照官方文档来走也是肯定会成功的,

    在此仅记录遇见无法更新的问题

     //设置本机为测试开发设备
    // Bugly.setIsDevelopmentDevice(getApplication(),true);

    很是奇怪,我设置本机为开发测试设备之后竟然收不到更新提示,所以我果断把此方法注释掉了

    在后来我发现了自动更新的全量更新,也就是所有设备的,所以无法更新的原因不在于此,最后发现,当确认当期版本无误之后,官方给的时间是在3s,但是我自己在能提示更新的时间大概在2分钟之后,(可能因为网速问题,更新提示有延迟)

    自动更新在初始化之后就已经调用了,如果后续还需要,那个调用Beta.checkUpgrade(false,false)方法,

    参数1:isManual 用户手动点击检查,非用户点击操作请传false

    参数2:isSilence 是否显示弹窗等交互,[true:没有弹窗和toast] [false:有弹窗或toast]

    默认的Beta.checkUpgrade() == Beta.checkUpgrade(true,false)

     

    还有比较蒙的一点就是,所有的版本的竟然可以在同一时间段同时启动,这时候我就比较好奇了,我到底更新的是哪一个版本,难道是随机的吗?这个问题现在还没有去测试,等有时间测试完成之后会贴上的!!!

     

    之前一直不知道这个策略名称到底是干啥用的,后来发现这只是一个标题的作用

    更新和热修复都有一个beta属性,具体属性如下

    https://bugly.qq.com/docs/user-guide/advance-features-android-beta/

    =============================================分割线==============================================

    crash的抓取和自动更新这一块按照文档走,只要你的配置没有问题,注册的appid没有问题,权限没有问题,网络没有问题,那就没有其他问题了,热更感觉坑就多了很多了,

    首先

    官方文档为了让我们能更好的学习热更技术,给我们提供了很多便利,比如bugly的热更是基于微信tinker开发的,我们只用去配置少量的代码就能集成热更功能,再比如,在页面的最上面给出了视频教程,等等

     

     孰能想到这和竟然是空的,如果想看视频的同学需要去自己找

     课时1:Bugly热更新介绍

    https://v.qq.com/x/page/w0384j4xrnd.html 

    课时2:tinker-support插件的使用

    https://v.qq.com/x/page/o03855ejzf4.html

    课时3:集成Sdk

    https://v.qq.com/x/page/e03855m02j8.html

    课时4:生成补丁包之痛 我懂你

    https://v.qq.com/x/page/i0385n7ncro.html

    课时5:补丁包为何传不上去

    https://v.qq.com/x/page/e0385shcfzm.html

    课时6:普通打包的热更新

    https://v.qq.com/x/page/k0385qx3tk2.html

    课时7:渠道包的热更新

    https://v.qq.com/x/page/z0393rt2cmq.html

    课时8:加固包的热更新

    https://v.qq.com/x/page/p0398b38vwl.html

     

    相信有不少小伙伴在打包的时候发现build\bakApk\app-0910-13-51-24\,缺失了app-release-mapping.txt

    而确实的这个文件其实是因为混淆没有打开,

    mapping文件

    mapping.txt 
    列出了原始的类,方法和字段名与混淆后代码间的映射。这个文件很重要,当你从release版本中收到一个bug报告时,可以用它来翻译被混淆的代码。

    mapping目录在 \app\build\outputs\mapping\release  把它复制到build\bakApk\app-0910-13-51-24\就好

    如果这时候还是找不到这个文件 就需要在混淆文件中添加

    混淆前后的映射 
    -printmapping mapping.txt

    然后到最后我发现其实没有这个文件的时候 我的更新和热更都是可以用的,抓到的crash日志也是可以正常查看,但是为避免意外出现,建议还是把app-release-mapping.txt文件和符号表插件配置好。

    另外一定要注意enableProxyApplication 这个属性

    enableProxyApplication = false 的情况

    这是Tinker推荐的接入方式,一定程度上会增加接入成本,但具有更好的兼容性。

     你需要自己去写ApplicationLike extends DefaultApplicationLike 

    还要去写SampleApplication

     public SampleApplication() {
            super(ShareConstants.TINKER_ENABLE_ALL, "xxx.xxx.SampleApplicationLike",
                    "com.tencent.tinker.loader.TinkerLoader", false);
        }
    
    参数一:表示Tinker支持的类型
    参数二:Application代理类 这里填写你自定义的ApplicationLike 包名+类名
    参数三:Tinker的加载器,使用默认即可
    参数四:加载dex或者lib是否验证md5,默认为false

     

    enableProxyApplication = true 的情况

    即正常使用

    在编译的时候如果找不到gradle 请看as最右边

    如果在编译的时候出现app-release-unsigned.apk情况,这是因为你的apk在打包的时候没有找到keystore

    在build.gradle中添加

    // 签名配置
        signingConfigs {
            release {
                try {
                    //这个keystore文件夹和app下的build文件夹同级
                    storeFile file("./keystore/xxx.keystore")
                    storePassword ""//密码
                    keyAlias ""//keystore的别名
                    keyPassword ""//密码
                } catch (ex) {
                    throw new InvalidUserDataException(ex.toString())
                }
            }
    
            debug {
                storeFile file("./keystore/debug.keystore")
            }
        }
    
        // 构建类型
        buildTypes {
            release {
                minifyEnabled false
                signingConfig signingConfigs.release
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
            debug {
                debuggable true
                minifyEnabled false
                signingConfig signingConfigs.debug
            }

    基准包和补丁包注意事项:

    基准包在没有升级到下个版本之前,务必不要删除,因为补丁包要和基准包对应,不然无法匹配,导致上传更新失败

    生成基准包的时候 baseApkDir 是以一个日期格式生成文件夹,

    在打补丁包的时候这个字符串一定要换成基准包的文件夹名。

    tinkerId 基本包和补丁包一定要确保唯一性,但是也可以这样写

    经过的测试发现只要补丁包的baseApkDir能和基准包的对应上,以上也是可以接到补丁的,同一个基准包同时只能下发一个补丁

    后下发的补丁会冲突掉之前的补丁包

    现在我要去看符号表的插入和so文件的更新了

     

    展开全文
  • Testin与Bugly对比

    千次阅读 2018-07-15 19:17:44
    理论上说二者没有什么可比性,但今天说的是二者的界面对比。为什么感觉它们非常像呢,可能跟我最近与二者的接触比较多有关系。先简单介绍一下它们吧。 Testin是目前国内非常有名的第三方测试平台,Testin是全球最大...
  • Bugly接入小结

    千次阅读 2018-02-09 16:17:43
    目前腾讯bugly热修复功能是免费的,结合我自己的实践,感觉对文档的理解很重要,自己开始也是文档没理解透彻,走了不少弯路,这里就做个小结;第一步: 工程的gradle dependence classpath 'com.tencent.tinker:tin...
  • 安卓腾讯Bugly使用教程

    千次阅读 2018-06-25 16:55:46
    这个是官网的网址https://bugly.qq.com,集成并获取appID都需要在这里面进行,没有注册的小伙伴用qq号就行,毕竟是企鹅的,废话不多说show time。首先点击 新建产品 ,然后出现如下界面简单填写一下,保存就可以了。...
  • CrashReport.postCatchedException(e); 如果是 Exception 可以用 CrashReport.postCatchedException(e); 如果想 自己打印固定日志 可以用 CrashReport....然后再 bugly 后台对应的app 异常上报 - 错误分析中...
  • Bugly不认真看文档,遇到的坑

    万次阅读 2016-07-29 18:05:06
    腾讯bugly 统计crash 不认真看文档,搞得我找个bug找了两天,无意发现的。爱偷懒,不把文档认真看,直接集成,害的自己看bugly上面的一个bug找了好久,最主要是定位不到到底是哪里出问题。项目植入bugly 和其他三方...
  • bugly 上传符号表文件

    千次阅读 2017-12-19 09:02:35
    整了半天,bugly自动上传符号表文件终于配置成功,配置过程,遇到好几个坑,为了避免以后再遇到这样的坑,所以就写了这篇博客把它记录下来。(我使用的是使用脚本自动配置,这样会省去很多麻烦。) 第一步:首先下载和...
  • Objective_C / Swift项目使用Bugly框架收集上架发版后产品奔溃信息
  • Bugly Android自动上传符号表

    千次阅读 热门讨论 2017-08-07 16:07:03
    我采用的是自动配置,这样比较简单,但是还是有一些坑的。 * 官方给出的appId和appKey样板带有尖括号,实际上不能带 * appVersion(就是你的versionName),这两个地方不能有汉字,否则不能识别符号表(**这个最坑*...
  • 问题描述在集成腾讯 Bugly 时有如下注意事项本来只是一个建议,但是app方法数真的超出65535会导致 Bugly 的无法正常使用问题分析因此必须把 Bugly 类放到主Dex,方式用两种:1.multiDexKeepFile:手动加入要放到Main....
  • Cocos项目接入腾讯Bugly

    千次阅读 2017-02-10 17:28:17
    1、腾讯Bugly简介 BuglySDK是可以上报bug到开发者后台的sdk,获取的信息可以包括用户移动设备的硬件信息(平台、系统、CPU架构、内存等各种信息)以及出错的堆栈信息。总之,这是一个可以让开发者快速获取用户端的...
  • bugly在错误跟踪上功不可没,但是如果在工程中没合理设置也会带来一些令人头疼的问题。比如把调试模式下的错误也上传到bugly,调试时上传mapping文件影响编译速度。这里我提供一种方法解决以上问题:一. 让bugly仅在...
  • 最近公司Flutter项目中要求集成监控App崩溃的功能,由于Flutter是一个跨平台中较新的框架,在衡量阿里云、AppCenter、腾讯Bugly的利弊之后,内部决定使用TencentBugly。而在GitHub上也找到了对应的插件,地址如下: ...
  • 一、登录BUGLY官网1、登录BUGLY官网以后,选择新建产品,选择IOS或ADNROID平台,如图: 完事以后点击保存,点击当前项目查看详细信息: 主要有:异常上报(异常概览、崩溃分析、卡顿分析、高级搜索、异常配置)、...
  • 由于android更新到了N之后,Bugly原有的更新方式会出问题,但是现在按照Bugly官网的配置方法依然不行。 目前存在的问题是能够下载,但是无法调起安装界面。请问各位dalao怎么解决这个问题?谢谢 希望能有Bugly官方...
  • Bugly 是腾讯公司为移动开发者开放的服务之一,这里主要指 Crash 监控、崩溃分析等质量跟踪服务。一、登录BUGLY官网1、登录BUGLY官网以后,选择新建产品,选择IOS或ADNROID平台,如图: 完事以后点击保存,点击当前...
  • 腾讯Bugly,简单实用的崩溃日志收集

    万次阅读 2016-07-13 14:06:34
    一:给大家介绍一款简单高效的应用崩溃收集方法:腾讯Bugly 腾讯 Bugly,是腾讯公司为移动开发者开放的服务之一,面向移动开发者提供专业的 Crash 监控、崩溃分析等质量跟踪服务。Bugly 能帮助移动互联网开发者更...
1 2 3 4 5 ... 20
收藏数 6,847
精华内容 2,738
关键字:

bugly