Android Studio buildflavors - android

Getting started with the new android studio it seems very flexible but that usually brings a steep learning curve. Hoping to get some help with that here.
I've built an app and deployed it with this build.gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.0"
defaultConfig {
applicationId "me.test.simpleProject
minSdkVersion 10
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
signingConfigs {
release {
storeFile file("../my.keystore.jks")
storePassword System.getenv("and_ks_pw")
keyAlias System.getenv("and_ky_alias")
keyPassword System.getenv("and_k_pw")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
debuggable true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile project(":Library:lib_my_lib_a")
compile project(":Library:lib_my_lib_b")
compile project(":Library:lib_my_lib_c")
}
This works pretty well and once I learn the syntax it'll be much easier to use than the previous system.
Now my question.
I would like to basically add a few product flavors.
I currently use google analytics to track clicks, usage stats, simple things like that.
In the past [before android studio] typically distribute my apps in a free/ paid version.
I would like to create say build flavors for:
google play free
google play paid
amazon free
amazon paid
The code for these apps should be mostly identical but they cannot be since, for example adding links to google play in your amazon apps gets you in a bit of trouble over there. So I will need to have unique classes across the build flavors.
I was reading some docs and watching google talks about setting up the build flavors but I am a bit confused.
Can someone help me define the folder structure for this project?
current application structure
test/
.gradle/
.idea/
app/
app/build
app/libs <-- empty
app/src
app/.gitignore
app/app.iml
app/build.gradle
app/proguard-rules.pro
build/
gradle/
Library/lib_a
Library/lib_b
Library/lib_c
.gitignore
build.gradle
gradle.properties
gradlew
gradlew.bat
local.properties
settings.gradle
test.iml
Can I place the new folders anywhere and how do I link them up with grade to properly build the variants?

The first thing you should do, is add these flavors to your gradle script, inside the android section:
productFlavors {
googleFree {
applicationId = "com.your.app.gfree"
}
googlePaid {
applicationId = "com.your.app.gpaid"
}
amazonFree {
applicationId = "com.your.app.afree"
}
amazonPaid {
applicationId = "com.your.app.apaid"
}
}
Note that you can define different package names for your app if needed, as well as some additional properties. Full details: Gradle Plugin - Build Variants
At this point you will have three different concepts in your app now:
Build types: Debug and Release
Product flavors: googleFree, googlePaid, amazonFree and amazonPaid
Build variants: Combination of build types and flavors
googleFreeDebug
googleFreeRelease
googlePaidDebug
googlePaidRelease
amazonFreeDebug
amazonFreeRelease
amazonPaidDebug
amazonPaidRelease
Flavor Specific resources:
For defining resources, you should have:
app
src
main
java
res
googlePaid
java
res
googleFree
java
res
amazonPaid
java
res
amazonFree
java
res
With that structure in place, you can place all your shared stuff under main, while the flavor specific stuff would live on each flavor's folder. Then, when building a specific variant of your app, android and gradle will resolve the right resources for you. If you are interested in more details, see Resource Merging.
Once the flavors have been added to your build.gradle file, if you sync your project, Android Studio will be able to pick your build variants and you may select these from the IDE:

To use flavors in your app you should have a structure like this:
app
src
flavor1
java
res
flavor2
java
res
main
java
res
You have to define the flavors in the build.gradle:
productFlavors {
flavor1 {
//
}
flavor2 {
//
}
}
Then you can have different dependencies using:
dependencies {
releaseCompile
debugCompile
flavor1Compile
flavor1DegubCompile
}
For example:
dependencies {
freeCompile 'com.google.android.gms:play-services:7.5.0'
}

Related

Android Dynamic Feature INSTALL_FAILED_INVALID_APK

I am trying to add some functionality to an existing application. The app's build.gradle contains several productFlavors and a couple of buildTypes. I have tried to replicate that as best I can in my dynamic-feature module, but I cannot seem to get it to install properly from Android Studio.
I followed the example from: https://github.com/googlearchive/android-dynamic-features to set up my feature module, so my project is structured like
app
features/module/build.gradle
build.gradle
I added a buildType and flavor to the app build.gradle
defaultConfig {
minSdkVersion 24
targetSdkVersion 28
}
dynamicFeatures = [":features:module"]
buildTypes{
myBuildType {
debuggable true
multiDexEnabled true
}
}
flavorDimensions "blah"
productFlavors{
arm64 {
ndk {
abiFilters "arm64-v8a"
}
ext {
abiVersionCode = 5
}
matchingFallbacks = ['defaultFlavor']
}
}
and in the module build.gradle, I have attempted to match that with:
defaultConfig {
minSdkVersion 24
targetSdkVersion 28
}
buildTypes {
dynamic {
multiDexEnabled true
debuggable true
}
}
flavorDimensions "blah"
productFlavors {
arm64 {
ext {
abiVersionCode = 5
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':app')
}
In my Run->Edit Configuration screen, I have put a checkbox next to both the base app and the module under the dynamic features to deploy section. I am trying to test this on a Nokia 6, with Android 9.0 running on it. The only output I get from the build is:
01/12 22:39:25: Launching 'app' on HMD Global TA-1025.
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_INVALID_APK
The APKs are invalid.
It just happened to me.
Turns out I was setting different flavors for different modules.
Try selecting the same variants under View > Tool Windows > Build Variants.
Please check those things
1) making sure that the AndroidManifest.xml package name was the same as the
build.grade applicationId
2) check package name in your Androidmanifest.xml see whether started with one empty
space character. like " com.example.test" instead of "com.example.test"
and make sure contain at least one dot in your package name
like "com.exampletest" instead of "comexampletest"
https://code.google.com/p/android/issues/detail?id=55841
3)"Build" > "Clean Project"
4)reboot the android system
Try Edit Configurations > Installations Options > Deploy APK from app bundle
I found a solution that resolved my problem. Make sure your libraries and class paths are up to date. I had a class for firebase plugins that were out of date. This problem occurred when using the new graddle. After updating the classpath, everything looks fine.
In my case. I changed this
classpath 'com.google.firebase:firebase-plugins:1.1.0'
to this
classpath 'com.google.firebase:perf-plugin:1.3.1'
I had same problem when I used Flavors (Build variants) in my app.
The solution for me was select another build variant in Build Variants tab (for example, release instead of debug flavor), then select the correct build variant, and then Clean, Rebuild.
I found this solution here: https://stackoverflow.com/a/65630971/6543967

