Build different APKs for different environments (Xamarin.Android) - android

We're building a Xamarin.Android application that connects to the cloud.
We have different Cloud URLs for different environments, namely Development, Staging and Production.
I find myself manually changing URLs everytime I generate an APK for a particular environment.
I came across Gradle/ANT ways of changing "flavours" but since it is not available in Xamarin, How do I go about it? How does one manage different environments in Xamarin? Is it using MSBuild config files? Any help would be appreciated!
EDIT:
What I currently have:
/// <summary>
/// The application URL for PROD
/// </summary>
//private const string ApplicationUrl = "https://prod.azure-mobile.net/";
/// <summary>
/// The application URL for DEV
/// </summary>
private const string ApplicationUrl = "https://dev.azure-mobile.net/";
In this case, we manually comment/uncomment URLs for different builds (Dev/Staging/Prod) and generate APKs. I understand it's not an optimal solution and is prone to mistakes.

I would probably define different build configurations (in the Project Options) for Development, Staging and Production. You could then define symbols (in the Compiler page of the options) and use preprocessor directives to change the definition of ApplicationUrl in the code. Building each one is then just a matter of selecting the appropriate configuration in the drop-down.
I'd also change the output path for each configuration so the APKs get written to different folders to reduce any possible confusion about which configuration each APK is built with.
Disadvantage is that if you change any other project options you need to ensure you make the change for every configuration, but as this isn't done very often it's probably a reasonable compromise.

Related

Android: Programmatically change SourceSet based on user settings

I am creating an app that has admin and user modes, and each mode has its own layouts, strings, and drawable resource files. I want to know how to change the resources SourceSet based on the app mode which can be toggled by the user at runtime.
Currently, I am using 2 product flavors to do this. But the problem with flavors is that it is build time, and I have to create 2 different apks, one for each flavor. So, being able to change SourceSet at runtime means I can have only 1 apk.
Update: I simply want a textview to call R.string.title, and this will call different string files based the user mode (Admin or user). This is the same as changing Locale language (en vs fr for example) will call the appropriate file without the need to change the code.
I want to know how to change the resources SourceSet based on the app mode which can be toggled by the user at runtime.
That is not possible. Source sets are a compile-time construct. An APK contains the contents of source sets based on the build variant you chose when you compiled the APK — the contents of other source sets are not in that APK.
I am creating an app that has admin and user modes, and each mode has its own layouts, strings, and drawable resource files.
Then either those are two apps (and two APKs), or you need to have all of those resources in the one source set that goes into your one APK.
Usually, an admin mode also involves dedicated Java/Kotlin code (e.g., dedicated fragments), and so just swapping resources would be insufficient, anyway.
If you are distributing solely through the Play Store, you could look into using dynamic feature modules, if your concern is the size of the APK with both user and admin code/resources in it.
The solution which worked for me in case there were corporate applications where default launcher was locked and user launched login screen by default there were two separate applications which were switched depends on the role of the user. In other app where one apk I just made different screens launches with its own logic based on role user choose.
But that also might help you Dynamically generating product flavors

Store android settings in editable config

I am looking for the best way to allow developers / testers to point an app to the UAT server rather than the default, PROD, in an android app. As with .NET or Java, where I would have an app.config or properties file allowing you to change the URL prior to running the app, I would like to understand the common approach on android apps?
The data storage options outlined in http://developer.android.com/guide/topics/data/data-storage.html are clear, but none of them seem to quite fit unless I am missing something.
Shared preferences and InternalStorage seem the best fit, but with shared preferences it looks like I would require root access to modify the file and with InternalStorage no API is provided for parsing the settings, so just wondering if I have missed something obvious.
Any advice?
You can achieve this in a slightly different manner by maintaining different build flavours. With different build flavours, you can have different configuration files for different flavours. So make different build flavours one for production and one for testing and put all your files which are different for production and testing separately in two flavour packages and you can build which ever flavour you want.
Check this link for further reference

Android compile with different resources (white label)

