I would like to create two falvors for my project. I did this successfully in the past but with new ANdroidStudio I a little bit concerned how to do that. The official guide is out-dated.
In the past what we need to do is to create additional folders on the level of "src" folder. In the current version of AndroidStudio we have app->{/java;/manifests;/res} structure and we can create folder only under the same package and I don't see the way to create additional folder for "res"
Can you advise please how I can create flavors for my app?
The official guide is out-dated.
The core of the official guide's section on product flavors seems fine to me.
In the past what we need to do is to create additional folders on the level of "src" folder.
That would define a sourceset for a product flavor. You still need to declare the product flavor in build.gradle for the module, via a productFlavors closure or via the Project Structure dialog.
In the current version of AndroidStudio we have app->{/java;/manifests;/res} structure
Switch from the Android view of your project contents to the Project view, via the drop-down just above the project structure tree.
You will start with a tree like:
and change it to a tree like:
Can you advise please how I can create flavors for my app?
Add a productFlavors closure to your module's build.gradle file, manually or via the Project Structure dialog:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.commonsware.myapplication"
minSdkVersion 8
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
vanilla {
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
If you want to have alternative source for that product flavor (Java, resources, manifest, etc.), create src/.../ in the project, where ... is the name of your flavor (src/vanilla/ would correspond with the sample build.gradle shown above). To create this directory, either:
in the Project view, create it as you would any other directory
in the Android view, just start defining a resource, and the dialog that appears will have a drop-down for the sourceset:
However, as I do not know how to put Java code in a particular sourceset this way, I always work in the Project view.
Maybe try with build types, somewhat similar to this post. You may change resource folders in that fashion
Related
I'm trying to create a plugin that relies upon AWS' Mobile SDK (In Java). It says to put
implementation ('com.amazonaws:aws-android-sdk-mobile-client:2.6.+#aar') { transitive = true }
inside the app/build.grade. However, when I'm developing that plugin as per the documentation, there is no app/ folder within the plugin's android root (there is one in the example project, but I don't think that's where I'm supposed to put it).
Specifically, I'm creating the plugin using this command:
flutter create --template=plugin hello
Where should I put this? Should I download the .jar itself, and put it in the project.
Cheers.
When using a plugin, add your gradle dependencies in [projectFolder]/android/build.gradle. At the bottom, below the android section, add a dependencies section like this:
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation('com.amazonaws:aws-android-sdk-mobile-client:2.6.+#aar') { transitive = true }
}
Then run the example application provided by the plugin project. Gradle will fetch the dependencies.
You need to create a plugin package for that
flutter create --template=plugin hello
--template=package is for packages that contain only Dart code.
One Android Studio project contains a no-activity service, to be communicated with via IMyAidlInterface (belonging to package com.example.tutorialspoint7.noactivity).
Another Android Studio project contains an activity-only application, for the sole purpose of testing the aforemention service (assume a different package, e.g. com.example.tutorialspoint7.aidlactivity)
Without any special configuration, the aidlactivity project does not know about the noactivity project and thus, any reference to IMyAidlInterface in aidlactivity gets "Cannot resolve symbol IMyAidlInterface".
I searched for a way to let the aidlactivity project to know about that AIDL file, but all "solutions" I found were actually workarounds duplicating the file and adding it as in this example: https://stackoverflow.com/a/16906355/5556250
So, I turned into manually tweaking the app's build.gradle by adding the following into it:
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.tutorialspoint7.aidlactivity"
minSdkVersion 16
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += '../../NoActivity/app/src/main/aidl/com/example/tutorialspoint7/noactivity'
}
}
I then synced it and, how wonderful, it is now part of the aidlactivity project:
But... AIDLActivity still gets "Cannot resolve symbol IMyAidlInterface".
What do I need to do now to get it to recognize the file?
Problem "worked around". Here is how:
I undid the manual addition into the app's build.gradle:
sourceSets {
main.java.srcDirs += '../../NoActivity/app/src/main/aidl/com/example/tutorialspoint7/noactivity'
}
I manually created the folder ..\AIDLActivity\app\src\main\aidl\com\example\tutorialspoint7\noactivity, and then copied over to there the original IMyAidlInterface.aidl file from the 'NoActivity' service project.
Adding import com.example.tutorialspoint7.noactivity; in AIDLActivity.java doesn't work!!! so... I worked around this by simply referencing IMyAidlInterface using its fully qualified name:
Gradle sync the projects
The AIDLActivity project now builds without any errors. :-)
Credits goes to this Jun 18, 2013 post by dominik2...#gmail.com: https://code.google.com/p/android/issues/detail?id=56755#c1
Update: I managed to avoid the explicit fully qualified name ugliness by simply importing the specific interface, not the package (duh!):
All is well now but... Why do I have to keep copying the interface file whenever it changes in the original service, instead of just referencing it? I wish there were a way to reference (instead of copy) an AIDL file in Android Studio (version 2.2.3).
I am trying to swap some resources in the res/raw folder and the jniLibs/armeabi folder based on whether its a release buildType or a debug buildType. I currently have two product flavors as well.
The build.gradle file:
apply plugin: 'com.android.application'
android {
dexOptions {
preDexLibraries = false
}
compileSdkVersion 21
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 17
targetSdkVersion 22
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
productFlavors{
phone{
applicationId "com.example.testPhone"
}
tablet{
applicationId "com.example.testTablet"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
sourceSets{
release{
res.srcDirs = ['androidRelease/res/raw']
}
}
}
dependencies {
compile project(':facebook')
}
Is using sourceSet the right way to do so? If it is, what folder should be created so that it swaps the appropriate resources based on the buildType only and irrespective of the productFlavors?
EDIT: Is it even possible to swap jniLibs and raw folder resources?
Folder Structure:
src/main/jniLibs/armeabi
phoneRelease/jniLibs/armeabi
tabletRelease/jniLibs/armeabi
Is the folder structure correct.?
EDIT 2:
Based on Xavier's answer should the gradle look like this:
android {
sourcesets {
phone {
jniLibs.srcDirs = ['phoneRelease/jniLibs/']
res.srcDirs = ['androidRelease/res/raw']
}
tablet {
jniLibs.srcDirs = ['tabletRelease/jniLibs/']
res.srcDirs = ['androidRelease/res/raw']
}
}
}
I keep reading lot of conflicting answers, some of them mention that you just need separate folders based on build variant and some mention about having to use sourceSet?
Thanks!
some of them mention that you just need separate folders based on build variant and some mention about having to use sourceSet?
Gradle/Gradle for Android has an expected structure for a sourceset:
Android resources in res/
Java source tree in java/
Pre-compiled JNI libraries in jniLibs/
Assets in assets/
Etc.
Where the sourceSets closure comes into play is if, for a given sourceset, you want a different structure:
Android resources in foo/
Java source tree in bar/
Pre-compiled JNI libraries in ickyNativeStuff/
Assets in assetsBecauseThatSeemsLikeADecentName/
Etc.
Each build type, product flavor, and build variant can have a separate sourceset (as can androidTest for instrumentation testing), to go along with main. They are named the same as the build type/product flavor/build variant. These will be in the stock structure, unless you use sourceSets to change things.
So, to roll all the way back to:
I am trying to swap some resources in the res/raw folder and the jniLibs/armeabi folder based on whether its a release buildType or a debug buildType
In the case of resources, other sourcesets overlay main. So, if you have src/main/res/... and src/main/debug/... and src/main/release/..., and you are doing a debug build, whatever is in src/main/release/... is ignored (as we aren't doing release) and whatever is in src/main/res/... and src/main/debug/... will be used. If there is the same resource in both (src/main/res/raw/boom.ogg and src/debug/res/raw/boom.ogg), the debug one trumps the main one.
I have not experimented with varying jniLibs/ by build variant. My guess is that it will behave more like Java code, where you cannot have conflicts between what is in a build variant's sourceset and what is in main, but that's just a guess. So, you can have the debug version of your compiled JNI code in src/debug/jniLibs/ and the release version of your compiled JNI code in src/release/jniLibs/. Only have in src/main/jniLibs/ any libraries that are not varying. That being said, as I mentioned, I haven't tried this, and so there may be hiccups here.
So, I would expect you to not have a sourcesets closure in build.gradle, and to just use the stock sourcesets structure, for your various bits:
src/
main/
...
debug/
jniLibs/
res/
raw/
release
jniLibs/
res/
raw/
Anything that's normally under src/main/ can be put in a different folder:
src/<element>/AndroidManifest.xml
src/<element>/java
src/<element>/res
src/<element>/assets
src/<element>/resources
src/<element>/jni
src/<element>/jniLibs
src/<element>/aidl
src/<element>/rs
Where element is the name of a build type or a product flavor. If your variant includes such a element (build type or flavor), then that source set is also used in addition to src/main
Note that the location is really not relevant if you have configured it.
What matters is that there is a android.sourcesets.main element that contains the sources common to all variants, and each variant has a set of sourcesets.
For instance if you have a flavor phoneRelease it's really using the following sourcesets:
android.sourcesets.main
android.sourcesets.phone
android.sourcesets.release
android.sourcesets.phoneRelease
If you have another variant tabletRelease, it'll use the following:
android.sourcesets.main
android.sourcesets.tablet
android.sourcesets.release
android.sourcesets.phoneRelease
So the phone/tablet sourceset is different and is where you'd put the variant specific sources, unless you want to be even more specific and use the phoneRelease/tabletRelease sourcesets (though those are less used generally.) By default these would be src/phone/... and src/tablet/... (or src/phoneRelease/...) but you can change that however you want and as long as it's connected to the android.sourcesets.* objects it'll be fine.
for example, doing:
android {
sourcesets {
phone {
jniLibs.srcDirs = ['phoneRelease/jniLibs/']
}
tablet {
jniLibs.srcDirs = ['tabletRelease/jniLibs/']
}
}
}
is fine. But do be aware that you only changed the jniLibs folder and not the other source elements (java, res, etc...)
If you kept the default location for the main sourcesets, I'd just keep everything under src/
You can see more info about sourcesets and how multiple sourcesets are combined here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Sourcesets-and-Dependencies
To use flavors to vary source sets,
productFlavors{
phone{
}
tablet{
}
}
Now structure your code like,
src
main
phone
tablet
The code in main is common between both flavors, but the code in phone or tablet is only included when the respective flavor is built. That's it, you don't need to do anything else.
The structure under phone and tablet is the same as under main (res, java, etc). You can also have a custom AndroidManifest.xml under the flavor directory. Gradle attempts to merge the flavor's AndroidManifest.xml with the one in main. In some cases you have to provide rules for how to merge.
I have an Android Studio library project which uses library.aar and library.jar. When I export it as mylib.aar and use this new AAR into a different app/project, it cannot find the classes defined in the library.aar and library.jar.
My build.gradle looks like this:
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':library_dot_aar')
compile project(':library_dot_jar')
}
I imported the AAR and JAR files in Android Studio using New -> Module -> Import .JAR or .AAR Package and add them as dependencies in Project Structure -> Module Settings -> Dependencies -> Add Module Dependencies.
When I unzipped mylib.aar it was only 25KB (considering library.aar was over 300KB, I assume mylib.aar's size would be in the same range) and the included dependencies were not included in it. How do I export an AAR that includes all its dependencies inside itself?
You must check this answer:
There is no mechanism to combine library. It's a bit complicated as
you probably want to control which dependencies get merged (for
instance you probably don't want to include support-v4 in there). Also
you'd need to merge the resources and Android manifest.
At this time there's no way to easily hack something, unless you are
sure the resources have no conflicts between the two res folders (for
instance you could have strings_a.xml in one lib and strings_b.xml in
the other lib). This way you can just "merge" the two res folders by
copying them both into the same location (as opposed to do a merge at
the android res level).
For the Manifest it'd be more complicated, but doable with some custom
code.
Providing a built-in mechanism for this is very low on our priority so
don't expect it anytime soon.
I am having troubles understanding Build Flavors in Android Studio. I am trying to achieve a simple thing: buidling 2 signed APK's with a minor code change. The "pro" APK just has a different drawer.xml in res/layout/. I've read a few things in the Documentation and here on StackOverflow but I don't see anything happen with my build.gradle changes.
my current build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.+'
}
}
apply plugin: 'android'
dependencies {
compile files('libs/android-support-v4.jar')
compile files('libs/GoogleAdMobAdsSdk-6.4.1.jar')
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 17
}
productFlavors {
lite {
packageName = 'com.mikebdev.refuel'
}
pro {
packageName = 'com.mikebdev.refuelpro'
}
}
sourceSets{
android.sourceSets.pro {
res.srcDirs = ['src/main/res_pro']
}
}
}
I created a new folder:
/src/main/res_pro/layout/drawer.xml
What am I doing wrong here?
EDIT
I updated my build.gradle file above.
After resetting my whole Android Studio because of some other instabilities I am now able to choose in the bottom left corner my build variants (lite-debug, lite-release, pro-debug, pro-release) Why even those debug AND release variants?
This seems to work now as it should.
I added a answer below
After resetting my whole Android Studio because of some other instabilities I am now able to choose in the bottom left corner my build variants (lite-debug, lite-release, pro-debug, pro-release) Why even those debug AND release variants?
I created a whole new Project with Module and copy&pasted everything from my old project which I exported from eclipse a while back in there.
NOW it works.
My Android-Studio was kinda broken before my reinstall. More crashes than there should be, some strange behaviors ans such stuff.
What you're doing wrong is that you are putting your file in /src/main/res_pro/layout/drawer.xml and not setting it in the gradle. the default location for the flavor that you created would be:
/src/pro/res/layout/drawer.xml
With this build script you are using build types AND flavors. For changing the xml file you only need the flavors. Try to delete buildTypes and use the productFlavor block as child of android.
The changing of the res folder of the pro flavor should go into the sourceSets Block right after all the changes of the main sourceSet