How to compile with gradle different dependency module's dependencies based on build variants?

I have an Android app which has a module dependency. This module itself has a jar library as a dependency that comes in two variants, each relative to a build variant of the main app. When I switch build variant in the main app, I managed to automatically select the module's build variant which picks the correct jar, but this is not reflected in the code, where the specific classes from the jar are not found in the build variant specific code.
Here's the related code from the build.gradle files of the main app and the dependency module:
main app - build.gradle
buildTypes {
type1 {initWith(debug)}
type2 {initWith(debug)}
}
productFlavors {
live{}
test{}
}
dependencies {
type1Compile project(path: ':module', configuration: 'one')
type2Compile project(path: ':module', configuration: 'two')
}
module - build.gradle
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
useLibrary 'org.apache.http.legacy'
publishNonDefault true
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
buildTypes {
release {
minifyEnabled = false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
one {initWith(release)}
two {initWith(release)}
}
}
dependencies {
oneCompile files('libs/versionOne/mylib.jar')
twoCompile files('libs/versionTwo/mylib.jar')
}
So, when I build testType1 variant, Android Studio automatically selects one variant, and with a clean build it all goes fine. But if I switch to testType2, although module's two variant is selected, the editor will highlight missing classes and methods.
How can I make gradle pick the right jar when I switch between the app's build variants?
Some considerations:
The module needs the library, since it uses a few classes that are common between the 2 versions.
I know this may look like bad project design, but it's an app that has been built by different people in different times, and I now have to develop it "as is".
After some tinkering, I found some clues. First of all, my two jars where the same name, in different folders. After renaming the jars to have also different names, gradle manages to pick the correct one after the build variant switch, provided that an additional "Sync project with gradle files" is done. So now it's not immediate, but eventually it's working.

