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.
Related
When I make an app with package name com.example.app, src/com/example/app/MainActivity.java is created automatically. I am new to Java and I don't understand
why it uses so many folders inside folders? Why isn't it just src/MainActivity.java?
In order to avoid namespace collisions and conflicts, it's a common best practice in Java nest source code within a folder structure that is the reverse of the internet site associated with it. If everyone created jar library files in the root /src directory, eventually you'd have a collision and the code wouldn't be usable.
For instance, if I have some fancy Android library and I provided a class called Button, in a Button.java class, and you also at times wanted to use some other library that also had a Button.java in /src, your project would not compile.
Thus, in order to let everyone have their own unique Button class, the convention that was adopted was for everyone to use their reverse domain name, followed often by the project name. So the Facebook SDK, fo instance, has /src/com/facebook/android/Util.java while my own project has /src/com/myapp/misc/Util.java and I can use and reference both in my source code.
For the application I'm working on I was thinking to define few property files, something like: debug.properties, beta.properties, release.properties. These files mostly will contain urls to their corresponding environments. Depending of some flag I will set, the application will load the corresponding property file and read the values from there.
I was thinking to put these files in assets or raw resource folder, but after changing the extension from .apk to .zip of my application, I noticed that these file are accessible and readable.
If you had prior experience, what are the best practices for configuring different build environments in Android?
Is there a better place where I could put the properties files so they cannot be accessed?
I had the same need in my app and found the same problem you found: It's to easy to open the apk and edit the properties files.
The solution I chose was to put those environment-specific properties in some Java source files.
We have one Android project per environment. Each project is almost empty and refers to an Android Library that actually contains the app's code. Each Android project contains a Java file declaring its environment properties.
This seems counter-intuitive to use Java instead of properties file, but when fighting against piracy, all ways are good. The Java files can be obfuscated if you use Proguard. Even better, you can use Dexguard that can encrypt the strings in the Java source so that it will extremely hard to tamper the source and make the properties point elsewhere.
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 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.