apply plugin: 'com.android.application'
def bakPath = file("${buildDir}/bakapk")
android {
compileSdkVersion 26
defaultConfig {
applicationId "***"
minSdkVersion 16
targetSdkVersion 26
versionCode 201907300
versionName "2.3"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// ndk{
// abiFilters "armeabi-v7a,armeabi"
// }
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDir 'libs'
//说明so的路径为该libs路径,关联所有地图SDK的so文件
jni.srcDirs = []
}
}
buildToolsVersion '26.0.2'
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//
//引入Tinker库
//生成application时使用
annotationProcessor('com.tencent.tinker:tinker-android-anno:1.9.1')
compileOnly('com.tencent.tinker:tinker-android-anno:1.9.1')
//核心sdk库
implementation('com.tencent.tinker:tinker-android-lib:1.9.1')
}
ext {
tinkerEnable =true
tinkerOldApkPatch = "${bakPath}/"
tinkerId = "2.3"
tinkerApplyMappingPatch = "${bakPath}/"
tinkerApplyResourcePatch = "${bakPath}/"
}
def buildWithTinker(){
return ext.tinkerEnable
}
def getOldApkPatch(){
return ext.tinkerOldApkPatch
}
def getApplyMappingPatch(){
return ext.tinkerApplyMappingPatch
}
def getApplyResourceMappingPatch(){
return ext.tinkerApplyResourcePatch
}
def getTinkerIdValue(){
return ext.tinkerId
}
if (buildWithTinker()){
//启动tinker
apply plugin: 'com.tencent.tinker.patch'
tinkerPatch{
oldApk = getOldApkPatch() //获得基础类apk地址
ignoreWarning = false //不忽略警告
useSign = true //强制patch文件也使用签名
tinkerEnable = buildWithTinker()
buildConfig{
applyMapping = getApplyMappingPatch()//指定old文件打包时候所使用的混淆文件
applyResourceMapping = getApplyResourceMappingPatch() // 指定old apk的资源文件
tinkerId = getTinkerIdValue() // 获取tinkerId
keepDexApply = false //
}
dex{
dexMode = "jar"
pattern = ["class*.dex","assets/secondry-dex-?.jar"] //指定dex文件路径
loader= ["***.MyApplication"]
}
lib{
pattern = ["libs/*/*.so"] //指定dex文件路径
}
res{
pattern = ["res/*","assets/*","sources.arcs","AndroidMainfest.xml"] //指定dex文件路径
// ignoreChange = []//
largeModSize =100 // 资源修改的默认值
}
}
List flavors = new ArrayList<>();
project.android.productFlavors.each { flavor ->
flavors.add(flavor.name)
}
boolean hasFlavors = flavors.size() > 0
def date = new Date().format("MMdd-HH-mm-ss")
/**
* 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 fileNamePrefix = "${project.name}-${variant.baseName}"
def newFileNamePrefix = hasFlavors ? "${fileNamePrefix}" : "${fileNamePrefix}-${date}"
def destPath = hasFlavors ? file("${bakPath}/${project.name}-${date}/${variant.flavorName}") : bakPath
if (variant.metaClass.hasProperty(variant, 'packageApplicationProvider')) {
def packageAndroidArtifact = variant.packageApplicationProvider.get()
if (packageAndroidArtifact != null) {
try {
from new File(packageAndroidArtifact.outputDirectory.getAsFile().get(), variant.outputs.first().apkData.outputFileName)
} catch (Exception e) {
from new File(packageAndroidArtifact.outputDirectory, variant.outputs.first().apkData.outputFileName)
}
} else {
from variant.outputs.first().mainOutputFile.outputFile
}
} else {
from variant.outputs.first().outputFile
}
into destPath
rename { String fileName ->
fileName.replace("${fileNamePrefix}.apk", "${newFileNamePrefix}.apk")
}
from "${buildDir}/outputs/mapping/${variant.dirName}/mapping.txt"
into destPath
rename { String fileName ->
fileName.replace("mapping.txt", "${newFileNamePrefix}-mapping.txt")
}
from "${buildDir}/intermediates/symbols/${variant.dirName}/R.txt"
from "${buildDir}/intermediates/symbol_list/${variant.dirName}/R.txt"
into destPath
rename { String fileName ->
fileName.replace("R.txt", "${newFileNamePrefix}-R.txt")
}
}
}
}
}
}
project.afterEvaluate {
//sample use for build all flavor for one time
if (hasFlavors) {
task(tinkerPatchAllFlavorRelease) {
group = 'tinker'
def originOldPath = getTinkerBuildFlavorDirectory()
for (String flavor : flavors) {
def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Release")
dependsOn tinkerTask
def preAssembleTask = tasks.getByName("process${flavor.capitalize()}ReleaseManifest")
preAssembleTask.doFirst {
String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 15)
project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release.apk"
project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-mapping.txt"
project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-R.txt"
}
}
}
task(tinkerPatchAllFlavorDebug) {
group = 'tinker'
def originOldPath = getTinkerBuildFlavorDirectory()
for (String flavor : flavors) {
def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Debug")
dependsOn tinkerTask
def preAssembleTask = tasks.getByName("process${flavor.capitalize()}DebugManifest")
preAssembleTask.doFirst {
String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 13)
project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug.apk"
project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-mapping.txt"
project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-R.txt"
}
}
}
}
}
}