How can I create aar file in android studio 1.3.1 while I've made the project without activity [duplicate]

I'd like to create an aar file for my library in Android Studio, i would've gone with a jar option but my library has resources.
Any idea how to create an aar file from a library?
If your library is set up as an Android library (i.e. it uses the apply plugin: 'com.android.library' statement in its build.gradle file), it will output an .aar when it's built. It will show up in the build/outputs/aar/ directory in your module's directory.
You can choose the "Android Library" type in File > New Module to create a new Android Library.
If you are still not seeing your aar file, select Build > Rebuild Project.
Retrieve exported .aar file from local builds
If you have a module defined as an android library project you'll get .aar files for all build flavors (debug and release by default) in the build/outputs/aar/ directory of that project.
your-library-project
|- build
|- outputs
|- aar
|- appframework-debug.aar
- appframework-release.aar
If these files don't exist start a build with
gradlew assemble
for macOS users
./gradlew assemble
Library project details
A library project has a build.gradle file containing apply plugin: com.android.library. For reference of this library packaged as an .aar file you'll have to define some properties like package and version.
Example build.gradle file for library (this example includes obfuscation in release):
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
minSdkVersion 9
targetSdkVersion 21
versionCode 1
versionName "0.1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Reference .aar file in your project
In your app project you can drop this .aar file in the libs folder and update the build.gradle file to reference this library using the below example:
apply plugin: 'com.android.application'
repositories {
mavenCentral()
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}
android {
compileSdkVersion 21
buildToolsVersion "21.0.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 20
versionCode 4
versionName "0.4.0"
applicationId "yourdomain.yourpackage"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
}
}
}
dependencies {
compile 'be.hcpl.android.appframework:appframework:0.1.0#aar'
}
Alternative options for referencing local dependency files in gradle can be found at: http://kevinpelgrims.com/blog/2014/05/18/reference-a-local-aar-in-your-android-project
Sharing dependencies using maven
If you need to share these .aar files within your organization check out maven. A nice write up on this topic can be found at: https://web.archive.org/web/20141002122437/http://blog.glassdiary.com/post/67134169807/how-to-share-android-archive-library-aar-across
About the .aar file format
An aar file is just a .zip with an alternative extension and specific content. For details check this link about the aar format.
just like user hcpl said but if you want to not worry about the version of the library you can do this:
dependencies {
compile(name:'mylibrary', ext:'aar')
}
as its kind of annoying to have to update the version everytime. Also it makes the not worrying about the name space easier this way.
To create AAR
while creating follow below steps.
File->New->New Module->Android Library and create.
To generate AAR
Go to gradle at top right pane in android studio follow below steps.
Gradle->Drop down library name -> tasks-> build-> assemble or assemble release
AAR will be generated in build/outputs/aar/
But if we want AAR to get generated in specific folder in project directory with name you want, modify your app level build.gradle like below
defaultConfig {
minSdkVersion 26
targetSdkVersion 28
versionCode System.getenv("BUILD_NUMBER") as Integer ?: 1
versionName "0.0.${versionCode}"
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "/../../../../release/" + ("your_recommended_name.aar")
}
}
}
Now it will create folder with name "release" in project directory which will be having AAR.
Updated Answer
In Latest releases specific path is not supported.Please add below code in library's build.gradle and rebuild project.After Rebuilding "aar",change project structure from Android to Project->navigate to your library->build->outputs->aar
android {
defaultConfig {
minSdkVersion ..
targetSdkVersion ..
versionCode ...
versionName "1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "${archivesBaseName}_${variant.name}_${defaultConfig.versionName}.aar"
}
}}
To import "aar" into project,check below link.
How to manually include external aar package using Gradle for Android
After following the first and second steps mentioned in the hcpl's answer in the same thread, we added , '*.aar'], dir: 'libs' in the our-android-app-project-based-on-gradle/app/build.gradle file as shown below:
...
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
...
Our gradle version is com.android.tools.build:gradle:3.2.1
btw #aar doesn't have transitive dependency. you need a parameter to turn it on:
Transitive dependencies not resolved for aar library using gradle
Finally got the solution here - https://stackoverflow.com/a/49663101/9640177
implementation files('libs/aar-file.aar')
Edit
I had one more complication - I had set minifyEnabled true for the library module.
[JAR vs AAR]
.jar is generated by apply plugin: 'java-library'
.aar is generated by apply plugin: 'com.android.library'
File -> New -> New Module... -> Android Library
If you have correctly set up for publishing, then you can just run this command to generate aar files.
./gradlew publishReleasePublicationToMavenLocal
This will generate a aar file inside <module-dir>/build/output/aar directory.
Now you can use this library in other local projects also. Add this in the project gradle in which you want to use this aar module
implementation fileTree(dir: '<location-to-library>/build/outputs/aar/', include: ['*.aar', '*.jar'], exclude: [])
Build ---> Build bundle/apk
.aar file will be generated in build/outputs/aar folder.

