I have an Android App that is published in a 'free' and 'pro' version. I have set up my project with a base 'library' project that is referenced from both versions, such that my package set looks like this:
com.example.myapp
com.example.myapp.free
com.example.myapp.pro
One of the Activity classes in my base 'library' project loads a help file into a WebView: WebView.loadUrl("file:///android_asset/help.html"). This class is extended in both the 'free' and 'pro' versions (for reasons outside the scope of this question), but I'd like both versions to reference the same HTML file (i.e. the one in the parent package). Under my current set up, however, the HTML file needs to be duplicated in the 'assets' folder under the 'com.example.myapp.free' and 'com.example.myapp.pro' packages for the "file:///android_asset/" URI to work.
Is there a way to specify the "file:///android_asset/" URI such that it accesses the 'assets' directory in the parent package?
A partial solution I found involves reading the HTML file from the 'raw' directory and then pushing the resulting string to my WebView object, but this would be messy to do for anything more than a text-only HTML page (e.g. one with images, like my one).
Cheers.
Since Andrew White didn't explain how to do what he recommends against, I'll show you:
Context otherContext = context.createPackageContext("other.package.name", 0);
AssetManager am = otherContext.getAssets();
That doesn't seem so bad. And I've verified that there's no need for the two packages to share a user ID.
As a developer that has both pro and free versions out there I can say from experience, don't try to share assets across applications. Even if you get it to work, you'll end up with more hassle than it's worth.
If you absolutely must do this, each app must share the same system user and you must create a context in one app that mimics the other. These aren't hard to do but and can be a maintenance nightmare.
Related
I know there are two well-known folders where one can put resources.
The first is the /assets folder, the documentation says:
Contains file that should be compiled into an .apk file as-is. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data.
The second is the /res folder, the documentation says:
Contains application resources, such as drawable files, layout files, and UI string. See Application Resources for more information.
Now i was wondering, there is a third option to create a resource folder "New > Folder > Java Resources Folder"
To me i looks like some part of the Android Plugin in IntelliJ because it has a little Android symbol in front of it .
Any ideas what the use of it could be? I couldn't find any documentation about it.
My first guess would be to use it in situations where you want to supply resources to a JVM Test.
In standard java world
Resources can be embedded directly in "your source tree" and used with Class's method getResource (see java documentation for a more precise description).
In android world
This practice is not recommanded (do not work at all, because such resources are removed from generated APK). You can still declare Java resources folders (see build.gradle :
sourceSets {
main {
resources.srcDirs = ['src/main/java/yourresourcesfolder']
}
}
And the result in the apk :
Conclusion
As resources's folder tree is removed,using java's resource folder become from my point of view, useless (in an android projet). Using android's asset folder is a better choice (also avoid resource's name conflict, but it's an another story :D )
This post is a bit old, but I want to bring an answer that explain one use case for the java resources directory on Android. If this folder exists in the options of a project it's because something can be done with it...
Enters the Service Loader, that helps to connect other services (aka libraries) into your main app, it can be used as a Gateway for your Android library to extend the functionality of a feature, exposing only the interfaces or abstract classes, with the Service Loader providing the implementation instead of your project having direct access to them.
Here is an example of how it's implemented. So, in summary the folder (META-INF/services) and files you have to create in order to use the Service Loader on an Android App, NEED to be inside this Java Resources Folder, otherwise your provider won't be able to see any implementation.
You can see it working in my sample here if you want to check it out: https://github.com/difereto-globant/test-library-feature/tree/1.0.9.
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/ .
The standard advice for sharing code & resources between Android projects is to use a library. Personally I find this works poorly if (a) the shared code changes a lot, or (b) your computer isn't fast enough.
I also don't want to get into deploying multiple APK's, which seems to be necessary when I use dependent projects (i.e. Java Build Path, Projects Tab).
On the other hand, sharing a folder of source code by using the Eclipse linked source feature works great (Java Build Path, Source tab, Link Source button), but for these two issues:
1) I can't use the same technique to share resources. I can create the link to the resources parent folder but then things get wonky and the shared resources don't get compiled (I'm using ADT 21).
2) So then I settle for copying the shared resources into each project, but this doesn't work because either. The shared code can't import the copy of its resources because it doesn't know the package name of the project that uses it. The solution I've been using is to access the resources dynamically, but that has become cumbersome as the number of resources grows.
So, I need a solution to either (1) or (2), or I'll have to go back to a library project. (Or maybe there is another option I haven't thought of?)
Your real problem is (2). Fixing (1) would eliminate some copying, but you would still run into problems with (2).
Unfortunately, that really isn't possible. There's a fair bit of fancy footwork that goes on to make multiple packages possible with library projects, and there's no good way to get that same result without library projects. Anything in res/ of a project is accessed via that project's R class, including your copied resources.
The solution I've been using is to access the resources dynamically
I translated that into you using getIdentifier(). That certainly works. Another approach is to having the hosting app supply resource IDs as parameters to the library code -- this is the pattern that the Android SDK itself uses. This is faster at runtime than the reflection-based getIdentifier(), and it gives the hosting app somewhat more flexibility, but you do wind up adding a bunch of parameters to your methods and constructors as needed to supply the various project-specific R values.
I have a non-standard Android application that has a requirement to load resources from an external file that is not part of the application apk. These resources will be packaged separately and delivered as its own package.
There are a few different types of items that will be part of this external resource bundle. One of those items includes the localized strings.xml file. This philosophy allows the change of a string / translation that does not affect the deployment of the application (in other words, application.apk stays in tact, but the only difference is a new strings.xml).
I've been searching around, and this doesn't seem possible. Is there any way? Or does this philosophy mean completely abandoning the resources all together and writing a custom layer to pull these strings and other external resources from a file?
The application is for Honeycomb platform.
Thanks in advance for any advise.
The best way to do this, I think, is to package your resources as a ContentProvider. See the guide topic Content Providers for how to get started doing this.
I'd like the ability to "overwrite" the Android resources packaged within my apk by having the app periodically download a zipped file containing overrides that follow the same naming convention as the source does. For example, the zip might consist of the following paths:
res/values/strings.json
res/values-land/strings.json
My code would parse those files and produce a Map> that would map the string resource id to a folder->value pair (or something along these lines). At this point I'm really only concerned with strings and images (maybe arrays), but not layouts, etc.
To the point: Is there any method available, that, given a list of folder names, would tell me which one the Android resolver would choose based on current state? I'm assuming this is difficult because the compiler breaks everything down to ids, but figured it was worth a shot. Any ideas?
Is there any method available, that, given a list of folder names, would tell me which one the Android resolver would choose based on current state?
No. You are welcome to roll this yourself based on Configuration, DeviceMetrics, and kin. You will also need to create your own parsers for your own files, as Android's resource system only works with resources, not arbitrary files retrieved from arbitrary locations.
The expectation in Android is that if you want to update resources, you update the app, probably because there were also code changes as well. Admittedly, this approach has its limitations.