I have some resources in my app that are going to be loaded optionally for different brands. I don't want to set up entirely different projects each time we re-brand the app so I want to know if the resources that are not used will be always packaged in and if there is a way to avoid this. Here's an example:
MyProject
/res
/layout
main.xml (used in all apps)
productlist1.xml (used in app ABC.apk)
productlist2.xml (used in app XYZ.apk)
main.xml should be packaged in both ABC and XYZ apps
productlist1.xml should be packaged with app ABC but not with app XYZ
productlist2.xml should be packaged with app XYZ but not with app ABC
I want to know if the resources that
are not used will be always packaged
in
Yes.
and if there is a way to avoid this
Use library projects. Or, create custom Ant tasks that filter the resources that get packaged in any given version of the app.
Related
I am creating an Android dependency library which will be packaged as an AAR file. The dependency will have layouts, strings, dimens, images etc. I created a sample demo project which includes this dependency.
Now consider the following scenario.
My library includes an Image file named filter.png and uses it inside a layout file. The demo project also has an Image named filter.png but it is a different image. So when the project gets built, only the app's filter.png is picked up. So even in my library's layout file, I am seeing the image used by the demo project.
As of now, I have changed the name and appended package name before every resource name to avoid the above scenario.
But is there any way I can force Android to pick resources only from the current module?
A library will only have access to its own set of resources, but nothing can prevent the application from intentionally overriding the library's resources.
To prevent accidental overrides, you usually prefix your library resource names. For example, AppCompat uses the abc_ prefix and the Design support library uses the design_ prefix.
Furthermore, you can explicitly declare which resources of your library are public, so that the other ones will be private by default and if the app overrides them you will get a Lint warning.
You app and library will have different package names, yes.
As of now, I have changed the name and appended package name before every resource name to avoid the above scenario
And that is correct because resources are associated by package name.
com.example.app.R.drawable.filter (Which is often just R.drawable.filter, check your import statements!), the current module.
vs some other module, com.example.library.R.drawable.filter
Android - Accessing Resources
[<package_name>.]R.<resource_type>.<resource_name>
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.
I have a small Android application that uses different sets of files (a couple of images, a small SQLite DB and a couple of XML files) depending on the specific task at hand.
I know I can include my files into the main application APK using resources or assets but I would be happy to distribute them in a separated APK.
How can I create a data-only APK file?
How can I distribute it? In particular, do I have to do anything special for a data-only package (for example for associating it to the main application package in some way)?
(I'm intentioned to give the user a link to the data package and ask him to install it. No automatic installation required.)
How can I install my files into the internal or into the external storage area of my application? Is it possible at all to install files into the internal storage area created by the main application installer? Do I have to set any particular permission for this?
My approach to this would be to create a wrapper app that's nothing but a content-provider and serves up the files per request by your main app. This would allow you to supply different data packages for the user -- you could even have your main app select between those relatively easily.
It looks like that the commonly accepted way to have the same application with different contents (or styles, or configurations) is to use an Android Library Project for the common code (that is: the whole application, the "engine", the "app framework") and a standard Android Application Project for the contents (that is: an application that actually contains just data). A little bit confusing, just because the "library" here is actually the whole "app", but this seems to be the way to go.
More in detail:
Create an Android Library Application and put into it as much code as you can (all of the non-changing stuff). Please note that this library cannot be launched and cannot be distributed alone. It must be included in a hosting application.
Create a standard Android Application. Include your library into this project. Put in /res and in /asset all of your data (files, XML, etc.).
Compile everything and distribute.
Repeat this cycle every time you need a different version. Different because of data, style, configuration or anything else. Publish the resulting app with a new name.
For what regards me, I'm not completely satisfied by this approach.
A possible alternative is preprocessing the source code with Ruby, Python, Perl, GIT, bash, Ant, Maven, Rake or any other tool that is able to read a file from here, make some change here and there, and write the file there.
The general outline is something like this:
Make a "template" application. Leave your /res and /assset empty.
Run a custom-made script. The script reads a configuration file, copy the /res and /asset files from your repository into the project /res and /asset directories, changes some Java source file and creates/changes some XML file.
Compile and distribute (with a new name, of course).
Using GIT or other SCMs, you just make a new branch for every new version and compile it. Not very elegant (because it can strongly interfere with the normal use of the SCM) but...
There are a few example of these approaches on the web. I'm not completely satisfied by them, either.
Frankly, what the Android ecosystem should offer to solve this problem is some kind of "in-app package manager". Something like the Eclipse Update Manager. This would allow us to use the same application framework to handle different scenarios.
As an alternative, a solid, officially-supported, template-based code-generation mechanism would be nice. Something in the spirit of "Software Production Line": https://en.wikipedia.org/wiki/Software_production_line . Have a look at fw4spl, for example: http://code.google.com/p/fw4spl/ .
I'm trying to find the best way to build/package an Android app for 6+ different customers. I could use different branches in SVN for all of the customers, but the only difference between the apps are some values in the resource folder (drawables, strings, etc).
I wrote an ant script that imports the standard Android build.xml. This script does the following:
Reads the customer names from a properties file.
For each customer the following is done:
The package name in AndroidManifest.xml is changed (by hooking into the -pre-build target).
The custom resources are copied into the res directory in the build (by hooking into the -pre-compile target).
The package name is changed back to the default value (by hooking into the -post-compile target).
The APK is copied to a specific location an named something like customer-versionno.apk.
This seemed to work well until I just now wrote the part that changes the package name. Because of the package name change the location of the R class is also changed, meaning that the build fails as the Java classes import the R class from the standard package.
I don't want to have a build script that changes code. I want to be able to do this with minimum changes to any files.
Soo..the questions are really:
Are there any good/simple solutions for my problem?
Am I approaching this problem in the wrong way? Are there better ways to easily package the same app to 6+ different customers?
Do you really need to change the package name? Changing the package name is a pain to do automatically. That being said, here is my solution to the problem:
My scenario is that I have one app that gets deployed to 30-200 different signed APK files where the only difference between the files are some resources (drawables, strings, values etc), and the package name.
I do this by working on a generic version of the app that serves as the template project. Once this works and I am ready to deploy I invoke a bash script that loops through the following steps for each target:
Clean the project completely
Swap out res dir and package name using sed.
Builds and signs the APK
This balances the horrific deply time with fast developemnt time. I really don't see another more elegant/robust solution than this.
And finally a small tip: In android manifest use relative package names like ".Application" instead of "com.mycompany.myproject.Application". This way you only need to change the package name in ONE location.
Is it possible to solve this with making 6+ different projects that includes your main projekt. This way you are able to override resources and make different apk's
Is it possible to share resources across APK's? For example, can application A (in APK A) load an icon or layout view from application B (in APK B)?
You can make use of getResourcesForApplication
That way you can load whatever you want from other app package as long as you know at least the package name and the id or name of the resource to load.
As a side note, layouts cannot be loaded without further processing them with an XMLResourceParser because of possible id mismatches between your app package and the "guest" package.
Two different apps can share resources - images/ files,etc. if they are signed with same certificate.
Please check android doc here
Only if it is delivered by content provider and the content serialized.
You can have two applications use the same Android library, which lets you share resources like activities, etc.
An Android library project is a
development project that holds shared
Android source code and resources.
Other Android application projects can
reference the library project and, at
build time, include its compiled
sources in their .apk files. Multiple
application projects can reference the
same library project and any single
application project can reference
multiple library projects.