Android: Programmatically change SourceSet based on user settings - android

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

Related

Build-time resource/layout selection in Eclipse for Android?

My company ships Android devices to control industrial equipment we make. We only ship one specific device running Android 2.36 that we buy in quantity and load our own app on, so we don't have to worry about accommodating different layouts, resolutions, etc.
We have a customer in Israel who would like us to have the legends on our buttons in Hebrew. Android 2.36 doesn't have good support for Hebrew (or RTL languages in general) so what we thought we would do is replace the text for these buttons with an image of the Hebrew text.
Since Hebrew is not a supported language on these devices I can't just put the whole device in Hebrew and have Android select the layout XML files with the images instead of text to use at runtime, so I think I might have to do it at build time, in other words have some kind of switch or setting that says use THESE layout resources instead of THOSE layout resources when building a Hebrew version of our product.
My Question: What's a good way to do that? Is there a simple way to force it to use a particular set of layout XML files at build time or am I thinking about this wrong?
If you're using Gradle for Android with Android Studio, this would be a fine place to use product flavors:
Have the bulk of your code and resources be in the main sourceset as normal
Define standard and hebrew product flavors in your build.gradle file
Have the normal (non-Hebrew) resources be in a standard sourceset
Have the Hebrew resources be in a hebrew sourceset
Then, a hebrew build will use the Hebrew layouts, while a standard build would use the normal layouts.
If Gradle for Android is not an option, since you control the hardware, you could drop some file in some special spot on the device, and check that when your process starts to determine if you should be in Hebrew-compatibility mode or not. This presumes that the users of the Android device do not have arbitrary access to it (so external storage would be safe) or that you inject the file into internal storage after installing your app (adb shell run-as should handle this, though I have only ever used it for read operations, not write operations).
I was going to say you could use the layout-LANG to specify region based layouts, but I don't think you can do that if the language isn't supported there.
https://developer.android.com/guide/topics/resources/localization.html
Does your app have a settings screen? You could simply have a setting to change all the layouts in run time.
Do you use Android Studio? Android studio allows different build profiles for debug, release, etc. You could set one up for Israel.

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.

Multiple app installer or multiple launchables

I want to create an "app loader" (primary) application, which will fetch a license from a server -- this license in turn will determine the features available in two other (secondary) applications.
I'd like to know the best approach to this. Should I:
just fetch the two secondary apks from the same server as the licensing info and attempt their installation from within the app loader code;
pack the secondary apks into the primary app apk. Am I able to then install the secondary apks from within the 'parent' apk's resource/assets at runtime?
recreate the secondary applications as multiple activities within one parent app -- with multiple launchers?
I require advice on the individual scenarios' feasibility, a preference (with a reason why) and indeed which ones are actually possible.
Many thanks.
Am I able to then install the secondary apks from within the 'parent' apk's resource/assets at runtime?
Not without copying those files to external storage. Since you cannot modify resources or assets at runtime, your "packed" "secondary" APKs will remain in the parent APK, for better or worse.
I require advice on the individual scenarios' feasibility
All are feasible, within the constraints outlined above.

How to maintain different versions of an Android app

I have a question I cant find an answer to anywhere. Suppose I have an app which basically has some content catering to a group of users. So I have the source code checked into some sort of an SVN , and I have an apk generated which I use as required on the tablet. Now I have a different set of users. The only thing that changes are logos in the app which are images in the drawable folder, language of the app and content within the app. Now how can I dynamically pick the right logo or language based on the user. Based on what I understand I have to build the source code again using the parameters required and generate another apk. Is there no way i can communicate with the apk as to who the user is and it can show the right logo.? Is there any method kind of like String_Resources.xml in the .Net world.
Handling Screen Sizes
http://developer.android.com/guide/practices/screens_support.html
Handling Localization
http://developer.android.com/guide/topics/resources/localization.html
These 2 resources should help. I'm not sure what you mean by 'pick the right logo or language based on the user." Users Device or Users Language??
The system language settings on the users device will determine which language folder to use (if you have them set up as outlined in the second link).
If you want select a logo based on screen size, see the first link. Basically you create identical xml layouts and put them into separate folders like:
layout-normal
layout-small
layout-large
layout-xlarge
then just change the drawable in the xml file for each screen size.
No, you need to generate new apk with new app package e.g.
myapplication.company1
myapplication.company2
...
myapplication.companyN
This topic may be helpful

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.

Categories

Resources