I'm developing and app which will (during the development and testing process but NOT in the final version) require slightly different functionality in different .apk release files.
There are few issues in this particular case:
different "testing" APK versions shouldn't contain ANY of the code and resources (so no shared strings and images) from other APK versions (for security/reverse engineering reasons cause different people will have access to different APK versions)
at the end of the development process the app will contain all/most of the features from the "testing" builds.
the app uses multiple modules (developed by different teams)
there might be a few (between 3 and 10) of those versions, all developed concurrently by multiple developers in the same project on the same repository.
The goal is to make it as easy to maintain (including UI/integration tests and CI) as possible. Is there any way to achieve this? We did some experiments with different build variants and flavours + no-op modules/methods but it seems a little bit complex. Any alternative suggestion will be welcomed.
Your question is indeed too broad, I think there is no general solution to your problem because it's too complex, and without knowing the details of the project it's even more difficult to tackle. Actually, your problem sounds much more like an organizational one rather than a programming-related one, the only "solution" I see is to address specific issues.
1. No VCS, no party
there might be a few (between 3 and 10) of those versions, all
developed concurrently by multiple developers in the same project on
the same repository.
I would start by defining your VCS flow, because without a version control system I'm afraid you and your team(s) aren't going anywhere. If you were to use git (don't know how this would be done with other VCS), you would have a few options:
Each feature (team) has its own, long-living, feature-branch. The common code shared by all teams is kept on a develop-branch, on which each feature-branch periodically rebase. You would need to setup your CI to build test apks and run automated tests for each branch. At the end of the development process everything gets merged into master (or develop, or whatever). The advantage would be that each feature (team) would work on a sealed portion of the project and will be able to handle test releases and automated tests autonomously. The disadvantage would be that the common part of the codebase (develop-branch) needs to be handled very carefully, otherwise you might get conflicts-hell.
The whole project is developed on a common develop-branch. Each feature is developed with small increments, each member of each team branches from develop-branch and merges every iteration back on develop-branch. The advantage would be: different features can potentially depend on each other, conflicts are less likely to occur, CI has simpler configuration. Disadvantage: teams are less independent, releasing different apks requires a strategy.
2. Define dependencies
In order to choose a proper strategy, it is crucial to define clearly the dependencies between the features. Would it be possible to have truly parallel development of each feature?
This depends entirely on the specification of the project. For instance, if you were to develop an e-commerce app, you might end up having feature domains like user account, products catalog, orders processing... If all of these features depend on common local storage layer, how are you going to develop them truly in parallel?
Once you've defined the dependencies, you will be able to decide in what degree the features can be developed in parallel. Do different teams need to agree on common interfaces? Could a feature be completed even if other teams are still at 0?
3. Build variants are your friend
different "testing" APK versions shouldn't contain ANY of the code and
resources (so no shared strings and images) from other APK versions
(for security/reverse engineering reasons cause different people will
have access to different APK versions)
Flavors are meant to do exactly what you're looking for, that is, build different apks from the same project but using different subsets of code and/or resources.
Keep in mind that you can have flavors in multiple dimensions (and build types). For instance, you could have one flavor dimension called "network", with 2 flavors "mockedNetwork" and "actualNetwork". Then you could have another dimension "feature", with "featureA", "featureB", "featureC". You could then easily build and release 6 types (well 12 if you have also debug and release build types) of apks, one for each combination (mockedNetworkFeatureA, actualNetworkFeatureA, mockedNetworkFeatureB etc.).
With flavors you could easily replace chunks of the app that you don't want your tester to have. For instance, you could have a strings.xml file with only lorem ipsum strings and then keep actual texts strings only for internal use.
What I would do is to use git. The master branch is kept clean for production and each team can have one or multiple branches to work on. They can change the package name in their branch so your APKs will all be different. The only problem with this approach will be the merges into the master branch that might cause conflicts. But this could be a solution to your problem.
Related
Well this question might not be directly related to any code issues but would like to know what is the general way in which we can have different environment configs for different build types.
In my case, I am looking for three different build types: DEBUG, STAGING, RELEASE where each build type should use different API_BASE_URL and some other keys. I have seen few react-native modules out there such as react-native-config but they seem to be unmaintained as there is a long list of issues unresolved.
App center is also another choice but comes with limitations in the free tier and the paid plan is out of my reach.
So, I would like to know what approaches do app developers usually take to achieve what I am looking for, keeping in mind the 12 factors and also how do I set the build types?
I'm searching for differences between modules and flavor.
I've read those posts:
Android difference between module vs flavor
When to use android flavours vs separate projects
But it's still a bit blur about the differences and how to choose between one and another.
So far the only differences, I manage to get out of it is:
Different structure
Modules can do everything that a Flavor does.
My first question is, what's the difference and what's so good about flavor that you don't use modules ?
Also, is flavor adapted for 2 applications where Application-1 and Application-2 share same code base (i.e. API, models, utils, service), but deviate from each other in terms of features and UI?
When to use modules:
When your project can be separated into smaller independent parts.
I've don'e this to my project, and my compile time went from 50+ seconds per iteration to less than 10 per iteration.
Because when I change code in 1 module, the others dont change and that's why the compile time is faster.
When to use flavours:
When you want to publish apps to different stores, and they need to have different applicationId
for example you want to publish to google play, and amazon store, and some other store that no one has heard of.
When you want to have part of your app available under certain build time conditions
When you want to whitelabel your app - basically it has the same logic but different UI, so in practice it is a completely different app, only... it's not.
Is it advantageously to have multiple modules in an Android Studio Project over having only a single large app-module?
I know about Android Modules in general and the advantages of SOLID so my focus is especially considering build performance. As gradle can do incremental builds, and if only one module changes, those other modules don't need to be processed?
Is this noticeable or is there even a considerable amount of overhead?
It is of great advantage to have multiple modules rather than to create a single large app-module. Following are the key points:
If you find the compile time is taking longer then you can disable the module from gradle you are not working upon temporarily and compile it faster.
A module helps us to divide project into discrete units of functionality also. You can create one data module which contains all pure java beans and can be used by multiple app if you are in same domain. Eg. Finance domain can have two applications one for viewing policies for customer and other can be for an insurance agent for viewing the same data. But the data module can be shared across all apps and even the data module can be borrowed from server or API team. Data module can be tested individually without any android dependencies and any one knows about java can write test cases.
Each module can be independently build, tested, and debugged.
Additional modules are often useful when creating code libraries within your own project or when you want to create different sets of code and resources for different device types, such as phones and wearables, but keep all the files scoped within the same project and share some code.
Also Android app module and Library module are different.
You can keep two different versions of module based on the API releases as from ASOP.
You can have a look for more on android developer resource
How modularization can speed up your Android app’s built time
App modularization and module lazy loading at Instagram and beyond
Modularizing Android Applications by Mauin
Survey on how Android developers were modularising their apps
There was an article on Medium yesterday, which exactly adresses my question:
https://medium.com/#nikita.kozlov/how-modularisation-affects-build-time-of-an-android-application-43a984ce9968#.at4n9imbe
tl;dr:
First and most important, the hypothesis was correct, modularising project can significantly speed up build process, but not for all configurations.
Second, if splitting is done in a wrong way, then build time will be drastically increased, because Gradle build both, release and debug version of library modules.
Third, working in test-driven way is much easier for a project with multiple modules, because building a small library module is way faster then the whole project.
Forth, doing many things in parallel slows down the build. So having more powerful hardware is a good idea.
Below you can find results of all experiments described in this article
Update
Addressed at Google I/O '17: https://youtu.be/Hx_rwS1NTiI?t=23m17s
i have to setup an android maven build for a customer, which previously was based on ant.
The base app is a white label implementation and the app is distributed to several third party customers. Each of those customer versions uses the same source code and a set of shared resources. But every customer also has some resources specific to their company (constants, assets, etc).
The structure of my android project looks like this. I only included relevant files/folders and the structure is remained from the ant build:
App
|--src
|--res
|--res-customer1
|--res-customer2
|--pom.xml
This means i have to build multiple .apk artifacts from the same source with different resources. What is the best approach to do this?
The first thing i tried was to use different profiles in my main projects pom for every customer. Then i wrote a shell script to execute all maven builds (1 per customer).
Then i came up with using only one release profile in my main project and passing the customer specific properties via command line. Properties are passed via a shell script, similar to my first approach.
But i'm not happy with that, so i thought about using multiple modules. One per customer. But my problem here is, how i can build those from the same source without copying the source from my main project over to all modules?
Or do i have to setup an android project for every customer and refer to my main project as apklib? Will this merge the shared and the customer specific resources?
Is there a best practice to do something like this?
Any other approach is also very welcome.
For only small differences it can be sufficient to just use profiles and a few different properties with resource filter. Profiles however are a bit of a bad pattern in the Maven world and can be hard to work with.
Your hunch to use separate modules for each customer and have the base application be an apklib is correct. I know of several people that have reported on the maven android developers list that this is what they use and works for them. I would personally use that approach in your case as well.
In general I would suggest to ask or at least mention this question on the mailing list.
I'm developing a series of applications for mobile devices, we'll call them Orange, Cherry, and Pear. Now, because of my familiarity with Blackberry, I chose to begin implementing the first of these three applications, Orange, on the Blackberry platform. I found a way to integrate a number of Blackberry platforms (since they use relatively the same API among different BB operating systems, with some exceptions) into the same codebase. Currently, my codebase looks something like this:
Orange/
trunk/
src/
... orange's source tree...
branches/
1.0/
... orange's source tree as it looked at release 1.0 ...
tags/
1.0.0/
1.1.0/
So, basically, I'm using a version-based methodology to my branching. Now, however, we want to migrate this application to the Android platform (and, at some point in time, probably to other mobile or even desktop platforms). So, my question is, what is the best method for branching with a single application across multiple platforms? I have read Branching Strategies, as well as a number of branching strategy webpages (e.g. http://www.codinghorror.com/blog/2007/10/software-branching-and-parallel-universes.html ), but I'm still unconvinced at branching based on having a 'common' trunk (e.g. as described in the last link as 'Branch per Technology').
The reason I remain unconvinced is that I'm a believer in the version-based branching strategy. It seems logical; if you want to maintain separate stages of development, then branches seem like the ideal way to do this. If I have aspects of the code that are 'common' between all three platforms, then I decide to make an android release, do I branch all of the code from the common and android trunks to make a new release tag? Or, do I keep all of the code in the 'common' branch in the android and blackberry branches as well?
I thought that perhaps another thing I could do would be to create separate projects, for instance orange-blackberry and orange-android. This might clutter my svn repository, however, since we keep all of our projects in the same repository. So, inevitably, I will have orange-blackberry, orange-android, cherry-android, cherry-blackberry, pear-android, pear-blackberry, along with a series of project folders for any other application I create.
So, I'm looking for some feedback about what might be the best way to manage all of this chaos. Also, if you could throw in some ideas about the logistics of transferring from my current implementation to the newer one, (i.e. what svn commands I should use to maintain history), that would be very much appreciated.
BlackBerry Java code is j2me, so source code must be Java 1.3 compliant. Android can use Java features all the way up to Java 6. If you want your app to look decent, you will be using the RIM proprietary UI components (net.rim.device.*) and those won't be available on Android.
I wouldn't consider an Android version of an application to be a branch of BlackBerry. You should just start from scratch. The platforms will share very little code, and the code that can be shared would be best factored into a library jar that both project incorporate.