1、在project目录下的build.gradle的dependencies下添加如下代码:
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.1')
2、添加依赖配置到你的app/build.gradle的dependencies下:
provided('com.tencent.tinker:tinker-android-anno:1.7.1')
compile('com.tencent.tinker:tinker-android-lib:1.7.1')
3、在app/build.gradle的dependencies的最外层添加下面这些配置:
def bakPath = file("${buildDir}/bakApk/")
ext {
tinkerEnabled = true
//for normal build
//原来的apk地址
tinkerOldApkPath = "${bakPath}/app-debug-1028-12-47-25.apk"
//如果资源文件改变了,这项必须填写
//tinkerApplyResourcePath = "${bakPath}/app-debug-1018-17-32-47-R.txt"
//只用于多渠道打包,没有的可以忽略
//tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
def getOldApkPath() {
return hasProperty("OLD_APK") ? OLD_APK : ext.tinkerOldApkPath
}
/*def getApplyMappingPath() {
return hasProperty("APPLY_MAPPING") ? APPLY_MAPPING : ext.tinkerApplyMappingPath
}*/
/*def getApplyResourceMappingPath() {
return hasProperty("APPLY_RESOURCE") ? APPLY_RESOURCE : ext.tinkerApplyResourcePath
}*/
//TINKER_ID可以自己指定
def getTinkerIdValue() {
return hasProperty("TINKER_ID") ? TINKER_ID : "100"
}
def buildWithTinker() {
return hasProperty("TINKER_ENABLE") ? TINKER_ENABLE : ext.tinkerEnabled
}
/*def getTinkerBuildFlavorDirectory() {
return ext.tinkerBuildFlavorDirectory
}*/
if (buildWithTinker()) {
apply plugin: 'com.tencent.tinker.patch'
tinkerPatch {
//必须的
oldApk = getOldApkPath()
//可选的,默认为false
ignoreWarning = false
//可选,默认为true
useSign = true
buildConfig {
//可选的,由于这用不到所以注释掉了
// applyMapping = getApplyMappingPath()
//可选
// applyResourceMapping = getApplyResourceMappingPath()
//必须的
tinkerId = getTinkerIdValue()
}
dex {
//可选,默为jar
dexMode = "jar"
//可选,默认为false
usePreGeneratedPatchDex = false
//必须的,默认为[]
pattern = ["classes*.dex",
"assets/secondary-dex-?.jar"]
//必须的,默认为[]
loader = ["com.tencent.tinker.loader.*",
//这里必须换成你自己的Application
"tinker.sample.android.app.SampleApplication"]
}
lib {
//可选,默认为[]
pattern = ["lib/armeabi/*.so"]
}
res {
//可选,默认为[]
pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
//可选,默认为[]
ignoreChange = ["assets/sample_meta.txt"]
//默认为100kb
largeModSize = 100
}
packageConfig {
//可选
configField("patchMessage", "tinker is sample to use")
}
/**
* if you don't use zipArtifact or path, we just use 7za to try
*/
sevenZip {
//可选,默认为7zip
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
/**
* optional,default '7za'
* you can specify the 7za path yourself, it will overwrite the zipArtifact value
*/
// path = "/usr/local/bin/7za"
}
}
/**
* bak apk and mapping
*/
android.applicationVariants.all { variant ->
/**
* task type, you want to bak
*/
def taskName = variant.name
tasks.all {
if ("assemble${taskName.capitalize()}".equalsIgnoreCase(it.name)) {
it.doLast {
copy {
def date = new Date().format("MMdd-HH-mm-ss")
from "${buildDir}/outputs/apk/${project.getName()}-${taskName}.apk"
into bakPath
rename { String fileName ->
fileName.replace("${project.getName()}-${taskName}.apk", "${project.getName()}-${taskName}-${date}.apk")
}
from "${buildDir}/outputs/mapping/${taskName}/mapping.txt"
into bakPath
rename { String fileName ->
fileName.replace("mapping.txt", "${project.getName()}-${taskName}-${date}-mapping.txt")
}
from "${buildDir}/intermediates/symbols/${taskName}/R.txt"
into bakPath
rename { String fileName ->
fileName.replace("R.txt", "${project.getName()}-${taskName}-${date}-R.txt")
}
}
}
}
}
}
}
4、自定义applicaiton继承DefaultApplicationLike,并且添加注解@DefaultLifeCycle,如果你之前的代码已经有自定义的application,可以将你的application继承DefaultApplicationLike,而不是Applicaiton。
@DefaultLifeCycle(application = "com.ress.tinker.app.SampleApplicaiton",
flags = ShareConstants.TINKER_ENABLE_ALL)
public class MyApplication extends DefaultApplicationLike {
public MyApplication(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent, Resources[] resources, ClassLoader[] classLoader, AssetManager[] assetManager) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent, resources, classLoader, assetManager);
}
application=“com.ress.tinker.app.SampleApplication"中的类名可以自己定义,这个类将由TInker自动生成。并在AndroidManifest,xml文件的applicaiton标签中声明。
<application
android:name=".app.SampleApplicaiton"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
5、重写MyApplicaiton的OnBaseContextAttached()方法,并初始化TInker
@DefaultLifeCycle(application = "com.ress.tinker.app.SampleApplicaiton",
flags = ShareConstants.TINKER_ENABLE_ALL)
public class MyApplication extends DefaultApplicationLike {
public MyApplication(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent, Resources[] resources, ClassLoader[] classLoader, AssetManager[] assetManager) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent, resources, classLoader, assetManager);
}
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
TinkerInstaller.install(this);
}
}
6、加载修复代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TinkerInstaller.onReceiveUpgradePatch(MainActivity.this, Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk");
Toast.makeText(this, "有Bug!!", Toast.LENGTH_SHORT).show();
}
}
Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk"
这是修复后的apk放在手机中的位置
6、打开android studio右侧的gradle面板,找到assembleDebug,双击
7、打开build/bakapk,将apk装到手机里
将apk名字复制到之前app/build.gradle中的tinkerOldApk处
ext {
//for some reason, you may want to ignore tinkerBuild, such as instant run debug build?
tinkerEnabled = true
//for normal build
//原来的apk地址
<span style="color:#ff6666;">tinkerOldApkPath = "${bakPath}/app-debug-1028-12-47-25.apk"</span>
//如果资源文件改变了,这项必须填写
//tinkerApplyResourcePath = "${bakPath}/app-debug-1018-17-32-47-R.txt"
//只用于多渠道打包,没有的可以忽略
//tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
8、修改土司的内容,再次打开android studio右侧的gradle面板,双击tinker/tinkerPatchDebug
9、在build/outputs/tinkerpatch下找到patch_signed_7zip.apk,并拷贝到手机内存根目录
注意:
不能忘记权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
10、运行之前的apk,干掉进程之后再次打开,会发现土司的内容变了。
最后感谢简书红飞大神的基于腾讯Tinker热修复框架的Demo和腾讯的Tinker,才能顺利的集成Tinker。