如何在 gradle 中更改 Android 项目的混淆器映射文件名
How to change the proguard mapping file name in gradle for Android project
我有基于 gradle 的 android 项目,我想在为我的构建生成文件名后更改 mapping.txt 文件名。怎么做到的?
更新
如何在 build.gradle 中完成?因为我可以在那里访问我的口味和其他僵硬的东西,所以我想根据 flavor/build 变体版本创建映射文件名。
在你的 proguard-rules.pro 文件中使用这个命令:
-printmapping path/to/your/file/file_name.txt
文件将写入 {root}/path/to/your/file
部分,名称为 file_name.txt
。
如果你想为不同的口味设置不同的设置,你可以为它们定义许多proguard-rules
我发现了另一种想法,但我不确定它是否正确。
您可以在口味中定义您的路径:
productFlavors {
test1 {
applicationId "com.android.application.test"
project.ext."${name}Path" = 'path/one/mapp.txt'
}
test2 {
project.ext."${name}Path" = 'path/two/mapp.txt'
}
}
接下来您可以在 $asseble{variant.name.capitalize()}
任务之前定义新任务,如下所示:
android.applicationVariants.all { variant ->
def envFlavor = variant.productFlavors.get(0).name
def modifyProguardPath = tasks.create(name: "modifyProguardFor${variant.name.capitalize()}", type: Exec) {
def pathToMap = project."${envFlavor}Test1"
doFirst {
println "==== Edit start: $pathToMap ===="
}
doLast {
println "==== Edit end: $pathToMap ===="
}
executable "${rootDir}/utils/test.bash"
args pathToMap
}
project.tasks["assemble${variant.name.capitalize()}"].dependsOn(modifyProguardPath);
}
并且在脚本 ${root}/utils/test.bash
中 - 您可以修改 proguard-rules.pro
.
但我认为存在更好的解决方案。
非常感谢 Sergii Pechenizkyi 帮助我找到了这个好的解决方案。
要为每种风格实现混淆器映射文件的复制,我们可以为每种风格创建 "root" 任务 copyProguardMappingTask
和动态任务数
def copyProguardMappingTask = project.tasks.create("copyProguardMapping")
applicationVariants.all { variant ->
variant.outputs.each { output ->
...
if (variant.getBuildType().isMinifyEnabled()) {
def copyProguardMappingVariantTask = project.tasks.create("copyProguardMapping${variant.name.capitalize()}", Copy)
def fromPath = variant.mappingFile;
def intoPath = output.outputFile.parent;
copyProguardMappingVariantTask.from(fromPath)
copyProguardMappingVariantTask.into(intoPath)
copyProguardMappingVariantTask.rename('mapping.txt', "mapping-${variant.name}.txt")
copyProguardMappingVariantTask.mustRunAfter variant.assemble
copyProguardMappingTask.dependsOn copyProguardMappingVariantTask
}
}
}
之后我们应该 运行 在组装我们的项目后执行此任务。我使用 jenkins,我的任务选项看起来像
gradle clean assembleProjectName copyProguardMapping
它就像一个魅力。
更简单的解决方案。
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from variant.mappingFile
into "${rootDir}/proguardTools"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
自上次更新后 variant.mappingFile 不再可用。
(我用的是ProGuard 4.7版,AndroidStudio 2.0)
这是我的 build.gradle 文件的(部分):
import java.util.regex.Matcher
import java.util.regex.Pattern
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else
{
println "NO MATCH FOUND"
return "";
}
}
buildTypes {
release {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
minifyEnabled true
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk")
}
def mappingFile = "${rootDir}\app\build\outputs\mapping\${getCurrentFlavor()}\release\mapping.txt"
println("mappingFile: ${mappingFile}")
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from "${mappingFile}"
into "${rootDir}"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
}
debug {
minifyEnabled false
useProguard false
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk")
}
}
}
}
Pinhassi 的上述解决方案效果很好,并且符合最新的 Gradle 更改。虽然有几件事我必须改变:
- 模块名称是硬编码的 ("app"),这并不理想,因为在很多情况下(包括我的)情况并非如此。动态检测模块名比较好
- 映射文件也仅通过向后转义斜杠(“\”)符合 Windows 文件系统。如果您使用的是像 Linux 或 Mac 这样的 *NIX 系统,您需要将它们替换为前向非转义斜杠 ("/")
- 稍微更改了 .apk 文件的重命名以包含项目名称,并在末尾添加了一个 date/time 标记。
这是完成的代码:
import java.util.regex.Matcher
import java.util.regex.Pattern
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles 'proguard.cfg'
// Rename the apk file and copy the ProGuard mapping file to the root of the project
applicationVariants.all { variant ->
if (variant.getBuildType().name.equals("release")) {
def formattedDate = new Date().format('yyyyMMddHHmmss')
def projectName = ""
variant.outputs.each { output ->
def fullName = output.outputFile.name
projectName = fullName.substring(0, fullName.indexOf('-'))
// ${variant.name} has the value of "paidRelease"
output.outputFile = new File((String) output.outputFile.parent, (String) output.outputFile.name.replace(".apk", "-v${variant.versionName}-${formattedDate}.apk"))
}
def mappingFile = "${rootDir}/${projectName}/build/outputs/mapping/${getCurrentFlavor()}/release/mapping.txt"
println("mappingFile: ${mappingFile}")
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from "${mappingFile}"
into "${rootDir}"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
}
}
debug {
debuggable true
}
}
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else {
println "NO MATCH FOUND"
return "";
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast{
copy {
from variant.mappingFile
into "${rootDir}/mapping"
rename { String fileName ->
"mapping-${variant.name}-${new Date().format('yyyy_MM_dd')}.txt"
}
}
}
}
}
}
所有这些答案都使用复制重命名文件。
但是我不想移动文件,我只是想更改它的名称,同时记住构建类型和风格。
我根据此处其他海报的代码进行了一些修改。
由于 Minify 可能是假的,同时仍然使用混淆器,我只是检查文件是否存在。
下面的代码就完成了这一点。
android {
applicationVariants.all { variant ->
variant.assemble.doLast {
def mappingFolderUrl = "${project.buildDir.path}/outputs/mapping/"
if (variant.buildType.name) {
mappingFolderUrl += variant.buildType.name + "/"
}
if (variant.flavorName) {
mappingFolderUrl += variant.flavorName + "/"
}
def mappingFileUrl = mappingFolderUrl + "mapping.txt"
logger.lifecycle("mappingFile path: ${mappingFileUrl}")
File mappingFile = file(mappingFileUrl)
if (mappingFile.exists()) {
def newFileName = mappingFolderUrl + "mapping-${variant.name}.txt"
mappingFile.renameTo(newFileName)
}
}
}
}
注意
您也可以使用此代码来移动文件。
.renameTo() 方法需要一个完整路径,如果您更改路径,我想您有效地将文件移动到另一个地方。
这是 but renames mapping.txt to match the apk's name exactly including the app version name. I've combined this with code to name the APK with a version number as described in this answer 的变体。我不得不窥探 gradle 源代码以找到 $variant.baseName
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.company.app"
minSdkVersion 13
targetSdkVersion 21
versionCode 14 // increment with every release
versionName '1.4.8' // change with every release
archivesBaseName = "MyCompany-MyAppName-$versionName"
}
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
(new File(variant.mappingFile.parent, "$archivesBaseName-$variant.baseName-mapping.txt")).delete();
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/$archivesBaseName-$variant.baseName-mapping.txt")
}
}
}
}
对于 Android Studio Gradle 插件版本 4.1.0 及更高版本(自 2020 年 5 月左右开始)
此版本修复了以下警告:
WARNING: API 'variant.getMappingFile()' is obsolete and has been replaced with 'variant.getMappingFileProvider()'.
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
def mappingFileProvider = variant.getMappingFileProvider().get()
if (mappingFileProvider != null) {
try {
def mappingFiles = mappingFileProvider.getFiles()
for (mappingFile in mappingFiles) {
if (mappingFile != null && mappingFile.exists()) {
def newMappingFileName = "$archivesBaseName-$variant.baseName-$mappingFile.name"
project.logger.lifecycle("Renaming '${mappingFile.name}' to '${newMappingFileName}'")
def newMappingFile = new File(mappingFile.parent, newMappingFileName)
newMappingFile.delete()
mappingFile.renameTo(newMappingFile)
}
}
} catch (Exception ignored) {
project.logger.lifecycle("No mapping files found to rename")
}
}
}
}
对于 Android Studio Gradle 插件版本 3.3.0(2019 年 1 月)至 2020 年 5 月左右
这克服了以前 Android 3.0/Android Gradle 插件 3.0 弃用 BuildType.isMinifyEnabled()
和 gradle 插件弃用 variant.getAssemble( ).
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
def mappingFilename = "$archivesBaseName-$variant.baseName-mapping.txt"
(new File(variant.mappingFile.parent, mappingFilename)).delete()
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/" + mappingFilename)
}
}
}
variant.assemble
现已弃用,建议的解决方案结合了之前的修改:
archivesBaseName = "MyCompany-MyAppName-$versionName"
...
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
def mappingFilename = "$archivesBaseName-$variant.baseName-mapping.txt"
(new File(variant.mappingFile.parent, mappingFilename)).delete()
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/" + mappingFilename)
}
}
}
如果使用应用程序包 (aab) 而不是 apk,请将此添加到 之后的 android 部分:
afterEvaluate {
bundleRelease.doLast {
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
tasks.create(name: "renameMappingFile") {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
variant.mappingFile.renameTo(variant.mappingFile.parent + "/$variant.baseName-$versionName-${new Date().format('yyyy-MM-dd_HHmm')}-mapping.txt")
}
}
}
}
}
}
在最后一个例子中也将 bundleRelease
换成 assembleRelease
for apks。
更新:但是,如果您尝试直接对您的 phone 构建正常调试,那么最后一个将不起作用。错误:
无法为 org.gradle.api.Project.
类型的项目“:app”获取未知 属性 'bundleRelease'
适合我的完整解决方案
applicationVariants.all { variant ->
def variantType = variant.buildType.name
if (variantType == "release") {
variant.assemble.doLast {
def mappingFile = variant.mappingFile
mappingFile.renameTo(mappingFile.parent + "/mapping-${variant.name}.txt")
}
}
}
截至今天(2020 年 5 月) 以前使用 variant.mappingFile
的解决方案在新的 Android Gradle 插件中不再有效( Android Studio) 3.6 及更高版本。
而是 variant.mappingFile
returns null
并且日志中显示以下内容:
WARNING: API 'variant.getMappingFile()' is obsolete and has been replaced with 'variant.getMappingFileProvider()'.
我正在分享我的工作解决方案,它使用新的 api:
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
def mappingFiles = variant.getMappingFileProvider().get().files
for (file in mappingFiles) {
if (file != null && file.exists()) {
def nameMatchingApkFile = "$archivesBaseName-$variant.baseName-$file.name"
def newMappingFile = new File(file.parent, nameMatchingApkFile)
newMappingFile.delete() //clean-up if exists already
file.renameTo(newMappingFile)
}
}
}
}
请注意,由于我们使用的是 DexGuard,因此未使用 variant.getBuildType().isMinifyEnabled()。
上面的代码使 映射文件的 名称与 apk 的文件名相匹配。
以防万一,如果您需要更改 apk 名称 - 可以使用以下内容:
android {
defaultConfig {
//resulting apk will looks like: "archive base name" + -<flavour>-<buildType>.apk
archivesBaseName = "$applicationId-$versionName"
}
}
这是对我有帮助的解决方案:
compileSdkVersion 30
Java版本.VERSION_1_8
kotlin_version = '1.5.31'
com.android.tools.build:gradle:7.0.2
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
// Generating apk file for each flavour release build
variant.outputs.all {
outputFileName = "${variant.flavorName}-${variant.versionCode}.apk"
}
// Generating mapping file for each flavour release build
if (variant.getBuildType().isMinifyEnabled()) {
variant.assembleProvider.get().doLast {
def files = variant.getMappingFileProvider().get().getFiles()
for (file in files) {
if (file != null && file.exists()) {
def newName = "mapping-${variant.flavorName}-${variant.versionCode}.txt"
def newFile = new File(file.parent, newName)
newFile.delete()
file.renameTo(newName)
}
}
}
}
}
}
我有基于 gradle 的 android 项目,我想在为我的构建生成文件名后更改 mapping.txt 文件名。怎么做到的?
更新
如何在 build.gradle 中完成?因为我可以在那里访问我的口味和其他僵硬的东西,所以我想根据 flavor/build 变体版本创建映射文件名。
在你的 proguard-rules.pro 文件中使用这个命令:
-printmapping path/to/your/file/file_name.txt
文件将写入 {root}/path/to/your/file
部分,名称为 file_name.txt
。
如果你想为不同的口味设置不同的设置,你可以为它们定义许多proguard-rules
我发现了另一种想法,但我不确定它是否正确。
您可以在口味中定义您的路径:
productFlavors {
test1 {
applicationId "com.android.application.test"
project.ext."${name}Path" = 'path/one/mapp.txt'
}
test2 {
project.ext."${name}Path" = 'path/two/mapp.txt'
}
}
接下来您可以在 $asseble{variant.name.capitalize()}
任务之前定义新任务,如下所示:
android.applicationVariants.all { variant ->
def envFlavor = variant.productFlavors.get(0).name
def modifyProguardPath = tasks.create(name: "modifyProguardFor${variant.name.capitalize()}", type: Exec) {
def pathToMap = project."${envFlavor}Test1"
doFirst {
println "==== Edit start: $pathToMap ===="
}
doLast {
println "==== Edit end: $pathToMap ===="
}
executable "${rootDir}/utils/test.bash"
args pathToMap
}
project.tasks["assemble${variant.name.capitalize()}"].dependsOn(modifyProguardPath);
}
并且在脚本 ${root}/utils/test.bash
中 - 您可以修改 proguard-rules.pro
.
但我认为存在更好的解决方案。
非常感谢 Sergii Pechenizkyi 帮助我找到了这个好的解决方案。
要为每种风格实现混淆器映射文件的复制,我们可以为每种风格创建 "root" 任务 copyProguardMappingTask
和动态任务数
def copyProguardMappingTask = project.tasks.create("copyProguardMapping")
applicationVariants.all { variant ->
variant.outputs.each { output ->
...
if (variant.getBuildType().isMinifyEnabled()) {
def copyProguardMappingVariantTask = project.tasks.create("copyProguardMapping${variant.name.capitalize()}", Copy)
def fromPath = variant.mappingFile;
def intoPath = output.outputFile.parent;
copyProguardMappingVariantTask.from(fromPath)
copyProguardMappingVariantTask.into(intoPath)
copyProguardMappingVariantTask.rename('mapping.txt', "mapping-${variant.name}.txt")
copyProguardMappingVariantTask.mustRunAfter variant.assemble
copyProguardMappingTask.dependsOn copyProguardMappingVariantTask
}
}
}
之后我们应该 运行 在组装我们的项目后执行此任务。我使用 jenkins,我的任务选项看起来像
gradle clean assembleProjectName copyProguardMapping
它就像一个魅力。
更简单的解决方案。
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from variant.mappingFile
into "${rootDir}/proguardTools"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
自上次更新后 variant.mappingFile 不再可用。 (我用的是ProGuard 4.7版,AndroidStudio 2.0)
这是我的 build.gradle 文件的(部分):
import java.util.regex.Matcher
import java.util.regex.Pattern
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else
{
println "NO MATCH FOUND"
return "";
}
}
buildTypes {
release {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
minifyEnabled true
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk")
}
def mappingFile = "${rootDir}\app\build\outputs\mapping\${getCurrentFlavor()}\release\mapping.txt"
println("mappingFile: ${mappingFile}")
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from "${mappingFile}"
into "${rootDir}"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
}
debug {
minifyEnabled false
useProguard false
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk")
}
}
}
}
Pinhassi 的上述解决方案效果很好,并且符合最新的 Gradle 更改。虽然有几件事我必须改变:
- 模块名称是硬编码的 ("app"),这并不理想,因为在很多情况下(包括我的)情况并非如此。动态检测模块名比较好
- 映射文件也仅通过向后转义斜杠(“\”)符合 Windows 文件系统。如果您使用的是像 Linux 或 Mac 这样的 *NIX 系统,您需要将它们替换为前向非转义斜杠 ("/")
- 稍微更改了 .apk 文件的重命名以包含项目名称,并在末尾添加了一个 date/time 标记。
这是完成的代码:
import java.util.regex.Matcher
import java.util.regex.Pattern
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles 'proguard.cfg'
// Rename the apk file and copy the ProGuard mapping file to the root of the project
applicationVariants.all { variant ->
if (variant.getBuildType().name.equals("release")) {
def formattedDate = new Date().format('yyyyMMddHHmmss')
def projectName = ""
variant.outputs.each { output ->
def fullName = output.outputFile.name
projectName = fullName.substring(0, fullName.indexOf('-'))
// ${variant.name} has the value of "paidRelease"
output.outputFile = new File((String) output.outputFile.parent, (String) output.outputFile.name.replace(".apk", "-v${variant.versionName}-${formattedDate}.apk"))
}
def mappingFile = "${rootDir}/${projectName}/build/outputs/mapping/${getCurrentFlavor()}/release/mapping.txt"
println("mappingFile: ${mappingFile}")
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from "${mappingFile}"
into "${rootDir}"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}
}
}
debug {
debuggable true
}
}
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else {
println "NO MATCH FOUND"
return "";
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast{
copy {
from variant.mappingFile
into "${rootDir}/mapping"
rename { String fileName ->
"mapping-${variant.name}-${new Date().format('yyyy_MM_dd')}.txt"
}
}
}
}
}
}
所有这些答案都使用复制重命名文件。 但是我不想移动文件,我只是想更改它的名称,同时记住构建类型和风格。
我根据此处其他海报的代码进行了一些修改。 由于 Minify 可能是假的,同时仍然使用混淆器,我只是检查文件是否存在。
下面的代码就完成了这一点。
android {
applicationVariants.all { variant ->
variant.assemble.doLast {
def mappingFolderUrl = "${project.buildDir.path}/outputs/mapping/"
if (variant.buildType.name) {
mappingFolderUrl += variant.buildType.name + "/"
}
if (variant.flavorName) {
mappingFolderUrl += variant.flavorName + "/"
}
def mappingFileUrl = mappingFolderUrl + "mapping.txt"
logger.lifecycle("mappingFile path: ${mappingFileUrl}")
File mappingFile = file(mappingFileUrl)
if (mappingFile.exists()) {
def newFileName = mappingFolderUrl + "mapping-${variant.name}.txt"
mappingFile.renameTo(newFileName)
}
}
}
}
注意
您也可以使用此代码来移动文件。
.renameTo() 方法需要一个完整路径,如果您更改路径,我想您有效地将文件移动到另一个地方。
这是 $variant.baseName
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.company.app"
minSdkVersion 13
targetSdkVersion 21
versionCode 14 // increment with every release
versionName '1.4.8' // change with every release
archivesBaseName = "MyCompany-MyAppName-$versionName"
}
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
(new File(variant.mappingFile.parent, "$archivesBaseName-$variant.baseName-mapping.txt")).delete();
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/$archivesBaseName-$variant.baseName-mapping.txt")
}
}
}
}
对于 Android Studio Gradle 插件版本 4.1.0 及更高版本(自 2020 年 5 月左右开始)
此版本修复了以下警告:
WARNING: API 'variant.getMappingFile()' is obsolete and has been replaced with 'variant.getMappingFileProvider()'.
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
def mappingFileProvider = variant.getMappingFileProvider().get()
if (mappingFileProvider != null) {
try {
def mappingFiles = mappingFileProvider.getFiles()
for (mappingFile in mappingFiles) {
if (mappingFile != null && mappingFile.exists()) {
def newMappingFileName = "$archivesBaseName-$variant.baseName-$mappingFile.name"
project.logger.lifecycle("Renaming '${mappingFile.name}' to '${newMappingFileName}'")
def newMappingFile = new File(mappingFile.parent, newMappingFileName)
newMappingFile.delete()
mappingFile.renameTo(newMappingFile)
}
}
} catch (Exception ignored) {
project.logger.lifecycle("No mapping files found to rename")
}
}
}
}
对于 Android Studio Gradle 插件版本 3.3.0(2019 年 1 月)至 2020 年 5 月左右
这克服了以前 Android 3.0/Android Gradle 插件 3.0 弃用 BuildType.isMinifyEnabled()
和 gradle 插件弃用 variant.getAssemble( ).
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
def mappingFilename = "$archivesBaseName-$variant.baseName-mapping.txt"
(new File(variant.mappingFile.parent, mappingFilename)).delete()
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/" + mappingFilename)
}
}
}
variant.assemble
现已弃用,建议的解决方案结合了之前的修改:
archivesBaseName = "MyCompany-MyAppName-$versionName"
...
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
def mappingFilename = "$archivesBaseName-$variant.baseName-mapping.txt"
(new File(variant.mappingFile.parent, mappingFilename)).delete()
variant.mappingFile.renameTo(variant.mappingFile.parent +
"/" + mappingFilename)
}
}
}
如果使用应用程序包 (aab) 而不是 apk,请将此添加到 之后的 android 部分:
afterEvaluate {
bundleRelease.doLast {
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
tasks.create(name: "renameMappingFile") {
if (variant.mappingFile != null && variant.mappingFile.exists()) {
variant.mappingFile.renameTo(variant.mappingFile.parent + "/$variant.baseName-$versionName-${new Date().format('yyyy-MM-dd_HHmm')}-mapping.txt")
}
}
}
}
}
}
在最后一个例子中也将 bundleRelease
换成 assembleRelease
for apks。
更新:但是,如果您尝试直接对您的 phone 构建正常调试,那么最后一个将不起作用。错误:
无法为 org.gradle.api.Project.
类型的项目“:app”获取未知 属性 'bundleRelease'适合我的完整解决方案
applicationVariants.all { variant ->
def variantType = variant.buildType.name
if (variantType == "release") {
variant.assemble.doLast {
def mappingFile = variant.mappingFile
mappingFile.renameTo(mappingFile.parent + "/mapping-${variant.name}.txt")
}
}
}
截至今天(2020 年 5 月) 以前使用 variant.mappingFile
的解决方案在新的 Android Gradle 插件中不再有效( Android Studio) 3.6 及更高版本。
而是 variant.mappingFile
returns null
并且日志中显示以下内容:
WARNING: API 'variant.getMappingFile()' is obsolete and has been replaced with 'variant.getMappingFileProvider()'.
我正在分享我的工作解决方案,它使用新的 api:
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
def mappingFiles = variant.getMappingFileProvider().get().files
for (file in mappingFiles) {
if (file != null && file.exists()) {
def nameMatchingApkFile = "$archivesBaseName-$variant.baseName-$file.name"
def newMappingFile = new File(file.parent, nameMatchingApkFile)
newMappingFile.delete() //clean-up if exists already
file.renameTo(newMappingFile)
}
}
}
}
请注意,由于我们使用的是 DexGuard,因此未使用 variant.getBuildType().isMinifyEnabled()。
上面的代码使 映射文件的 名称与 apk 的文件名相匹配。
以防万一,如果您需要更改 apk 名称 - 可以使用以下内容:
android {
defaultConfig {
//resulting apk will looks like: "archive base name" + -<flavour>-<buildType>.apk
archivesBaseName = "$applicationId-$versionName"
}
}
这是对我有帮助的解决方案:
compileSdkVersion 30
Java版本.VERSION_1_8
kotlin_version = '1.5.31'
com.android.tools.build:gradle:7.0.2
buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' applicationVariants.all { variant -> // Generating apk file for each flavour release build variant.outputs.all { outputFileName = "${variant.flavorName}-${variant.versionCode}.apk" } // Generating mapping file for each flavour release build if (variant.getBuildType().isMinifyEnabled()) { variant.assembleProvider.get().doLast { def files = variant.getMappingFileProvider().get().getFiles() for (file in files) { if (file != null && file.exists()) { def newName = "mapping-${variant.flavorName}-${variant.versionCode}.txt" def newFile = new File(file.parent, newName) newFile.delete() file.renameTo(newName) } } } } } }