I am trying to use android build tools "com.android.tools.build:gradle:3.0.0-alpha4" in my project. In my build script I rename the output apk which worked fine in the past but does not seem to be supported any more.
android {
productFlavors {
flavorUnsigned {
applicationVariants.all { variant ->
variant.outputs.all { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace("app-flavorUnsigned-release-unsigned.apk", "DemoApp-${variant.versionName}($variant.versionCode).apk"))
def mappingFile = "${rootDir}/app/build/outputs/mapping/${getCurrentFlavor()}/release/mapping.txt"
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from "${mappingFile}"
into "${rootDir}/app/build/outputs/apk"
}
}
}
}
}
}
}
}
But now I am getting this error while building my project
Error:Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=flavorUnsignedDebug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
If you want to migrate your project to Android plugin 3.0.0-alpha1 or higher you should be doing the following :
API change in variant output:
// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
Read this page to learn how to apply the plugin and adapt your project to some breaking changes.
I solved this problem with this method. Create a new project and copy the contents of build.gradle to the existing project.
Related
After the Android Studio Update, there is error as below image,
enter image description here
here project build.gradle code,
debug {
minifyEnabled false
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace("app-debug.apk", "GoodWeather-debug-${variant.versionName}.apk"))
Modifying variant outputs at build time may not work
Using the Variant
API to manipulate variant outputs is broken with the new plugin. It
still works for simple tasks, such as changing the APK name during
build time, as shown below:
// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
Source: https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html
I would like to change the APK output folder and this is what I used to do:
applicationVariants.all { variant ->
variant.outputs.all {
def filePath = "${rootProject.rootDir.absolutePath}/apks/${variant.name}"
println("My Path: " + filePath)
outputFileName = filePath
}
}
However, it didn't work in Gradle 4.1 (Android studio 3.0 preview). Instead of generating the folder as the path above, it generated the above path inside old debug folder like image below:
Does anyone have a solution for this? Thanks.
This is a workaround to keep the output path same after upgrade to gradle 4.x.
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "../" + outputFileName
}
}
now apk is generated at platforms/android/build/outputs/apk/android-release.apk
From migration guide:
Using the Variant API to manipulate variant outputs is broken with the new plugin. It still works for simple tasks, such as changing the APK name during build time, as shown below:
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
However, more complicated tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times.
I had a similar issue, because I needed the output apk in a known folder and not in a folder depending on the computer user name. So I have fixed like this:
applicationVariants.all { variant ->
variant.outputs.all {
def apk = output.outputFile;
def newName = apk.name.replace(".apk", "-v" + variant.versionName + "-RELEASE.apk");
newName = newName.replace("-" + variant.buildType.name, "");
outputFileName = "./" + newName
}
}
With this I get the apk in:
".../outputs/apk/flavorName/buildTypeName/xxx.apk"
Hope it helps you.
I want to have a different versionCode for debug build type rather than the one in release build type. This used to work by using the configuration from below in Gradle Android plugin v2.3.2 (Gradle v3.3), but doesn't have any effect now in v3.0.0-alpha5 (Gradle v4.1-milestone-1). Any ideas as to what changed in the newest Gradle plugin that makes it ignore the variant.mergedFlavor.versionCode attribute?
buildTypes {
debug {
applicationIdSuffix ".debug"
versionNameSuffix "-" + buildTime()
android.applicationVariants.all { variant ->
if (variant.buildType.name != buildTypes.debug.name) return
variant.outputs.all {
outputFileName = "${archivesBaseName}-${variant.name}-v${variant.versionName}-signed.apk"
variant.mergedFlavor.versionCode = Integer.parseInt(buildTimeSmall())
}
}
}
}
As a workaround before the 3.0 release, if anybody is looking for a solution, you can use:
output.setVersionCodeOverride(Integer.parseInt(buildTimeSmall()))
Thanks to Jerome, reference: https://issuetracker.google.com/issues/63785806#comment6
From migration guide:
Using the Variant API to manipulate variant outputs is broken with the new plugin. It still works for simple tasks, such as changing the APK name during build time, as shown below:
// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
However, more complicated tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times. As an alternative, we will introduce new APIs to provide similar functionality.
Prior to Android plugin version 3.0.0-alpha4, I have been using the following for publishing different variants of my APKs to a specific file path:
def publish = project.tasks.create("publishAll")
android.applicationVariants.all { variant ->
def task = project.tasks.create("publish${variant.name}Apk", Copy)
task.from(variant.outputs[0].outputFile)
task.into(buildDir)
task.dependsOn variant.assemble
publish.dependsOn task
}
I originally got it from this answer from Xavier Ducrohet: Copying APK file in Android Gradle project
As of the new updates to Android Studio Preview which uses version 3.0.0-alpha4, variant.outputFile is deprecated. What is the new suggested way to achieve something like this?
EDIT:
Looks like there is no way to currently access the variant output file as pointed out here: https://developer.android.com/studio/preview/features/new-android-plugin-migration.html#variant_api
Looks like we'll have to wait until they introduce those apis
If you don't use abi splits next snippet works
project.afterEvaluate {
android.applicationVariants.all { variant ->
// create file where to copy
def backupFolder = rootProject.file("backup")
def backupFile = new File(backupFolder, String.format("%s_v%s.%d.apk", variant.flavorName, variant.versionName, variant.versionCode))
variant.outputs.all { output ->
Task copyAndRenameAPKTask = project.task("copyAndRename${variant.name.capitalize()}APK", type: Copy) {
from output.outputFile.getParent()
into backupFolder
include output.outputFileName
rename(output.outputFileName, backupFile.getName())
}
// if copyAndRenameAPKTask needs to automatically execute assemble before
copyAndRenameAPKTask.dependsOn(variant.assemble)
copyAndRenameAPKTask.mustRunAfter(variant.assemble)
// if assemble needs to automatically execute copyAndRenameAPKTask after
variant.assemble.finalizedBy(copyAndRenameAPKTask)
}
}
}
Is it possible to specify the filename of the generated *.apk through gradle? So that I automatically could get MyApp-1.0.0.apk instead of the default app-release.apk.
You can do this by adding the following line to your build.gradle file inside the android{...} part:
android.applicationVariants.all { variant ->
variant.outputFile = file("$project.buildDir/${defaultConfig.versionName}-${defaultConfig.versionCode}.apk")
}
Notes:
Everything inside the file(...) is arbitrary, of course
This code will output the *.apk to your project/module/build directory, no matter what path you've specified when Building the Signed APK.
The output-file will take the Name and Version-Code from your build.gradle file.
Android Studio may complain that it "cannot resolve symbol applicationVariants/defaultConfig" - ignore it. ;)
Got it working! Used this answer
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
}