I am trying to implement robobinding with product flavors but the custom code classes under the flavor's source directory never get executed.
Has anyone tried anything similar to this use-case? i.e. used some kind of element binders and then implemented product flavors?
On a certain demo project the structure I have:
-app/src/main/java/demo.app.pkg/MainActivity.java
-app/src/free/java/demo.app.pkg.free/MainActivity.java
build.gradle :
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
free {
applicationId "demo.app.pkg.free"
}
paid {
applicationId "demo.app.pkg.paid"
}
}
and when the MainActivity.java class is modified present under free flavor it does get packaged when the free flavor's debug/release is built. and is executed as well containing the custom code.
(On a side Note: some say that in-order to implement product flavors which has different versions of a single class one needs to have a src folder for main containing common code (but not the classes having same name present in the flavor's src folders) and other 2 src folders which have the class(es) having same name etc. which would essentially segregate the two flavors. This wasn't the case with the sample project I tried above^ it worked flawlessly; even when I had the same named class under main src folder.)
Now, the issue lies when I try to implement similar kind of product flavors (as seen above) in a project already having robobinding implemented.
Structure goes like:
-app/src/main/java/demo.app.pkg/MainActivity.java
-app/src/main/java/demo.app.pkg/MainActivityPresentationalModel.java (class to be replaced by class present under 'free' flavor)
-app/src/main/java/demo.app.pkg/Pojo.java
-app/src/free/java/demo.app.pkg.free/MainActivityPresentationalModel.java
This thing doesn't work. Only the class MainActivityPresentationalModel.java under main gets executed.
Now, if anyone has used view binders especially robobinding or SDK's binders (still under beta) they must be aware of that we get access to a presentational model which is essentially logic where we have setter/getters to get/put values so that they get updated on the UI at runtime and hence my motive to have this class in a product flavor.
Any help is much appreciated.
Reference:
For the first sample project kindly have a look at 'Build-It-Bigger' project on gitHub.
Related
The problem i am facing is there is two project(apps) similar and there will be more in future and when i change a code in one i will need to do same changes in other projects. when i searched on web i found product flavors but not sure if it's the answer for my problem.
How can i merge two different projects (apps) in playstore. Projects codes are %85 similar can i use flavors to merge both project in one and will i be able to update them in playstore using different jks with different package names and a few different permissions. Will i need AndroidManifest file for each flavor.
How can i solve this problem. Thanks
To change packageName you have to create product Flavor like
flavorDimensions "versionCode"
productFlavors {
doctorApp {
dimension "versionCode"
applicationId "com.doctor.app"
}
patientApp {
dimension "versionCode"
applicationId "com.patient.app"
}
}
After that create two sibling folder of main after switch project View to Project
app -> src -> main /// write all common classes here
app -> src -> doctorApp // doctor related classes here along with their resources
app -> src -> patientApp // patient related classes here along with their resources
create same package name and res folder under patientApp and doctorApp
Short question:
How can I change the package name for debug or release build type in a library module?
Context:
In an Android project with MVP + Clean architecture, we have the repository pattern in a library module. We want to include Firebase on that library with two environments (development and production).
I already created the project in Firebase (com.example.com and com.example.com.dev) and then downloaded the respective google-services.json to src/main and src/debug folders.
Gradle google-services plugin validates the module package name with the client ID defined in the google-services.json, but Android restrict to change the applicationId in a library (I can't find the technical reason why)
Things that I tried:
Have two AndroidManifest.xml with different package property. com.example.com in the src/main and com.example.com.dev in src/debug/ but the second one it is just ignored
Set manifest.srcFile in Gradle sourceSets. The file is in the list when I run ./gradlew sourceSets but the package name doesn't change
Two different flavors in the library module and set different manifests for each one. The package anyway doesn't change.
At this moment I have just two suitable solutions:
1. Keep the Firebase setup and implementation in the app module outside of the repository.
2. Have only one environment for Firebase.
Thanks a lot for any help or advice.
EDIT:
Consider that I need to modify the package in a module (library), not in the app. For some weird reason Gradle shows this error when I try to use applicationIdSuffix or applicationId in a module:
ERROR: Library projects cannot set applicationIdSuffix.
Library projects cannot set applicationId.
This is the designed behaviour of Android Library project.
Two different flavors in the library module and set different
manifests for each one. The package anyway doesn't change.
Probably you need to change your Build Variants to that particular flavor/buildtype then you can see the updated package name taking effect.
See below screenshot.
I spent some time investigating and trying different alternatives to achieve two different package name per flavor or build type in a library module, and my short answer is: You can't, at least without doing something tricky and dirty.
Some guys that recommend using the parameter applicationIdSuffix or applicationId, that option doesn't work because of the design of library modules restricts those parameters to the app module. In a library, the package must be defined in the manifest.
That restriction delimits options to flavors, but, the package attribute in the manifest isn't merged, and you get an error when having different package name for the scr/main/AndroidManifest.xml and src/flavor/AndroidManifest.xml.
A tricky solution is to get the currently selected flavor form the task name and then change the main manifest in the sourceSets.
sourceSets {
main {
manifest.srcFile "src/$flavor_name/AndroidManifest.xml"
}
}
This hack works but in general is a bad idea, and I prefer to change the design of my architecture and implement the repository for both Firebase variants in a different way.
Gradle plugin: 3.2.0
I have created 2 flavors in Android Studio's Gradle, and I put the MainActivity file in their respective folder structures.
This is how the project looks:
This is the Gradle flavor part:
productFlavors {
free {
applicationId "com.xxxxx.yyyyy.free"
versionName "1.0.0"
}
full {
applicationId "com.xxxxx.yyyyy"
versionName "1.0.0"
}
}
Unfortunately, when I use the full flavor, the MainActivity is considered unset.
Free flavor:
Full flavor:
The project can be compiled in both flavors, it just can't be run on full flavor as it can't find the Default Activity.
The two files have minimal differences.
What should I check?
Perhaps not directly addressing your issue, but have you considered making a pure Java helper class that provides different functionality to your MainActivity?
The problem here appears to be your moving MainActivity is not being recognized by the AndroidManifest when in full mode, but if you have 2 versions of your helper class everything should be good
Edit
If you want to specify two different activities, use a relative path in your AndroidManifest.
<activity android:name=".MainActivity">
Be cautious to try and reuse as much common code as possible between your two activities to save yourself any headaches down the road though
I have a project in Android Studio with two Product Flavours. They're effectively identical except for a few hard-coded values in them, e.g. URLs, ids and whether to activate some additional functionality.
I'd like to be able to just have one flavour and move these hard-coded values out to some kind of config/properties file which the now generic code could read or pre-load on startup as needed. I'd then like to have some kind of gradle command that creates the different APKs using the different config/properties file.
That way, if I wish to create another configuration for the app (a combination of the properties I mentioned above), I don't have to go copying (and maintaining) another Product Flavour to do this.
It'd be great if this could all be done in Android Studio and not the command line also. Can someone tell me of a way to do this please?
A command-line solution may also be acceptable, but it would ideally have to be Operating System independent as some of our developers work on MACs while others work on PCs.
I and other Android developers around me looked into this ourselves. But we couldn't find anything within the gradle framework that allowed the kind of flexibility I've outlined.
Outside of pre-configured android parameters that can be set in build.gradle, we couldn't find anything where we could configure properties of our own that would affect the build.
The only solution we could see it to have duplicate Product Flavours with the hard-coded values changed to the new configuration we want. We'd like to avoid this at all costs.
Looks like I asked too soon :D .
Someone else in our company managed to solve the problem using build types.
For example, say we wanted a boolean variable saying whether the app should operate in "Test-mode". We can define a "TEST_MODE_ENABLED" variable using the buildConfigField parameter. You could define a "testing" build type in the gradle file as follows (see the last build type):
buildTypes {
debug {
debuggable true
buildConfigField "boolean", "TEST_MODE_ENABLED", "false"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
buildConfigField "boolean", "TEST_MODE_ENABLED", "false"
}
testing {
debuggable true
buildConfigField "boolean", "TEST_MODE_ENABLED", "true"
}
}
This parameter and others can then be accessed in the java code by referencing:
BuildConfig.TEST_MODE_ENABLED
With this concept, we can create as many configurations we like and then define additional Build Variants using these additional build types.
We can also use this with gradlew, e.g.:
gradlew assemble[ProductFlavour][BuildType]
Hope I explained that properly and that it might help someone else.
I'm trying to understand how i can generate multiple APK from one single project.
I'm using gradle and this is my project's three:
ambrogiocore is the core library module that implements all the common classes and resources.
ambrogioremote is the module that has the :ambrogiocore dependence.
It's work. Now i'm able to generate multiple APK. (just one at the moment)
One apk for each module.
The problem is that i need to manually sync all the AndroidManifest.xml for every future module that i'll include in my project.
Is this the correct way?
Can i automate this operation?
I took a look at productFlavor. Just I don't understand if this tool can help me.
What do you think about?
THANK YOU ALL!
**SOLUTION**
Finally! I found the same solution proposed by #Kai!
Flavor is the way!
This is the best approach for a lots of reasons:
Single-module project
You don't need to copy XML files
RoboGuice will work like a charm. (RoboGuice presents some BIG problem on library projects)
http://www.techotopia.com/index.php/An_Android_Studio_Gradle_Build_Variants_Example
If by "one single source core and multiple project that extends "ProductName", "PackageName" and "resources"" you mean to provide each flavor with unique "ProductName", "PackageName" and "resources", then yes it can be done.
To give each flavor its own unique package, set applicationId for each of your flavors like so:
android {
productFlavors {
flavor_1 {
applicationId = 'com.app.flavor_1'
}
flavor_2 {
applicationId = 'com.app.flavor_2'
}
}
}
To give each flavor its own app name and resources, simply put them in a flavor's own directory, Gralde will merge a flavor's resources with your base resources to create a complete one.
For more detail on how Gralde flavors work, please see Gradle Plugin User Guide
This is my final solution!
All the common files, manifest and base resources are under "src/main"
I moved my projects inside "src/projects"
declared two productFlavor (one per project) specifying applicationId and versionName
created two sourceSet (one per project) indicating the specific res folder.