We have an Android project where we maintain a single code base for different customers, what will be the fastest/most efficient way to compile for different customers every time? Few options I found and my questions:
writing scripts: to replace resources folder and edit app name, version, etc.
Using Android Library Projects It is gonna be quite impractical to separate current project as Library projects, I am thinking whether it is possible to save some settings and resources files as a Library project and just import different library projects for different compilation?
Storing settings and resources on a remote server Is it possible to store resource files and some app settings (xml, constants, etc) on a remote server, and download them and replace to the app when the user first launch the apk? Where will these files be stored?
Any other options you would suggest?
Android Studio provides a feature called "flavors" that allow you to quickly define different configurations from a single code base. I have just learned about this in the last couple of days, so I don't know a lot more than this.
The best way I've found is a post build script step. Use a default set of resources/assets for your main build. This is your default apk, use it for default testing. Save the unsigned apk this builds. Then for the customer specific APKs, open up the unsigned apk (its just a zip file), overwrite any overwritten files, then sign the new version.
This works fine so long as you don't need to change code for different customers. It also doesn't put any unneeded assets/resources in any build, so you don't leak info to one customer about your other customers by including their files.
If you do need to change code, the best way is to do a runtime check on a variable from a settings file. And overwrite the settings file the same way you do everything else.
As an added bonus, if you need to you can write a very fancy system that would allow the customer to upload his own files to override your defaults (including allowing them to override some of your settings), so you don't need to deal with a dozen change requests. That requires a lot more work though.

Brandable Android Application

We service multiple clients. One feature we want to offer is an android application which allows the client to custom brand the application (icons, logos, names, etc).
Here are a few stipulations.
Customers of clients will use this app.
You could be a customer of more than one client, but we cannot show the user any kind of list of clients.
Clients cannot share a single app.
The app must be able to look different per client, even though the functionality is the same
Yes, I know it's a PITA to build it this way, but our clients don't want customers of other clients to know they are also our client.
So, what is the best way to build an easily brandable application with as little strain on the developer's sanity as possible?
Keep a separate res/ folder for each version of the app. Give every icon, logo and String the same name but tailor the content for each client, and build a different .apk for each by simply dropping that res folder into the build. I don't think you can make custom qualifiers work for this and just make a single .apk - and this would in any case bundle every client's custom pictures and Strings in to everyone's application.
I would start by developing a script for a global re-name, since you'll need that anyway (can be done fairly simply with find, xargs and sed)
You'll need tools for making the customizations to resources, that could be the SDK & Eclipse plug-in
Perhaps you could create some kind of wizard extending the Eclipse plug-in.
Or with a lot of work but easier usage, you could do something stand alone that drives the necessary command line tools to build the generated package.
You can do what #Jems said or (presuming that the app comunicates with a server) put the "logic" on the server side.
The first time you run the application the server will send you the resources corresponding to your client that you store locally.
Problems with this approach: The first time you may have to download a load of stuff...
Advantages: You just have to change a properties string saying which is the server, or the login to the server to know what it has to send changing the layout without having to deploy another app with different resources.
It really depends if you want to support layout changes on server side.
Build time solution using gradle could be achieved with productFlavors feature, described in http://blog.robustastudio.com/mobile-development/android/building-multiple-editions-of-android-app-gradle/
Flavors (aka customer brands) could be defined in build.gradle file in the following way (different package names are here to deploy each branded apk as separate application):
productFlavors {
vanilla {
applicationId "com.example.multiflavorapp"
}
strawberry {
applicationId "com.example.multiflavorapp.strawberry"
}
}
Specific android resources for brand could be then placed (instead of src/main/res directory) into src/vanilla/res or src/strawberry/res directories (in this case vanilla and strawberry are the brands). Please be aware that using productFlavors feature, gradle does no merging of assets, only simple replacing files without any knowledge about specific res subdirectories.
During building proces gradle creates build variants as combination of build type (debug,release) and productFlavor, more at http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Type-Product-Flavor-Build-Variant.

how to manage multiple editions of the same android app

I have 3 editions of my android app. one free with ads, one paid and one branded with company CI.
so the difference betwenn them is minimal.
what is the best practice to manage multiple editions of this app.
one project, in code if (editionA) { ... }
multiple projects, reference common code in extra project
or something else ?
Update on the link and detailed description;
1. Library Modules
2. Setting up Library Project
Use an Android library project for the common code, with tiny projects for each specific flavor.
I do something similar with my apps. Common code base, several different sets of resources. I have a python script that copies my generic source from a common location to the src directory, copies the res_project directories to the res directory, updates the package names to reflect the new application package and update the AndroidManifest with the appropriate values.
I felt like there should have been a better way to do this, since your resources are already nicely segregated from your source, but had problems with an application package name that differed from my src package name. I blogged about that process in detail here.
I'd say 2, makes for the most flexibility + you can have different package names so your able to have them all installed at the same time on you device (if you want/need to)
Create a Master activity that has all the functionality, use sub activities and layouts for the 3 types of access?
This way you only have to maintain 1 project and core functionality.
Just have an initializer on start up which detects which activity to start.

Categories

Resources