第一步:添加相关依赖
回车下面的依赖全部添加上去,上面的是android 本来有的
第二步:在app级的builder.gradle里添加相关配置
1:这里是在defaultConfig里面,官方文档里面会加很多东西,但是热修复只需这两个就ok
2:这是在defaultConfig外面,但是在android里面,具体怎么操作生成不会的可以网上找
3:这也是在defaultConfig外面,但是在android里面,里面添加两句
4:基本上应用级的builder.gradle配置就到这结束了,还有最重要的一步,在顶部添加apply from:''........这是打包的相关配置,很重要也很坑
5:不要急着点同步,否则第四步会报错,需要在app目录下新建一个file文件,名字就叫做 tinker-support.gradle 第四步添加的
第三步:在应用级的builder.gradler里面,添加以下
这里特别注意,目前腾讯的Bugly不支持高版本的gradle,所以尽量修改成3.2.0及以下,下面一句就是应用bugly相关资源了,版本可以往高了走,可以尝试一下
第四步:在刚刚创建的 tinker-support.gradle里面添加以下代码,全部复制即可,有注释,容易坑人的地方有截图解释
applyplugin:'com.tencent.bugly.tinker-support'
def bakPath = file("${buildDir}/bakApk/")
/**
* 此处填写每次构建生成的基准包目录,需要每次大补丁包的时候更换基准包目录
*/
def baseApkDir ="app-0827-08-54-15"
/**
* 对于插件各参数的详细解析请参考
*/
tinkerSupport {
// 开启tinker-support插件,默认值true
enable =true
// 自动生成tinkerId, 你无须关注tinkerId,默认为false
autoGenerateTinkerId =true
// 指定归档目录,默认值当前module的子目录tinker
autoBackupApkDir ="${bakPath}"
// 是否启用覆盖tinkerPatch配置功能,默认值false
// 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
overrideTinkerPatchConfiguration =true
// 编译补丁包时,必需指定基线版本的apk,默认值为空
// 如果为空,则表示不是进行补丁包的编译
// @{link tinkerPatch.oldApk }
baseApk ="${bakPath}/${baseApkDir}/app-release.apk"
// baseApk = "${bakPath}/${baseApkDir}/app-debug.apk"
// 对应tinker插件applyMapping
baseApkProguardMapping ="${bakPath}/${baseApkDir}/app-release-mapping.txt"
// baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt"
// 对应tinker插件applyResourceMapping
baseApkResourceMapping ="${bakPath}/${baseApkDir}/app-release-R.txt"
// baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-debug-R.txt"
// 构建基准包跟补丁包都要修改tinkerId,主要用于区分
// tinkerId = "base-1.0.0"
// tinkerId = "patch-1.0.2"
// 打多渠道补丁时指定目录
// buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
// 是否使用加固模式,默认为false
// isProtectedApp = true
// 是否采用反射Application的方式集成,无须改造Application
enableProxyApplication =false
// 支持新增Activity
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"
}
}
特别注意:
1:这里我把自动生成tinkerId,所以我把自定义的tinkerId注释掉了,好处是不用担心每次打包忘记更新tankerId,tankerId是热跟新的依据,一样的话可能会导致上传补丁包失败或其他错误
2:这是需要改动的地方,具体怎么改动,请往下看
3:这里生成基准包,就是你有bug的初始应用,点击后会生成相关的安装包
4:安装包目录在这里,这个目录的名字是根据当前时间起的,与上面所说的需要注意的地方毫无关系,不用担心
5:生成补丁包,就是你修改了bug后的包,不要着急点,在生成前你需要把刚刚提到需要注意的地方里面的名字改成刚刚生成基准包的名字,否则不会生成补丁包,直接给你生成基准包的哦,我挣扎了半天才知道这个
6:生成成功后会在outputs下的patch里有.....7zip.apk这就是你生成的补丁包,如果没有就说明你前面的步骤出问题了
7:生成成功后,就可以去控制台上传补丁包了,不要以为就好了,还有问题你会遇到
一种是上传的时候提示你没有对应版本的基准包
这种情况很简单,把刚刚你生成的基准包里面的apk文件拖到模拟器里安装,安装完成后打开运行以下,必须要能正常联网,这就是上报基准包,然后回来上传就可以了
第二种就是比较坑的了,我遇到的就是提示你文件格式非法,我找了半天没有什么不对劲,看到github上有人说是腾讯后台的原因,然后我就放弃挣扎了,第二天一早来上传补丁包,我靠我靠,上传成功!!!然后就没有然后了。。。其他错误我没遇到过,整个集成过程就暂且这样把,我也是刚刚集成,不懂不合适的地方请指教,只是想把坑分享出来,其实官方文档也很简单,就是乱了一点,还有很多配置,什么ndk一大堆,反正别人的代码就是low,哈哈哈互相嫌弃。
好了就到这吧,其他还有在AndroidManifest.xml里面配置的都一样,只是那个provider需要改成android x的包
然后那些Application啊什么的和官方文档以及demo提供的差不多,我也都贴出来吧
AndroidManifest.xml:
都用android x了不可能不知道联网需要加个userCleartextTraffic吧
需要加个activity的文件,腾讯提供的吧具体实现不需要管,只要加上就行了
android x的FileProvider
具体怎么写的,还有那个provider_paths的xml弄过的都知道,不知道的去网上搜吧,很简单
MainActivity:
package com.xqb.buglyhotupdatedemo3;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivityextends AppCompatActivity {
private ButtonshowBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showBtn=findViewById(R.id.show_btn);
showBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int num=1/1;
Toast.makeText(MainActivity.this,""+num, Toast.LENGTH_SHORT).show();
}
});
}
}
SampleApplication:
package com.xqb.buglyhotupdatedemo3;
import com.tencent.tinker.loader.app.TinkerApplication;
import com.tencent.tinker.loader.shareutil.ShareConstants;
/*
*create by xqb on 2020/8/26
*/
public class SampleApplicationextends TinkerApplication {
public SampleApplication() {
super(ShareConstants.TINKER_ENABLE_ALL,"com.xqb.buglyhotupdatedemo3.SampleApplicationLike","com.tencent.tinker.loader.TinkerLoader",false);
}
}
SampleApplicationLike:
package com.xqb.buglyhotupdatedemo3;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.Toast;
import androidx.multidex.MultiDex;
import com.tencent.bugly.Bugly;
import com.tencent.bugly.beta.Beta;
import com.tencent.bugly.beta.interfaces.BetaPatchListener;
import com.tencent.tinker.entry.DefaultApplicationLike;
import java.util.Locale;
/*
*create by xqb on 2020/8/26
*/
public class SampleApplicationLikeextends DefaultApplicationLike {
public static final StringTAG ="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();
// 设置是否开启热更新能力,默认为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) {
Toast.makeText(getApplication(),"补丁下载地址" + patchFile, 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 msg) {
Toast.makeText(getApplication(),"补丁下载成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadFailure(String msg) {
Toast.makeText(getApplication(),"补丁下载失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onApplySuccess(String msg) {
Toast.makeText(getApplication(),"补丁应用成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onApplyFailure(String msg) {
Toast.makeText(getApplication(),"补丁应用失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onPatchRollback() {
}
};
// 设置开发设备,默认为false,上传补丁如果下发范围指定为“开发设备”,需要调用此接口来标识开发设备
Bugly.setIsDevelopmentDevice(getApplication(),true);
// 多渠道需求塞入
// String channel = WalleChannelReader.getChannel(getApplication());
// Bugly.setAppChannel(getApplication(), channel);
// 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
Bugly.init(getApplication(),"90a758c619",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);
// TODO: 安装tinker
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();
}
}
里面有个需要你换成自己在控制台生成的appId。