I'm trying to use Gradle to set app's name. Please, look at this snippet of build.gradle:
android {
...
defaultConfig {
...
versionCode getVersionCode()
versionName getVersionName()
...
}
...
}
...
int getVersionCode() {
return 1
}
def getVersionName() {
return "1.0"
}
Android Studio says
'versionCode' cannot be applied to 'java.lang.Integer'
'versionName' cannot be applied to 'java.lang.String'
and when I install the app on a device it has no versionCode and versionName at all.
The problem is clear to me but I don't know how to solve it.
Please advice.
It doesn't resolve your issue, but it can be a different solution.
You can use gradle.properties inside your root project and define:
VERSION_NAME=1.2.1
VERSION_CODE=26
Then in your build.gradle you can use:
versionName project.VERSION_NAME
versionCode Integer.parseInt(project.VERSION_CODE)
EDITED
In order to define your app version dynamically, specify a custom method with def and call it, as such:
def computeVersionName() {
return "2.0"
}
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
versionCode 12
versionName computeVersionName()
minSdkVersion 16
targetSdkVersion 16
}
}
See here for more.
Make sure not to use function names that could conflict with existing getters in the given scope. For instance, defaultConfig { ... } calling getVersionName() will automatically use the getter defaultConfig.getVersionName() instead of the custom method.
Here is a build.gradle that I am using based on ideas from JakeWharton :
apply plugin: 'com.android.application'
def versionMajor = 1
def versionMinor = 2
def versionPatch = 0
def gitVersion() {
def counter = 0
def process = "git rev-list master --first-parent --count".execute()
return process.text.toInteger()
}
repositories {
mavenCentral()
}
android {
compileSdkVersion 19
buildToolsVersion '19.1.0'
defaultConfig {
applicationId 'my.project.com'
minSdkVersion 14
targetSdkVersion 19
versionCode gitVersion()
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
}
....
}
First of all - you are calling the inner getter., hence you have nulls.
versionCode property is accessed by getVersionCode().
versionName property is accessed by getVersionName()
So you get null and assign null... - remember, you are inside defaultConfig scope, hence Gradle will use the closest gerVersionCode() function.
There is a cleaner way to make it in newer Android Gradle (4.1.2).
Usually, those values are separated to the new file.
Firstly, you should use closures, not functions.
Fuction:
def myFunction() {
}
Closure:
myClosure = {
}
Also, you can extend ext scope (it is used to store all custom project-wide Gradle properties, this is a great place for it!) with your closure!
Remember not to name your functions 'getVersionName' 'getVersionCode'
Create a file config.gradle:
ext {
appSetup = [
majorVersion : 1,
minorVersion : 0,
patchVersion : 0
]
getAppVersionCode = { appSetup.majorVersion * 10000 + appSetup.minorVersion * 100 + appSetup.patchVersion }
getAppVersionName = { "${appSetup.majorVersion}.${appSetup.minorVersion}.${appSetup.patchVersion}" }
In build.gradle:
// applies bloc
apply from: 'config.gradle'
android {
versionCode getAppVersionCode()
versionName getAppVersionName()
If you use a gradle.properties file to store shared build versions, make sur to use the toInteger() function for the version code, compiled/min and target sd versions.
See this post for more information: https://medium.com/#ali.muzaffar/gradle-configure-variables-for-all-android-project-modules-in-one-place-5a6e56cd384e#.yl1x0ziqe
Related
I tried to immigrate a deprecated flutter application, but after following the steps provided on github im getting this
C:\Users\personal\AndroidStudioProjects\flash-chat-flutter\android\app\src\main\AndroidManifest.xml:10:9-42 Error:
Attribute application#name at AndroidManifest.xml:10:9-42 requires a placeholder substitution but no value for <applicationName> is provided.
C:\Users\personal\AndroidStudioProjects\flash-chat-flutter\android\app\src\debug\AndroidManifest.xml Error:
Validation failed, exiting
I ran into this as well. In my case it was because I had set manifestPlaceholders the "usual" way, by assigning with = (as all examples seem to do):
In android/app/build.gradle:
android {
⋮
defaultConfig {
applicationId "com.example.my_app"
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
// This right here!
manifestPlaceholders = [someKey: "#string/some_value"]
}
⋮
}
It turns out that multidex support introduced the need to dynamically determine the application name, hence the ${applicationName} placeholder in the manifest.
That value is determined by the Flutter Gradle plugin here by means of manifestPlaceholders, so if you replace the value by reassigning it then you will run into this issue. The fix is simple: add your values to the existing ones with += like so:
android {
⋮
defaultConfig {
applicationId "com.example.my_app"
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
// Fixed now! Note the plus!
manifestPlaceholders += [someKey: "#string/some_value"]
}
⋮
}
I got the same error:
You need to add this to your build.gradle (YourFlutterProject/android/app/build.gradle)
buildTypes {
release {
manifestPlaceholders = [applicationName: "android.app.Application"]
}
debug {
manifestPlaceholders = [applicationName: "android.app.Application"]
}
build{
manifestPlaceholders = [applicationName: "android.app.Application"]
}
}
Based on this answer, I realized that we can use Gradle variables (I'm not familiar with Gradle of course, so excuse my terminology) to make some consistencies across many Android projects.
For example, I want to change the android closure configuration from this:
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
}
To this:
android {
compileSdkVersion configurationVariables.sdk
buildToolsVersion configurationVariables.buildToolsVersion
defaultConfig {
minSdkVersion configurationVariables.minSdk
targetSdkVersion configurationVariables.targetSdk
versionCode 1
versionName "1.0"
}
}
However, I get this error:
Error:(5, 0) startup failed: build file
'path_to_android\build.gradle': 5: Statement labels may not be used in
build scripts. In case you tried to configure a property named
'buildToolsVersion', replace ':' with '=' or ' ', otherwise it will
not have the desired effect. # line 5, column 24.
buildToolsVersion: configurationVariables.buildToolsVersion
How can I use variables to centralize my build configuration across projects and modules?
Update: I'm defining my configurationVariables as follow:
ext {
configurationVariables = [
sdk = 27,
buildToolsVersion = "27.0.3",
minSdk = 16,
targetSdk = 27
]
}
I write this in a config.gradle file and use apply from to import it in the build.gradle of the root project to apply it on all subprojects.
your config file structure store value as a varible. Generally this structure is use to store variable.Your config file should be like this
ext {
sdk = 27
buildToolsVersion = "27.0.3"
minSdk = 16
targetSdk = 27
}
and you use this variable as
compileSdkVersion sdk
buildToolsVersion buildToolsVersion
I haven't use array for storing this variable but as you given in another answer link they store array variable with colon(:) and you are directly storing values. I am not sure but try to use colon like this if you want to use an array :
ext {
configurationVariables = [
sdk : 27,
buildToolsVersion : "27.0.0",
minSdk : 16,
targetSdk : 27
]
}
I have gradle project, the simplified android part of the build.gradle of which looks like this:
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
def mapPlacesApiKeys = [dev_1: [api_key: 'key_1', sender_id: 'sender_id_1'], dev_9: [api_key: 'key_2', sender_id: 'sender_id_2'],prod_1: [api_key: 'key_3', sender_id: 'sender_id_3']]
if (project.hasProperty('env')) {
if (mapPlacesApiKeys.get(env) == null) {
def keyset = mapPlacesApiKeys.keySet()
throw new StopExecutionException("Value '$env' is not a valid environment value. Valid environments: $keyset. You can set an environment by passing the -Penv=<env> parameter to your gradle build.")
}
}
buildConfigField "String", "SENDER_ID", "\"${mapPlacesApiKeys.get(env).get('sender_id')}\""
manifestPlaceholders = [maps_places_api_key: mapPlacesApiKeys.get(env).get('api_key')]
}
}
When I run this from the command line I run it with an environment parameter e.g. -Penv=dev_1. This does 2 things as you can see in the script:
a) Replaces in the androidmanifest the value "maps_places_api_key" with the actual key of the specified environment
b) Adds a String with the SENDER_ID in the BuildConfig java class.
This works fine from the command line. My problem is that in intellij (or android studio, should be the same) when I import the gradle project I get the following error:
-Penv is missing. You can set an environment by passing the -Penv=<env> parameter to your gradle build.
Which is the exception that I am declaring. So my question is how can I structure this code so that the IDE doesn't try to run it when it's loading the project.
Note that I don't want to replace the "env" parameter with any kinds of flavors or buildTypes, as there's about 15 different environments and it's gonna be a mess, but if there's another suggestion that comes in to your mind feel free to share it.
android{
defaultConfig {
applicationId 'com.xx'
minSdkVersion 14
}
productFlavors {
def path="./channel.txt"
file(path).eachLine { line->
def words = line.split(':')
def name = words[0]
def sender_id = words[1]
def api_key = words[2]
"$name" {
buildConfigField "String", "SENDER_ID", sender_id
manifestPlaceholders = [maps_places_api_key: api_key]
}
}
}
}
I want to override the Android versionCode property from an applied script file (as to keep the app script clean). This is what i am doing currently (i omitted anything unrelated):
build.gradle:
apply from: 'ci.gradle'
android {
defaultConfig {
versionCode 1
}
}
ci.gradle:
project.afterEvaluate {
project.android.defaultConfig.versionCode = 3434
}
But i still end up with versionCode being 1... What i am doing wrong?
I learned that it can be solved by moving apply from: 'ci.gradle' after the android block:
build.gradle:
android {
defaultConfig {
versionCode 1
}
}
apply from: 'ci.gradle'
ci.gradle:
android.defaultConfig.versionCode = 3434
After updating Android Studio to 1.0, I see this error:
Error: Library projects cannot set applicationId. applicationId is set
to 'com.super.app' in default config.
I updated the Gradle plugin as suggested but I did not understand how to fix this.
Based on this info:
ApplicationId in Library Projects
You cannot use applicationId to customize the package of a library project. The package name has to be fixed in library projects (and specified as packageName in the manifest). The Gradle plugin did not enforce this restriction earlier.
Removing applicationId variable from the library's build.gradle file should resolve the issue.
Thanks to Joel for his correct answer: I need to remove only 1 line from te .gradle file:
defaultConfig {
applicationId "com.super.app" <---- remove this line
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
becomes
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
and my AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.super.app">
...
This is the right solution if you don't need to rename the package name of your app. To rename it you need to use "flavours":
android {
...
productFlavors {
flavor1 {
applicationId 'com.super.superapp'
}
}
Libraries can't set applicationId and if you are working in a multi-module project and picking up flavors from a separate file , none of the above answers will work. For a modularized app, you need the following steps -
Create a flavors.gradle file in project root directory
ext.flavorConfig = { // 1
flavorDimensions "pricing"
productFlavors {
free {
dimension "pricing"
ext.myApplicationIdSuffix = '.free' // 2
}
paid {
dimension "pricing"
ext.myApplicationIdSuffix = '.paid'
}
}
productFlavors.all { flavor -> // 3
if (flavor.hasProperty('myApplicationIdSuffix') && isApplicationProject()) {
flavor.applicationIdSuffix = flavor.myApplicationIdSuffix
}
}
}
def isApplicationProject() { // 4
return project.android.class.simpleName.startsWith('BaseAppModuleExtension')
}
In 1 we export a closure so that we can use it in our modules’ build.gradle files.
In 2 we define a custom myApplicationIdSuffix property. We cannot simply have applicationIdSuffix as it is not possible to use it in library modules (build would fail if you did).
In 3 we iterate over created flavors and set applicationIdSuffix if we detect that it’s an application module only.
4 is a way to check where this closure is being used.
All that’s left is to use this closure in our modules’ build.gradle files. E.g. in application module this would look like this:
apply plugin: 'com.android.application'
apply from: "${rootProject.projectDir}/flavors.gradle"
android {
// other config...
with flavorConfig
}
If this isn't clear, you can check out this article for better understanding.
Just incase it helps some one :
When i imported an eclipse project into android studio,i got an error ::
"Error:Application and test application id cannot be the same"
Strange though,but i looked into the build.gradle and found the two placeholders,one for the application and other for testapplication.
I removed the testApplicationId from that as is suggested in this post and this helped me resolve the issue.
Note: This explaination is not related to the errors posted in this question,but might help someone who is getting a similar error.
You cannot define applicationId for your lib.
But incase you want to use an identifier in your build file, which will give you, your library package name, you can define a variable for the module and then use the value as required.
eg : Library's build.gradle
apply plugin: 'com.android.library'
def libraryGroupId = 'com.google.example'
def libraryArtifactId = project.getName()
def libraryVersion = '1.1'
Also, you can use the value below as needed in your build file itself in lib.
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "$libraryVersion"
resValue "string", "Library", libraryGroupId"
}
}