In my Flutter mobile app have two flavors with separate res folders for each. I have added sourceSet in build.gradle file, but at runtime the running flavor does not show the relavant resource from flavor folder, instead the main folder resources.
Folder structure as below.
src
|
flavor1
------res(with sub folders)
|
flavor2
------res(with sub folders)
|
main
------res(with sub folders)
build.gradle file changes.
android {
sourceSets {
main {
java.srcDirs += 'src/main/kotlin'
res.srcDirs = ['src/main/res']
manifest.srcFile 'src/main/AndroidManifest.xml'
}
flavor1 {
res.srcDirs = [
'src/flavor1/res/drawable-hdpi',
'src/flavor1/res/drawable-ldpi',
'src/flavor1/res/drawable-mdpi',
'src/flavor1/res/drawable-v21',
'src/flavor1/res/drawable-xhdpi',
'src/flavor1/res/drawable-xxhdpi',
'src/flavor1/res/drawable-xxxhdpi',
'src/flavor1/res/drawable',
'src/flavor1/res/mipmap-hdpi',
'src/flavor1/res/mipmap-mdpi',
'src/flavor1/res/mipmap-xhdpi',
'src/flavor1/res/mipmap-xxhdpi',
'src/flavor1/res/mipmap-xxxhdpi',
'src/flavor1/res/raw',
'src/flavor1/res/values',
'src/flavor1/res'
]
manifest.srcFile 'src/flavor1/AndroidManifest.xml'
}
flavor2 {
res.srcDirs = [
'src/flavor2/res/drawable-hdpi',
'src/flavor2/res/drawable-ldpi',
'src/flavor2/res/drawable-mdpi',
'src/flavor2/res/drawable-v21',
'src/flavor2/res/drawable-xhdpi',
'src/flavor2/res/drawable-xxhdpi',
'src/flavor2/res/drawable-xxxhdpi',
'src/flavor2/res/drawable',
'src/flavor2/res/mipmap-hdpi',
'src/flavor2/res/mipmap-mdpi',
'src/flavor2/res/mipmap-xhdpi',
'src/flavor2/res/mipmap-xxhdpi',
'src/flavor2/res/mipmap-xxxhdpi',
'src/flavor2/res/raw',
'src/flavor2/res/values',
'src/flavor2/res'
]
manifest.srcFile 'src/flavor2/AndroidManifest.xml'
}
}
// Because of flavors and multiple res folders.
afterEvaluate {
android.applicationVariants.all { variant ->
tasks.named("generate${variant.name.capitalize()}ResValues")
.configure { task ->
task.outputs.upToDateWhen {false}
}
}
}
flavorDimensions "app"
productFlavors {
flavor1 {
dimension "app"
applicationIdSuffix ""
}
flavor2 {
dimension "app"
applicationIdSuffix ".flavor2"
}
}
}
Running the flavor2 app still refers to main resources is the issue. I want the respective flavor to refer only the given flavor specific resource folder in runtime.
sourceSet in not necessary, just add product flavors within app/build.gradle, folders structure is ok, at compilation time all resources are merged and main folder resources are overridden with flavor resources
just run next command
flutter run --flavor flavor2
more info here: https://medium.com/#salvatoregiordanoo/flavoring-flutter-392aaa875f36
Related
I have an application with below source sets and flavors:
flavorDimensions "brand"
productFlavors {
flavor1 {
dimension "brand"
sourceSets {
main {
manifest.srcFile "src/main/flavor1/AndroidManifest.xml"
resources.srcDirs = ['src/flavor1/']
}
}
}
flavor2 {
dimension "brand"
sourceSets {
main {
manifest.srcFile "src/main/flavor2/AndroidManifest.xml"
resources.srcDirs = ['src/flavor2/']
}
}
}
flavor3 {
dimension "brand"
sourceSets {
main {
manifest.srcFile "src/main/flavor3/AndroidManifest.xml"
resources.srcDirs = ['src/flavor3/']
}
}
}
My application is such that 99% of layouts and classes are the same. E.g. only layout file main_activity.xml is different among flavors but the other 20~30 layout files are completely the same. I don't want to copy these 20~30 in three different flavor source set. Are there any ways to share them among three flavors and if a file was present in source set, it overrides the share files? (Such as want android does for drawable and drawble-hdpi , ...)?
So I don't want to have
Unless I have misunderstood the question, you could solve the issue by changing build.gradle like this:
productFlavors {
flavor1 {
dimension "brand"
}
flavor2 {
dimension "brand"
}
//...
}
and structuring your app module like this:
/src
/main
/flavor1
/flavor2
...
and placing all common files(source, resources) in main and the custom/specific files in the flavorX folders which will cause gradle to replace the identically named files in main when each flavor is built.
This question already has answers here:
Reference different assets based on build flavor
(2 answers)
Closed 3 years ago.
I can not get product flavours working. I have this gradle
apply plugin: 'com.android.application'
android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 24
compileSdkVersion 27
}
signingConfigs {
release {
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
signingConfig signingConfigs.release
}
}
repositories {
maven { url "https://jitpack.io" }
}
flavorDimensions "dim1", "dim2", "dim3"
productFlavors {
flavor1 {
dimension "dim1"
applicationId "com.example.dim1.app"
}
flavor3 {
dimension "dim2"
applicationId "com.example.dim2.app"
}
flavor3 {
dimension "dim3"
applicationId "com.example.dim3.app"
}
}
sourceSets {
flavor1 {
java.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/java/"]
manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example1/AndroidManifest.xml"
assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example1/assets/"]
resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example1/res/"]
}
flavor2 {
java.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/java/"]
manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example2/AndroidManifest.xml"
assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example2/assets/"]
resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example2/res/"]
}
flavor3 {
java.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/java/"]
manifest.srcFile "W:/android-studio-projects/sharedid/app/src/example3/AndroidManifest.xml"
assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/example3/assets/"]
resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/example3/res/"]
}
}
}
dependencies {
api 'com.google.android.gms:play-services-maps:15.0.0'
api 'com.google.android.gms:play-services-location:15.0.0'
api 'com.android.support:appcompat-v7:27.1.1'
api 'com.github.PhilJay:MPAndroidChart:v2.0.8'
}
...
When I got to "Build | Select variant" I can only select
Module:app
Build Variant:flavor1Flavor2Flavor3Debug,flavor1Flavor2Flavor3Release
I would have liked to get
the following build variants: flavor1Debug,flavor2Debug,flavor3Debug,flavor1Release,flavor2Release,flavor3Release
I have tried "File | Sync project with gradle file"
...
I get this error
Caused by: java.lang.RuntimeException: Cannot read packageName from
W:\android-studio-projects\sharedid\app\src\main\AndroidManifest.xml
I have tried to both
have no such file (hoping it would take the product flavor one?)
have the "main" manifest only define shared stuff between all product flavors
Just try like below,
flavorDimensions "dim1"
productFlavors {
flavor1 {
dimension "dim1"
applicationId "com.example.dim1.app"
}
flavor3 {
dimension "dim1"
applicationId "com.example.dim2.app"
}
flavor3 {
dimension "dim1"
applicationId "com.example.dim3.app"
}
}
For more details about build variant see this link
I think there are two unrelated problems :
Currently you have 2 build types (the automatically created debug and release) and 3 dimensions (dim1, dim2 and dim3), each one having 1 variant (flavor1 for dim1, flavor2 for dim2, ...)
this gives at most :
2 * 1 * 1 * 1 = 2 combinations
You should switch to 2 build types and 1 dimension (say dim1) having 3 variants (flavor1, flaver2 and flavor3) to have :
2 * 3 = 6 apks
You should have a main manifest. Unlike other resources the manifest is not simply overriden but merged from multiple sources (see Merge Multiple Manifest Files for more details).
It should at least contains a package name (possibly different from the final applicationId(s)) as explained by this note from Configure Product Flavors :
Note : You still need to specify a package name using the package attribute
in the main/ manifest file. You must also use that package name in
your source code to refer to the R class, or resolve any relative
activity or service registration. This allows you to use applicationId
to give each product flavor a unique ID for packaging and
distribution, without having to change your source code.
I would have liked to get
the following build variants:
flavor1Debug,flavor2Debug,flavor3Debug,flavor1Release,flavor2Release,flavor3Release
For this, you need to define the same dimension for all flavors.
I get this error
Caused by: java.lang.RuntimeException: Cannot read packageName from
W:\android-studio-projects\sharedid\app\src\main\AndroidManifest.xml
You get this error because the path is not reachable.
Just think, how can app find W: when it is running?
So, you need to use a relative path here.
Also from official documentation (https://developer.android.com/studio/build/build-variants#configure-sourcesets):
If you have sources that are not organized into the default source set
file structure that Gradle expects, as described above in the section
about creating source sets, you can use the sourceSets block to change
where Gradle looks to gather files for each component of a source set.
You don't need to relocate the files; you only need to provide Gradle
with the path(s), relative to the module-level build.gradle file,
where Gradle should expect to find files for each source set component
I have been stuck on this for a day now. I created 2 flavors for my project and added them under the buildtype in android in build.gradle. I then created a res folder for both and changed the icons for each. When I run the project for any of the variants, it is showing the icon from the project.
My project structure in as follows
[project]
[app]
src
main
res
mipmap
flavor1
flavor2
res
mipmap
and my build.gradle is
productFlavors {
flavor1 {
applicationId "abc"
}
flavor2 {
applicationId "abc"
}
}
sourceSets {
flavo1 {
res.srcDirs = ['src/flavor1/res']
}
flavor2 {
res.srcDirs = ['src/flavor2/res']
}
}
PS: nvm the naming
You should remove the icon from main and leave it only in flavor1 and flavor2 directories.
Also check the names of the flavors in the build.gradle, I think it should be flavor1 instead of flavo1 and flavor2 instead of staging.
Another note, sourceSets definition is not required, standard res directories inside flavors' directories will be used automatically.
My project contains multiple flavor and main folder which contains common logic when i build project with a specific flavor gradle use values from main folder even if that value is present in that flavor
Please help
Project structure
MainProject
src
main (main project)
java
flavor1
java/Appconstant.java
flavor2
java/Appconstant.java
...
build.gradle file
productFlavors {
flavor1 {
applicationId <pkgName>
versionCode 15
versionName "2.4.0"
}
flavor2 {
applicationId <pkgName>
versionCode 1
versionName "1.0.0"
}
}
sourceSets {
flavor1 {
java.srcDirs = ['src/flavor1/java']
res.srcDirs = ['src/flavor1/res']
}
flavor2 {
java.srcDirs = ['src/flavor2/java']
res.srcDirs = ['src/flavor2/res']
}
}
EDIT
modified project structure as per suggestion but now flavor class in not visible in Main
I'm trying to make a batch file with some commands, so once it runs, it will change some strings in the files, build the project and generate the APK signed.
The strings I need to change are:
- The package name (com.company.project)
- Some images (like icons, splash screen, ...)
- some irrelevant string that are specific from the app.
For the last 2 things I know how to do it, but for the package name I feel there is something wrong about just find and replace all the occurrences of that string in the root folder of the app (including subdirectories).
Is there any way or command that ant has for doing this?
Also I ran into an issue while running the command ant release.
I went to my root folder, ran the command and it gets errors.
So I had to go to eclipse, clean the project and let it autobuild (with no generation of APK since it does that when you try to run it on a device) so at that point my bin folder just contains the folders: classes, dexedLibs, res and the Manifest.xml file.
Then I can go to the CL and run ant release.
So is there any way to do all this from CL? Something like clean and build so I can run ant release command after with no issues?
NOTE: for find and replace I use an .exe called FNR that does the job
EDIT:
I'm now using gradle and can build changing the package name but there is still a few things I want to do in the build.gradle file and can't make it work.
This is build.gradle:
task("hello"){
println "Hello world!!"
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.8.+'
}
}
apply plugin: 'android'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}
android {
compileSdkVersion 19
buildToolsVersion "19.0.3"
productFlavors {
flavor1 {
packageName "com.testCompany.testProject"
}
}
signingConfigs {
release {
storeFile file("keystore/android.keystore")
storePassword 'blah blah'
keyAlias "blah blah"
keyPassword 'blah blah blah'
}
}
buildTypes {
flavor1 {
zipAlign true
sourceSets {
main {
signingConfig signingConfigs.release
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
}
}
}
}
I am pretty sure I'm doing things wrong.
So I want to:
- Change some strings in the res/strings.xml file.
- Change the icon/png files in the res/drawable.... folder for custom ones.
I have completely no idea of how to do it. I tried:
buildTypes{
flavor1{
copy{
from('src/res/'){
include '**/*.xml'
filter{String line -> line.replaceAll(string_to_be_replaced, replaced_string)}
}
into '$buildDir/res'
}
}
}
but nothing
The strings I need to change are: - The package name (com.company.project)
If you are changing these things based upon whether this is a debug build or a release build, you can specify a suffix on the package name for a build type:
android {
buildTypes {
debug {
packageNameSuffix ".debug"
}
}
}
Or, if you are changing these things for anything else, you can create product flavors and replace the package name per flavor:
android {
productFlavors {
flavor1 {
packageName "com.example.flavor1"
}
flavor2 {
packageName "com.example.flavor2"
}
}
}
Some images (like icons, splash screen, ...) - some irrelevant string that are specific from the app.
You can create source sets for build types (e.g., src/debug/) or product flavors (e.g., src/flavor1/) and have replacement versions of resources in them. That will handle your images, as well as your "irrelevant string" if you define it as a string resource.
Source sets can also have Java code, though that gets incrementally more complex, so I would recommend that you use the string resources and replacement resources instead.