I followed instructions similar to these:
Android Library Gradle release JAR
However, I get the following error:
Could not find method isReleaseBuild() for arguments [] on project ':myProject'.
None of the examples I saw on Maven integration define this function, so I assumed it was built-in. However, I get this error with Gradle 1.12 and 2.1, and Android plugin 0.12.+ and 0.13.+
If it's not a built-in function, what is the best practice for defining it?
No. It is user defined, but seems to permeate examples because a lot of Gradle examples are copied.
This is the way I ended up defining it, so that I could pass in -PMAVEN_RELEASE_BUILD on the command line to turn on release builds.
def isReleaseBuild() {
return hasProperty("MAVEN_RELEASE_BUILD") && MAVEN_RELEASE_BUILD == "true";
}
Some people also like to define as version names ending in -SNAPSHOT. I do not prefer to do this, because I want to be able to choose whether to build a release or debug build without checking in a change to gradle.properties.
def isReleaseBuild() {
return !VERSION_NAME.contains("SNAPSHOT");
}
Related
I have converted my Gradle build scripts to the Kotlin DSL. Since I was starting with a small new project, everything went according to plan. When referencing more and more dependencies I wanted to put their version numbers in the script as constants, especially for those versions which are used in several places.
In my app/build.gradle.kts I have basically the following:
dependencies {
implementation("androidx.appcompat:appcompat:1.0.0")
...
}
Android Studio inspections tell me, that I should upgrade to 1.1.0. I changed it to
val appCompat = "1.0.0"
dependencies {
implementation("androidx.appcompat:appcompat:$appCompat")
...
}
but now I do not get that inspection hint anymore.
I compared my Kotlin script to what I find in the Sunflower reference project and found it to be working there. So, I experimented with defining extra-values with
extra.apply {
set("appCompat", "1.0.0")
}
implementation("androidx.appcompat:appcompat:${extra["appCompat"]}")
but got no inspection hint either.
To me, it seems that the inspection is broken using the Kotlin DSL. Do you agree or do you have a working setup for this?
In my environment inspection is broken also. So I used from third-party plugin and run it task in some interval for checking available update and manage it.
More details: https://github.com/jmfayard/gradle-dependencies-plugins
My android build is set to use a versionName and versionCode from a file in release mode. They are set to static values when not creating a release build to keep incremental builds working.
The relevant parts of the gradle file are:
android {
defaultConfig {
versionCode 1
versionName "1.0"
// SNIP...
}
applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
variant.versionCode = file('version-code.txt').text as int
variant.versionName = file('version.txt').text
}
}
// SNIP ...
}
Example contents of the version files could be:
version.txt: 0.7
version-code.txt: 7
This was done by following the Use static build config values with your debug build section in the recommended guidelines for keeping incremental builds working.
For example, using dynamic version codes, version names, resources, or any other build logic that changes the manifest file requires a full APK build every time you want to run a change—even though the actual change might otherwise require only a hot swap. If your build configuration requires such dynamic properties, then isolate them to your release build variants and keep the values static for your debug builds, as shown in the build.gradle file below.
However, we've found this has broken since upgrading to version 3 of the gradle plugin this no longer works. The Modifying variant outputs at build time may not work section of the gradle plugin 3.0.0 migration guide says:
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:
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.
There doesn't seem to be any alternative recommended in the migration guide. Is there another way this can be achieved?
UPDATE
Thanks to the answer from #nhoxbypass, changing my gradle file to contain following got things working again:
applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
variant.outputs.all { output ->
output.setVersionNameOverride(file('version.txt').text)
output.setVersionCodeOverride(file('version-code.txt').text as int)
}
}
}
The migration guide still works for simple tasks, such as changing the APK name during build time (at least worked for my project). However, more complicated tasks that involve accessing outputFile objects no longer work.
But if you need to try a workaround there is one existing before the 3.0 release, if anybody is looking for a solution, you can use:
output.setVersionCodeOverride(Integer.parseInt(buildTimeSmall()))
See: Unable to change project versionCode for different build types
I need to run some tasks that occur after an Android project's assemble* task finishes. In particular, these tasks need to know what was the output directory for all the compiled classes for a particular build variant. How do I retrieve the output directory for an assembleFlavor1Debug task?
My current workaround is something like this (although this workaround presents problems of its own, like not being able to find the assemble tasks even though it's been placed after the android configuration block):
android.buildTypes.all { theBuildType ->
android.productFlavors.all { theFlavor ->
String capitalizedType = ... //Type name with first letter capitalized
String capitalizedFlavor = ... //Flavor name with first letter capitalized
...
project.tasks["assemble${capitalizedType}${capitalizedFlavor}"].configure {
doLast {
project.ext.variantOutput = "build/intermediates/classes/${theFlavor.name}/${theBuildType.name}"
}
}
}
}
EDIT #1: I was able to fix my workaround. The major issue was that the Android assemble* tasks (assembleProdDebug, assembleProdRelease, etc.) were not yet created on the project, even though configuration was occurring after the Android configuration block. I was able to get the additional configuration on the assemble* tasks done by enclosing the entire code snippet above into a gradle.taskGraph.whenReady {...} block, but this did mean I lose out on the ability to continue configuring the dependency graph. Fortunately, not being to configure dependencies in my particular case was not a major loss; all I needed was the ability to record the last assembled build type and product flavor.
I'd also like to note that this behavior is with version 1.0.0 of the Android Gradle plugin. Although I have not checked, the absence of these Android tasks might not occur on newer versions of this plugin.
EDIT #2: So I've also tried version 1.3.0 of the Android Gradle plugin. I'd also like to note that this is the LIBRARY Android plugin, and not the application plugin (I suspect these missing assemble* tasks are not generated during project configuration for the application plugin as well, however).
You might want to try instead of wrapping the entire thing with gradle.taskGraph.whenReady try using afterEvaluate closure. The tasks should exist after the project is evaluated.
This means your closure would run at the end of the configuration phase and before the execution phase. At this time all tasks would have to be registered.
afterEvaluate { project ->
// do work on `Project` object just like normal
project.android.buildTypes.all { theBuildType ->
...
}
}
ref: https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#afterEvaluate(groovy.lang.Closure)
I just updated android Gradle plugin to 1.1.0 from 1.0.0, and I got this error:
No signature of method:
com.android.build.gradle.LibraryPlugin.getNdkFolder() is applicable
for argument types: () values: []
I tried to find diff of gradle plugin 1.0.0 to 1.1.0 but couldn't find anywhere online.
Seems like getNdkFolder method has been either changed or removed.
Is there a replacement ? Or any other way to get NdkFolder ?
I'm using that method like this,
def ndkDir = project.plugins.findPlugin ( 'com.android.library'
).getNdkFolder ()
I have also filed an issue against tools team in Android issue tracker: https://code.google.com/p/android/issues/detail?id=152810
Thank you !
You can get it like this:
plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()
The correct way - android.ndkDirectory
The change from android.plugin.ndkFolder to android.ndkDirectory was documented in the technical doc Migrating Gradle Projects to version 1.0.0. In addition you should update your android plugin to 2.3.0.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
}
}
The sdkFolder is internal and will likely stop working just like ndkFolder stopped working.
Regarding experimental branches
Search around, the plugin is mature enough you'll have trouble finding reasons to use experimental branches with the NDK.
There is some discussion about an Experimental version of the plugin breaking ndkDirectory which is the documented way to access this value after 1.1. If that changes in a released version I'll update my answer, in the mean time if running experimental plugins is your thing you can hack your way around this bug/feature using #Alex Cohn's answer.
I am using gradle 2.2.3 version. The think that worked for me:
def ndkDir = project.android.ndkDirectory
Ref. Link: https://code.google.com/p/android/issues/detail?id=152810
If in the build.gradle file you can probably use this now that the bug referenced has been marked fixed.
project.android.ndkDirectory
If you're in a custom Task or Plugin you'll want to use this
def androidPluginExtension = project.getExtensions().getByName("android");
// Use this for easily viewing the properties available in the extension.
androidPluginExtension.properties.each { Object key, Object value ->
logger.info("Extensionprop: ${key} ${value}")
}
String ndkDir = androidPluginExtension.getProperties().get("ndkDirectory");
System.out.println("Using ndk dir: ${ndkDir}");
But remember that the Android Plugin would have had to have been initialized, so this will always work in a Task's execute method, but it may not work if Gradle hasn't parsed the Android DSL yet during the Gradle Configuration phase.
As Michael Pardo mentioned, you can get it by
*
plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()
*
, In case you receive the following error:
Error:(9, 0) Plugin with id com.android.library has not been used.
You can use the applied plugin : 'com.android.application', therefore the final code will be :
def ndkDir = plugins.getPlugin('com.android.application').sdkHandler.ndkFolder
Can the pre-defined build-types somehow being renamed?
We use some custom build types that represent our internal staging setup (DEV/TEST/LIVE) and do not need the build in buildTypes (release/debug). Can these somehow being renamed or disabled when calling assemble?
import com.android.builder.core.BuilderConstants
android.variantFilter { variant ->
def build = variant.buildType.name
if (build == BuilderConstants.DEBUG || build == BuilderConstants.RELEASE) {
variant.setIgnore(true)
}
}
Note that the very first time importing the project Android Studio will pick any variant named debug else it will pick the first build variant in alphabetical order, which may not be the one you prefer as the default.
One solution i have come up with is to acctually just assemble the specifics and not run assemble. Which assembles all.
Try out gradle tasks to see the possibilites
But im looking for a better solution too, one that can be defined in the gradle.build file.