首先在tinker平台新建app,获取对应的appkey
首先在项目下的gradle文件下添加
classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.6"
如下图
以下几个在app的gradle文件添加:
1、添加依赖
annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:1.9.6") { changing = true }
compileOnly('com.tinkerpatch.tinker:tinker-android-anno:1.9.6') { changing = true }
implementation('com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.6') { changing = true }
implementation 'com.android.support:multidex:1.0.1'
2、添加引用
apply from: 'tinkerpatch.gradle'
3、添加签名
添加完签名不要忘了在buildTypes->release里面添加
signingConfig signingConfigs.config
4、添加ndk和multiDexEnabled
ndk {
//设置支持的SO库架构
abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
这样app目录下的gradle文件就配置完了,接下来添加tinkerpatch.gradle文件,可以直接复制下面的代码,文件在app目录下,更我们上面配置的gradle文件同级。
文件代码
apply plugin: 'tinkerpatch-support'
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.6-0703-09-26-35"
def variantName = "release"
/**
* 对于插件各参数的详细解析请参考
* http://tinkerpatch.com/Docs/SDK
*/
tinkerpatchSupport {
/** 可以在debug的时候关闭 tinkerPatch **/
/** 当disable tinker的时候需要添加multiDexKeepProguard和proguardFiles,
这些配置文件本身由tinkerPatch的插件自动添加,当你disable后需要手动添加
你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro,
需要你手动修改'tinker.sample.android.app'本示例的包名为你自己的包名, com.xxx前缀的包名不用修改
**/
tinkerEnable = true
reflectApplication = true
/**
* 是否开启加固模式,只能在APK将要进行加固时使用,否则会patch失败。
* 如果只在某个渠道使用了加固,可使用多flavors配置
**/
protectedApp = false
/**
* 实验功能
* 补丁是否支持新增 Activity (新增Activity的exported属性必须为false)
**/
supportComponent = true
autoBackupApkPath = "${bakPath}"
appKey = "68c4e7c2d49890b1"
/** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = "1.0.6"
def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
def name = "${project.name}-${variantName}"
baseApkFile = "${pathPrefix}/${name}.apk"
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
/**
* 若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
* 注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
**/
}
/**
* 用于用户在代码中判断tinkerPatch是否被使能
*/
android {
defaultConfig {
buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
}
}
/**
1. 一般来说,我们无需对下面的参数做任何的修改
2. 对于各参数的详细介绍请参考:
3. https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
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
}
}
里面主要注意3个参数baseInfo appkey appVersion:
baseInfo 在后面会用到,到时再说
appkey换成自己在平台申请的
其中 appVersion 要和 app下的build.gradle文件里面的versionName保持一致
接下来添加权限
<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.REQUEST_INSTALL_PACKAGES" />
鉴于现在的手机系统版本,不要忘了动态添加权限
android7.0即以上需要添加provide
<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,grantUriPermissions">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"
tools:replace="name,resource"/>
</provider>
在res目录新建xml文件夹,创建provider_paths.xml文件如下:
<?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>
然后就是新建自己的application了,别忘了在AndroidManifest.xml里面把aplication的name加上,下面整个类的代码可以复制
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initTinkerPatch();
}
private void initTinkerPatch() {
// 我们可以从这里获得Tinker加载过程的信息
ApplicationLike tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
// 初始化TinkerPatch SDK
TinkerPatch.init(
tinkerApplicationLike
// new TinkerPatch.Builder(tinkerApplicationLike)
// .requestLoader(new OkHttp3Loader())
// .build()
)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3)
;
// 每隔3个小时(通过setFetchPatchIntervalByHours设置)去访问后台时候有更新,通过handler实现轮训的效果,可以改为(1-24)小时
// fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false)
// 不同的是,会通过handler的方式去轮询
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
@Override
public void attachBaseContext(Context base) {
super.attachBaseContext(base);
//you must install multiDex whatever tinker is installed!
MultiDex.install(base);
}
}
这样所有的配置就做完了,接下就可以生成apk包了,可以先去修改mainactivity里面的布局之类的,用于后面的打补丁之后做比较,我这边是修改textview里面的内容为当前时间。生成apk的方法,点击Android studio右上角的gradle,按照下图,双击 assembleRelease
就可以在左边的工程项目下的app->build找到对应的apk,如下图
把这个apk包安装到手机,然后接下来就可以模拟打补丁了,先去修改布局里面的textview显示的时间,接着修改tinketpatch.gradle文件里面的 baseInfo,上面有提到的后面再说的那个参数。怎么修改?如图
在生成apk时,可以不管baseInfo这个参数,这时生成的可以称之为基准包,后面生成的补丁,不管是多少个补丁包,只要app的版本没有变,baseInfo的参数设置都要指向这个基准包所对应的包名。
生成补丁的方法,还是点击Android studio右上角的gradle,如下图
双击tinkerPatchRelease,就可以生成补丁包了,补丁布的路径如下图
这个patch_signed_7zip.apk就是补丁包了,接下来只要把他上传到tinker平台就算是打补丁成功了
如果你是刚生成apk包,然后马上模拟打补丁是不会里面生效的,由于MyApplication里面的这个设置setFetchPatchIntervalByHours(3),里面的3指3小时,即这个补丁3小时后才会生效(由于这个原因我一直以为我的配置是错误的)。但如果你安装apk包后,过个3小时,然后再上传补丁包,这时你杀掉app再重启,刚刚打的补丁就可以立马生效了。如果这段话有错误,欢迎各位大佬指正。
测试后发现,我下发补丁后,app要杀掉重启两次后,app才能更新到下发的补丁,第一次杀掉重启只是下载和合并补丁,第二次重启才应用补丁包。不能一次重启就马上修复bug,感觉并不实用,大佬勿喷啊