Reputation: 2249
I am trying to convert our Android application to a gradle build. I have the project and it's libraries building successfully. I am now trying to create separate apks for our various environments (dev/test/prod have different urls for the restful services they consume).
In searching around, the best way that I feel to do this is with making different BuildConfig for each environment. This is what I tried:
import java.util.regex.Pattern
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:+'
}
}
apply plugin: 'android'
task('increaseVersionCode') << {
def manifestFile = file("AndroidManifest.xml")
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
def manifestText = manifestFile.getText()
def matcher = pattern.matcher(manifestText)
matcher.find()
def versionCode = Integer.parseInt(matcher.group(1))
def manifestContent = matcher.replaceAll("versionCode=\"" + ++versionCode + "\"")
manifestFile.write(manifestContent)
}
tasks.whenTaskAdded { task ->
if (task.name == 'generateReleaseBuildConfig') {
task.dependsOn 'increaseVersionCode'
}
}
dependencies {
compile 'com.android.support:support-v4:19.0.0'
compile files('libs/commons-io-2.4.jar',
'libs/google-play-services.jar',
'libs/gson-2.2.4.jar',
'libs/universal-image-loader-1.8.6.jar',
'libs/wakeful-1.0.1.jar')
compile project(':pulltorefresh_lib')
compile project(':edgeeffect_lib')
compile project(':viewpagerindicator_lib')
}
android {
buildToolsVersion "18.1.1"
compileSdkVersion "Google Inc.:Google APIs:18"
defaultConfig {
minSdkVersion 14
targetSdkVersion 18
}
buildTypes {
debug {
packageNameSuffix ".debug"
}
dev.initWith(buildTypes.debug)
dev {
buildConfigField "String", "URL_SEARCH", "\"https://dev-search.example.com\";"
buildConfigField "String", "URL_CONNECT", "\"https://dev-connect.example.com\";"
buildConfigField "String", "URL_SVC_NEWSLIST", "\"https://dev-mobilenews.example.com/newslist\";"
buildConfigField "String", "URL_SVC_NEWSDETAIL", "\"https://dev-mobilenews.example.com/newsdetail\";"
buildConfigField "String", "URL_SVC_REGISTERENDPOINTS", "\"https://dev-mobilenews.example.com/registerendpoints\";"
}
prod.initWith(buildTypes.release)
prod {
buildConfigField "String", "URL_SEARCH", "\"https://search.example.com\";"
buildConfigField "String", "URL_CONNECT", "\"https://connect.example.com\";"
buildConfigField "String", "URL_SVC_NEWSLIST", "\"https://mobilenews.example.com/newslist\";"
buildConfigField "String", "URL_SVC_NEWSDETAIL", "\"https://mobilenews.example.com/newsdetail\";"
buildConfigField "String", "URL_SVC_REGISTERENDPOINTS", "\"https://mobilenews.pdc-np-cf.lmig.com/registerendpoints\";"
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
}
}
The problem is that my BuildConfig.java doesn't seem to get the static variables injected, therefore I get errors similar to:
/Users/path/to/project/MainActivity.java:348: error: cannot find symbol
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.URL_SEARCH)));
^
symbol: variable URL_SEARCH
location: class BuildConfig
/Users/path/to/project/MainActivity.java:359: error: cannot find symbol
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.URL_CONNECT)));
^
symbol: variable URL_CONNECT
location: class BuildConfig
/Users/path/to/project/MainActivity.java:600: error: cannot find symbol
HttpPost httpPost = new HttpPost(BuildConfig.URL_SVC_REGISTERENDPOINTS);
^
symbol: variable URL_SVC_REGISTERENDPOINTS
location: class BuildConfig
/Users/path/to/project/service/AlarmNotificationService.java:145: error: cannot find symbol
String requestUrl = BuildConfig.URL_SVC_NEWSLIST + "?"
^
symbol: variable URL_SVC_NEWSLIST
location: class BuildConfig
/Users/path/to/project/service/NewsService.java:240: error: cannot find symbol
String requestUrl = BuildConfig.URL_SVC_NEWSLIST + "?"
^
symbol: variable URL_SVC_NEWSLIST
location: class BuildConfig
/Users/path/to/project/service/NewsService.java:530: error: cannot find symbol
HttpPost httpPost = new HttpPost(BuildConfig.URL_SVC_NEWSDETAIL);
^
symbol: variable URL_SVC_NEWSDETAIL
location: class BuildConfig
6 errors
My build/source/buildConfig/debug/com/.../BuildConfig.java file contains:
/**
* Automatically generated file. DO NOT MODIFY
*/
package com....;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String PACKAGE_NAME = "com.....debug";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 5;
}
What am I doing wrong?
Upvotes: 140
Views: 172554
Reputation: 21
Also watch out if you're creating an instance instead of calling the function
BuildConfigField("String", "BASE_URL", ""https"")
instead
buildConfigField("String", "BASE_URL", ""https"")
See the docs: https://developer.android.com/build/gradle-tips#share-custom-fields-and-resource-values-with-your-app-code
Upvotes: 0
Reputation: 81
In 2024+ and new scenarios with kotlin DSL
If you are using AGP 8.0+ BuildConfig feature is disable by default. See more Breaking changes: build option default values
In order to use the feature yo need to enable it on gradle.properties
file as below
android.defaults.buildfeatures.buildconfig = true
then Sync Project With Gradle Files, good look!
Testing on: Android Studio Iguana | 2023.2.1 Patch 2
Upvotes: 7
Reputation: 5665
Add this in app build.gradle
buildFeatures {
buildConfig = true
}
if using jet pack compose
buildFeatures {
compose = true
buildConfig = true
}
Upvotes: 28
Reputation: 5059
I had similar problem related to build types being setup using .initWith(someotherbuildtype)
, BuildConfig
was not being created properly. I had to switch to the parent build variant and build that first, then the build types that initWith the parent built fine.
Upvotes: 0
Reputation: 2853
You need to have this line in your gradle.properties
file:
android.defaults.buildfeatures.buildconfig=true
Hope this helps
Upvotes: 17
Reputation: 343
Very logical Answer if this is not heppening in compose
buildFeatures {
// The first line should already be in your project!
compose = true
buildConfig = true
}
This will now generate the file and you can use the BuildConfig.Debug in Application and everywhere.
Upvotes: 7
Reputation: 4423
In my case I had to enable buildConfig as a build feature.
android {
buildFeatures {
buildConfig true
}
}
Upvotes: 210
Reputation:
None of the solutions worked for me, I closed the project and opened again, and then rebuilt it because it clears all the generated stuff on closing and it worked, thank you.
Upvotes: 0
Reputation: 1029
For Android Studio Version
Android Studio Dolphin | 2021.3.1 Patch 1
Build #AI-213.7172.25.2113.9123335, built on September 30, 2022
Runtime version: 11.0.13+0-b1751.21-8125866 aarch64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
What was I trying to do?
I set up three build variants for the app module, I wanted BuildConfig to be changed every time I change the build variant, for that particular variable defined in the build.gradle (app) configurations.
What didn't work
I have tried all three methods, DIDN'T WORK AT ALL, to regenerate my BuildConfig for the build variant I was changing:
File > invalidate cache and restart
along with Build > Clean Project
& Build > Rebuild Project
Build > Make Project
aloneFile > Sync Project with Gradle Files
aloneWhat worked
Then I tried a combination which is surprisingly WORKING WELL:
Build > Make Project
File > Sync Project with Gradle Files
I hope it will work for that particular version I am not sure for other versions of Android Studio.
Thanks, @ravi, and @ibrokhim for partially answered for the case.
Upvotes: 6
Reputation: 4649
In my case there was an string field resValue "string", "app_name", "MyApp"
in strings.xml as well as in product flavours.
I did Invalidate Caches
then Rebuild
then android studion given the actual error of duplicate resources.
so Invalidate caches -> Rebuild -> Remove string resources which were already in buildconfigfield resvalue
worked for me
I was using Android Studio Bumblebee 2021.1.1
Upvotes: 0
Reputation: 1001
After trying everything, switching the build variant and selecting Build > Make Project worked for me.
Upvotes: 2
Reputation: 4636
In my case, I was expecting the BuildConfig for my new gradle module created. But forgot to add it as a dependency in app: module.
Upvotes: 0
Reputation: 81
I solve this problem as given below in this case Android studio will generate Build Config file itself
File -> Sync Project with Gradle Files
Upvotes: 6
Reputation: 1143
I did all the things in the answers but still didn't work. I solved my problem by changing the package name in the manifest.xml
file which still hadn't been updated :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android">
Upvotes: 3
Reputation: 157
Try to do
Build -> Clean Project
then do
Build - > Rebuild Project
If it doesn't work, try
File -> Invalidate Caches/Restart... -> Invalidate and Restart
then do
Build -> Clean Project
then do
Build - > Rebuild Project
Upvotes: 14
Reputation: 5865
first do
File -> Invalidate Caches/Restart... -> Invalidate and Restart
then do
Build -> Clean Project
then do
Build - > Rebuild Project
Upvotes: 69
Reputation: 169
If you are modifying your Environment Variables, and they are not reflecting correctly in Android studio try doing:
Build -> Clean Project
File -> Invalidate Caches/Restart... -> Invalidate and Restart
Upvotes: 4
Reputation: 457
In the project.ext.envConfigFiles array, ensure you set the debug to the right .env file you are using for development
Upvotes: 1
Reputation: 1317
Here is what fixed this for me:
File -> Invalidate Caches/Restart... -> Invalidate and Restart
Upvotes: 5
Reputation: 2429
Please, be sure that you are building "dev" or "prod" variant. There is no BuildConfig definition in default "debug" and "release" variant. In Android Studio, you can select current variant in bottom left corner:
To simplify your build.gradle file, you can define:
buildTypes {
debug {
buildConfigField "String", "URL_SEARCH", "\"https://dev-search.example.com\""
// etc.
}
release {
buildConfigField "String", "URL_SEARCH", "\"https://search.example.com\""
// etc.
}
}
and then just use default "debug" and "release" variants.
At last, delete semicolon (sign: ';') from the value of buildConfigField parameter.
Upvotes: 89
Reputation: 11921
I had same issue and fixed it like below:
buildConfigField 'String', 'BASE_URL', '"https://api.example.com"'
Upvotes: 58
Reputation: 673
Just in case that helps somebody else, in my case it was a missing import:
import uk.co.yourpackage.yourapp.BuildConfig;
Somehow, nowhere in the doc does it mention you need that include! Made me think it was automatically imported somehow but it ISN'T. not for me at least... So much time lost... Hope that helps another newbie like me!
Upvotes: 23