How to share SDK without src folder [duplicate]

I'd like to create an aar file for my library in Android Studio, i would've gone with a jar option but my library has resources.
Any idea how to create an aar file from a library?
If your library is set up as an Android library (i.e. it uses the apply plugin: 'com.android.library' statement in its build.gradle file), it will output an .aar when it's built. It will show up in the build/outputs/aar/ directory in your module's directory.
You can choose the "Android Library" type in File > New Module to create a new Android Library.
If you are still not seeing your aar file, select Build > Rebuild Project.
Retrieve exported .aar file from local builds
If you have a module defined as an android library project you'll get .aar files for all build flavors (debug and release by default) in the build/outputs/aar/ directory of that project.
your-library-project
|- build
|- outputs
|- aar
|- appframework-debug.aar
- appframework-release.aar
If these files don't exist start a build with
gradlew assemble
for macOS users
./gradlew assemble
Library project details
A library project has a build.gradle file containing apply plugin: com.android.library. For reference of this library packaged as an .aar file you'll have to define some properties like package and version.
Example build.gradle file for library (this example includes obfuscation in release):
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
minSdkVersion 9
targetSdkVersion 21
versionCode 1
versionName "0.1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Reference .aar file in your project
In your app project you can drop this .aar file in the libs folder and update the build.gradle file to reference this library using the below example:
apply plugin: 'com.android.application'
repositories {
mavenCentral()
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}
android {
compileSdkVersion 21
buildToolsVersion "21.0.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 20
versionCode 4
versionName "0.4.0"
applicationId "yourdomain.yourpackage"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
}
}
}
dependencies {
compile 'be.hcpl.android.appframework:appframework:0.1.0#aar'
}
Alternative options for referencing local dependency files in gradle can be found at: http://kevinpelgrims.com/blog/2014/05/18/reference-a-local-aar-in-your-android-project
Sharing dependencies using maven
If you need to share these .aar files within your organization check out maven. A nice write up on this topic can be found at: https://web.archive.org/web/20141002122437/http://blog.glassdiary.com/post/67134169807/how-to-share-android-archive-library-aar-across
About the .aar file format
An aar file is just a .zip with an alternative extension and specific content. For details check this link about the aar format.
just like user hcpl said but if you want to not worry about the version of the library you can do this:
dependencies {
compile(name:'mylibrary', ext:'aar')
}
as its kind of annoying to have to update the version everytime. Also it makes the not worrying about the name space easier this way.
To create AAR
while creating follow below steps.
File->New->New Module->Android Library and create.
To generate AAR
Go to gradle at top right pane in android studio follow below steps.
Gradle->Drop down library name -> tasks-> build-> assemble or assemble release
AAR will be generated in build/outputs/aar/
But if we want AAR to get generated in specific folder in project directory with name you want, modify your app level build.gradle like below
defaultConfig {
minSdkVersion 26
targetSdkVersion 28
versionCode System.getenv("BUILD_NUMBER") as Integer ?: 1
versionName "0.0.${versionCode}"
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "/../../../../release/" + ("your_recommended_name.aar")
}
}
}
Now it will create folder with name "release" in project directory which will be having AAR.
Updated Answer
In Latest releases specific path is not supported.Please add below code in library's build.gradle and rebuild project.After Rebuilding "aar",change project structure from Android to Project->navigate to your library->build->outputs->aar
android {
defaultConfig {
minSdkVersion ..
targetSdkVersion ..
versionCode ...
versionName "1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "${archivesBaseName}_${variant.name}_${defaultConfig.versionName}.aar"
}
}}
To import "aar" into project,check below link.
How to manually include external aar package using Gradle for Android
After following the first and second steps mentioned in the hcpl's answer in the same thread, we added , '*.aar'], dir: 'libs' in the our-android-app-project-based-on-gradle/app/build.gradle file as shown below:
...
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
...
Our gradle version is com.android.tools.build:gradle:3.2.1
btw #aar doesn't have transitive dependency. you need a parameter to turn it on:
Transitive dependencies not resolved for aar library using gradle
Finally got the solution here - https://stackoverflow.com/a/49663101/9640177
implementation files('libs/aar-file.aar')
Edit
I had one more complication - I had set minifyEnabled true for the library module.
[JAR vs AAR]
.jar is generated by apply plugin: 'java-library'
.aar is generated by apply plugin: 'com.android.library'
File -> New -> New Module... -> Android Library
If you have correctly set up for publishing, then you can just run this command to generate aar files.
./gradlew publishReleasePublicationToMavenLocal
This will generate a aar file inside <module-dir>/build/output/aar directory.
Now you can use this library in other local projects also. Add this in the project gradle in which you want to use this aar module
implementation fileTree(dir: '<location-to-library>/build/outputs/aar/', include: ['*.aar', '*.jar'], exclude: [])
Build ---> Build bundle/apk
.aar file will be generated in build/outputs/aar folder.

