##騰訊Bugly
功能:
1.異常上報(bào)(上線后的APP 在用戶手中發(fā)送的bug看不到,這就用到Bugly,可以吧bug上傳到后臺(tái)供開發(fā)人員觀察并及時(shí)修復(fù)bug)
????2.運(yùn)營統(tǒng)計(jì),可以統(tǒng)計(jì)日活躍,月活躍量,還有使用客戶數(shù),安裝客戶數(shù)
????3.應(yīng)用升級(jí),升級(jí)功能是轉(zhuǎn)為APP的灰度升級(jí)而開發(fā)的組件,在Bugly內(nèi)側(cè)頁面配置好APP的更新策略,策略指定的老版本APP在啟動(dòng)時(shí)會(huì)自動(dòng)檢測(cè)更新并提示升級(jí),為團(tuán)隊(duì)的應(yīng)用分發(fā),灰度內(nèi)側(cè)提供一站式解決方案
????4.熱更新,熱更新能力是Bugly為解決開發(fā)者緊急修復(fù)線上bug,而無需重新發(fā)布新版本,讓用戶無感知就能把問題修復(fù)的一項(xiàng)能力。bugly目前采用微信Tinker的開源方案,開發(fā)者主需要繼承我們提供的SDK就開源實(shí)現(xiàn)自動(dòng)下載補(bǔ)丁包、合成、并應(yīng)用補(bǔ)丁的功能,我們也提供了熱更新管理后臺(tái),讓開發(fā)者對(duì)每個(gè)版本補(bǔ)丁進(jìn)行管理?
##Bugly集成熱更新
1.申請(qǐng)賬號(hào):HTTPS://bugly.qq.com/
2.完善開發(fā)者信息+創(chuàng)建應(yīng)用(直接提交,不審核,可直接使用)
##參照文檔集成
首先去申請(qǐng)賬號(hào):https://bugly.qq.com/
創(chuàng)建應(yīng)用,拿到appid后續(xù)會(huì)用到
在工程跟目錄下
????????buildscript {
????repositories {
????????google()
????????jcenter()
????}
????dependencies {
????????// tinkersupport插件, 其中l(wèi)astest.release指拉取最新版本,也可以指定明確版本號(hào),例如1.0.4
???????classpath "com.tencent.bugly:tinker-support:1.1.5"
????}
}
##在導(dǎo)入依賴的Gradle中
defaultConfig {
????????applicationId "com.example.dell.demohotbuglys"
????????minSdkVersion 17
????????targetSdkVersion 27
????????versionCode 1
????????versionName "1.0"
????????testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
????????ndk {
????????????//設(shè)置支持的SO庫架構(gòu)
????????????abiFilters 'armeabi', 'x86' // 'armeabi-v7a', 'x86_64', 'arm64-v8a'
????????}
????????// 開啟multidex
????????multiDexEnabled true
}
// 簽名配置,官方文檔上面沒說,但我們得配置,因?yàn)楣倬W(wǎng)不負(fù)責(zé)教你????配置這個(gè),
????signingConfigs {
????????release {
????????????try {
????????????????storeFile file('buglys.jks')
????????????????storePassword "123456"
????????????????keyAlias "key0"
????????????????keyPassword "123456"
????????????} catch (ex) {
????????????????throw new InvalidUserDataException(ex.toString())
????????????}
????????}
????}
????buildTypes {
????????release {
????????????signingConfig signingConfigs.release
????????????minifyEnabled true
????????????proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
????????}
????????debug {
????????????signingConfig signingConfigs.release
????????????minifyEnabled true
????????????proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
????????}
????}
?????在dependencies 中導(dǎo)入下面幾個(gè)依賴
????dependencies {
compile "com.android.support:multidex:1.0.1" // 多dex配置
????//其中l(wèi)atest.release指代最新版本號(hào),也可以指定明確的版本號(hào),例如1.3.4
????//包含了crash上報(bào)功能
????compile 'com.tencent.bugly:crashreport_upgrade:1.4.0'
????// 指定tinker依賴版本(注:應(yīng)用升級(jí)1.3.5版本起,不再內(nèi)置tinker)
????compile 'com.tencent.tinker:tinker-android-lib:1.9.9'
????//其中l(wèi)atest.release指代最新版本號(hào),這里我們指定某個(gè)版本
????//compile 'com.tencent.bugly:nativecrashreport:latest.release'
????compile 'com.tencent.bugly:nativecrashreport:3.7.1'
}
在最頂端依賴插件腳本
????// 依賴插件腳本
????apply from: 'tinker-support.gradle'
##在APP下創(chuàng)建tinker-support.gradle這個(gè)文件哦(和app module 的 build.gradle同級(jí)別)。
apply plugin: 'com.tencent.bugly.tinker-support'
????def bakPath = file("${buildDir}/bakApk/")
????/**
?????6
?????*?此處填寫每次構(gòu)建生成的基準(zhǔn)包目錄,注意每次打補(bǔ)丁包都需要修????改
?????7
?????*/
????def baseApkDir = "app-0611-20-44-04"
????/**
?????11
?????*?對(duì)于插件各參數(shù)的詳細(xì)解析請(qǐng)參考
12
*/
????tinkerSupport {
????// 開啟tinker-support插件,默認(rèn)值true
????enable = true
????// 指定歸檔目錄,默認(rèn)值當(dāng)前module的子目錄tinker
????autoBackupApkDir = "${bakPath}"
????// 是否啟用覆蓋tinkerPatch配置功能,默認(rèn)值false
????// 開啟后tinkerPatch配置不生效,即無需添加tinkerPatch
????overrideTinkerPatchConfiguration = true
????// 編譯補(bǔ)丁包時(shí),必需指定基線版本的apk,默認(rèn)值為空
????// 如果為空,則表示不是進(jìn)行補(bǔ)丁包的編譯
????// @{link tinkerPatch.oldApk }
????baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
????// 對(duì)應(yīng)tinker插件applyMapping
????baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
????// 對(duì)應(yīng)tinker插件applyResourceMapping
????baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
????//建議設(shè)置true,用戶就不用再自己管理tinkerId的命名,插件會(huì)為每一次構(gòu)建的base包自動(dòng)生成唯一的tinkerId,默認(rèn)命名規(guī)則是versionname.versioncode_時(shí)間戳
????//具體參考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
????// 構(gòu)建基準(zhǔn)包和補(bǔ)丁包都要指定不同的tinkerId,并且必須保證唯一性
????tinkerId = "patch-1.0.1-0611-2030"
????// 構(gòu)建多渠道補(bǔ)丁時(shí)使用
????// buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
????// 是否啟用加固模式,默認(rèn)為false.(tinker-spport 1.0.7起支持)
????// isProtectedApp = true
????// 是否開啟反射Application模式
????enableProxyApplication = false
????// 是否支持新增非export的Activity(注意:設(shè)置為true才能修改AndroidManifest文件)
????supportHotplugComponent = true
????}
????/**
57
?????*?一般來說,我們無需對(duì)下面的參數(shù)做任何的修改
?????58
?????*?對(duì)于各參數(shù)的詳細(xì)介紹請(qǐng)參考:
59
?????*?https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
60
?????*/
????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" //??可選,設(shè)置mapping文件,建議保持舊apk的proguard混淆方式
????????//applyResourceMapping = "${bakPath}/${appName}/app-release-R.txt" // 可選,設(shè)置R.txt文件,通過舊apk文件保持ResId的分配
????}
}
##去初始化applacation
????public class SampleApplication extends TinkerApplication {
????public SampleApplication() {
????????super(ShareConstants.TINKER_ENABLE_ALL, "com.example.dell.demohotbuglys.SampleApplicationLike",
????????????????"com.tencent.tinker.loader.TinkerLoader", false);
????}
}
##使用applacation的代理類來完成所有的工作
注意在初始化時(shí)候要換成自己的appid
?????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();
????????// 這里實(shí)現(xiàn)SDK初始化,appId替換成你的在Bugly平臺(tái)申請(qǐng)的appId
????????// 調(diào)試時(shí),將第三個(gè)參數(shù)改為true
????????Bugly.init(getApplication(), "a55ecdce55", 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);
????}
????@Override
????public void onTerminate() {
????????super.onTerminate();
????????Beta.unInit();
}
????}
##清單文件中注冊(cè)權(quán)限 及配置一些文件
????<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" />
????????<!--bugly-->
????????<activity
????????android:name="com.tencent.bugly.beta.ui.BetaActivity"
????????android:configChanges="keyboardHidden|orientation|screenSize|locale"
????????android:theme="@android:style/Theme.Translucent" />
>
????注意:如果您想兼容Android N(7.0/M(8.0))或者以上的設(shè)備,必須要在AndroidManifest.xml文件中配置FileProvider來訪問共享路徑的文件
????????<provider
????????android:name="android.support.v4.content.FileProvider"
????????android:authorities="${applicationId}.fileProvider"
????????android:exported="false"
????????android:grantUriPermissions="true">
????????<meta-data
????????android:name="android.support.FILE_PROVIDER_PATHS"
????????android:resource="@xml/provider_paths"/>
????</provider>
如果你使用的第三方庫也配置了同樣的FileProvider, 可以通過繼承FileProvider類來解決合并沖突的問題,示例如下:
????<provider
android:name=".utils.BuglyFileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true"
????????tools:replace="name,authorities,exported,grantUriPermi????ssions">
????<meta-data
????????android:name="android.support.FILE_PROVIDER_PATHS"
????????android:resource="@xml/provider_paths"
????????tools:replace="name,resource"/>
????</provider>
>這里要注意一下,F(xiàn)ileProvider類是在support-v4包中的,檢查你的工程是否引入該類庫。
在res目錄新建xml文件夾,創(chuàng)建provider_paths.xml(庫里已經(jīng)有了,不用創(chuàng)建了)文件如下:
????<?xml version="1.0" encoding="utf-8"?>
????<paths xmlns:android="http://schemas.android.com/apk/res/android">
????<!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
????<external-path name="beta_external_path" path="Download/"/>
????<!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
????<external-path name="beta_external_files_path" path="Android/data/"/>
????</paths>
>混淆配置
-dontwarn com.tencent.bugly.**
????-keep public class com.tencent.bugly.**{*;}
????# tinker混淆規(guī)則
????-dontwarn com.tencent.tinker.**
????-keep class com.tencent.tinker.** { *; }
????#如果你使用了support-v4包,你還需要配置以下混淆規(guī)則:
????-keep class android.support.**{*;}
##自己去手寫一個(gè)bug
private void bug() {
????????String str = null;
????????Log.d(TAG, "bug: "+str.length());
????????Toast.makeText(this,"bug 不見了", Toast.LENGTH_SHORT).show();
????}
找到我們studio右上角的Gradle,點(diǎn)開會(huì)看到當(dāng)前APP的構(gòu)建文件app-->build-->assembleRelesease,雙擊此目錄會(huì)自動(dòng)打包生成apk(在build目錄下生成bakapk文件夾,內(nèi)部才是我們打包的apk,有三個(gè)文件,實(shí)際應(yīng)用中,請(qǐng)注意保存線上發(fā)布版本的基準(zhǔn)apk包、mapping文件、R.txt文件,如果線上版本有bug,就可以借助我們tinker-support插件進(jìn)行補(bǔ)丁包的生成),也就是我們有bug的一個(gè)版本,然后運(yùn)行到手機(jī)去測(cè)試,點(diǎn)擊崩掉。
>第二步
>
????修改bug,并去我們的tinker-support.gradle這個(gè)文件中,把生成的bug版本的文件夾名字復(fù)制,修改def baseApkDir = "app-0611-20-44-04"這個(gè)值,把賦值的內(nèi)容放在這個(gè)變量中
????第二個(gè)修改的就是我們的tinkerId = "patch-1.0.1-0611-2030"
????只用把patch隨便改個(gè)自己記住的名字,把后邊版本號(hào)增加就行,比如2030--》到2060 2045 2080 只要大于之前那個(gè)就行
>第三步
????同樣找到我們studio右上角的Gradle,點(diǎn)開會(huì)看到tinker-support這個(gè)文件夾,點(diǎn)開,找到buildTinkerPatchRelease,雙擊生成補(bǔ)丁包,等待生成后,會(huì)在我們的build下的outputs目錄下的patch文件夾中,同樣會(huì)生成三個(gè)文件,我們保存,并把7zip。apk名字的去上傳到我們的騰訊Bugly中,找到應(yīng)用升級(jí)模塊,點(diǎn)擊熱更新,上傳補(bǔ)丁,把此文件上傳上去,會(huì)自動(dòng)匹配目標(biāo)版本,并在下發(fā)中選擇全量設(shè)備,點(diǎn)擊立即下發(fā)即可,等待10分鐘左右再去看應(yīng)用(有可能時(shí)間更長(zhǎng),不固定),已經(jīng)修復(fù)。