Can I list all string resource files in folder tree?

I create a project with free and pro edition based productFlavors, and use different string resource file for different edition, the folders construction is cc.png.
If I change Build Variant in panel, the values in Android tab display two strings.xml(2), one is located main folder, another is located free or pro folder, you can see aa.png and bb.png.
I hope that all string resource files can be displayed together, it will display three string.xml(3), first is located main folder, sencond is located free folder, third is located pro folder. How can I do that ? Thanks!
CC.Png
AA.png
BB.png
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "info.dodata.messagecleanup"
minSdkVersion 9
targetSdkVersion 22
versionCode 7
versionName "1.07"
archivesBaseName = "MessageCleanup-V" + versionName
}
productFlavors {
free {
applicationId "info.dodata.messagecleanup"
buildConfigField "String", "AppName", "\"Message Cleanup\""
}
pro {
applicationId "info.dodata.messagecleanup.pro"
buildConfigField "String", "AppName", "\"Message Cleanup Pro\""
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.google.android.gms:play-services:7.3.0'
}
Unfortunately the Android project pane view does not support this behavior. The Android view was specifically designed to show the state of your project for a given build variant, not across all variants.
As you have already discovered, the easiest way to see your resources in all available configurations is to use the "project" view instead of the "Android" view.
You are also free to file a feature request on the Android issue tracker for the option to show the resources available across all variants.
You can define custom scopes within IntelliJ / Android Studio, that display specific folders/files:
You can then select that custom scope from the scope drop-down selector:
That said, I think the more efficient way of navigating between the string files is to hit the "Search Everywhere" hotkey, type "strings.xml", and select the one you want:

Categories

Resources