Assume I've got 2 Application A and B.
I want to access resources (drawables, images, strings) of an B application from A application. How would I do that?
Edit:
You can also designate an Android project as a library project, which allows it to be shared with other projects that depend on it. Once an Android project is designated as a library project, it cannot be installed onto a device.
Does it mean That I can not use my library on android market?
My aim is to use default resources of Application A, but also if someone what he can download Application B and use it resources.
If you are the developer of both applications then the right approach would be, as othes noted, to create an Android library project and share it between apps.
Nevertheles, you can still access resources from another app, even if this is not your app:
Resources res = context.getPackageManager().getResourcesForApplication("com.example.foo")
If both apps are your own and you want to bundle these resources at build-time:
Create an Android Library Project, put all the needed resources into it and reference it from both your apps.
Edit to your edit:
You can use the library in the android market. You just can not use it alone (compile it). You have to build an app that uses the library. When you build that app, all the needed content gets basically grabbed from the library and copied to your apk. Which you can put on the market as usual.
This does not work when you want to access resources from an app that gets downloaded onto the device at runtime. A library project bundles all resources when you build the app that uses it. Peter Knego's response is the correct one when accessing at runtime.
It is possible if those both application are yours. Or you can used any Android Library for both these application. If you want you also create your own Android Library for this kind of work. Thnx.
Peter's answer above is great, but I'd like to elaborate a little more...
When you control appA and appB and want to get a drawable from appB, while in appA, then do the following:
Get the identifier of the drawable when in appB (for example, R.drawable.iconInAppB)
Then, in appA
Resources res = context.getPackageManager().getResourcesForApplication("com.example.appB");
Drawable d = res.getDrawable(integer);
//integer was what appB assigned to R.drawable.iconInAppB
*Note: The integer id assigned to R.drawable.iconInAppB will change over time so don't rely on hardcoding. I save the key-value pairs (String resourceName, int resourceId) in a database in appB and access them using a content provider.
For example, let's get the string-array with the ID of entryvalues_font_size from the package com.android.settings
String[] enries = null;
try {
// You can get PackageManager from the Context
Resources res = getPackageManager().getResourcesForApplication("com.android.settings");
int resId = res.getIdentifier("entryvalues_font_size", "array", "com.android.settings");
if (resId != 0) {
enries = res.getStringArray(resId);
}
}
catch (NameNotFoundException e) {
e.printStackTrace();
}
Related
Can I somehow alias a generated R file from a library and a generated R file from an application?
IE: I have two projects, one being a library. I reference the library in the application.
The library creates one R file, the application creates two: com.example.mapplication.R and the R from the referenced library, com.example.mlibrary.R. However, since I want to use both frequently in the application, I want to alias both the R classes. For example, call the library R something like libR and the app R something like appR.
I tried a couple of things which are of such stupidity, I won't even fully mention them, but I did some things like private com.example.mapplication.R appR = com.example.mapplication.R (immediately realising this wasn't gonna work), and private Class<com.example.mapplication.R> appRclass = com.example.mapplication.R.class;, but that didn't give me the desired effect. I do, however, use the latter method and some reflection to make it possible to be able to get the field and inner classes like this:
Class<com.example.mapplication.R> appRclass = com.example.mapplication.R.class;
int activity_main_layoutid = Toolkit.getFromClass(appR).
getMeTheInnerClass("layout").getMeAField("activity_main");
I haven't fully implemented the Toolkit method, but as we all know refletion can do this kind of stuff, but at the end of the day it's just as much work as just typing com.example.mapplication.R or com.example.mlibrary.R everywhere.
So to wrap thing up: Is it possible to alias multiple R's so that I can use appR and libR to distinguish the two?
I wish we could, but according to what I know, it isn't possible, at least not yet.
I also wish we could put resources in sub folders, but even this is impossible.
What you can do is setting a unique prefix (rename each resource file) for each library, as it's done by some third party libraries (like actionBarSherlock, which uses "abs" as the prefix).
Alternatively, you can have a special trick and put the files in the src folder and reach them from there, but that's more of a workaround, since the R won't have a reference to any of the resources there.
For example, you can put an image called image.png into the src/com/company/app_name, and then create a bitmap from it using:
final InputStream fis = getClass().getResourceAsStream("/com/company/app_name/image.png");
final Bitmap bitmap = BitmapFactory.decodeStream(fis);
By the way, if you've thought of using the assets folder, you can't do it for library projects, since it requires you to have the files in the project that uses the library project. It will work, but it misses the encapsulation idea...
I'm trying to write a tristate switch. But I'm failing to access the default com.android.internal.R.styleable.Switch_track drawable to use as background.
How to get that drawable?
Is there another approach for getting the default background?
You should not access private resources, you can't be sure that the resource will be available on all devices. And even if it is available, you can't be sure it will be the same.
If you want to use a private resource, you have to copy it into your project resources from SDK or Android sources.
Just for reference:
While it is not advised to access internal resources and you should be aware, that they can change or could be removed by a vendor or with an OS update, it is possible to access them at runtime:
int id = Resources.getSystem().getIdentifier("Switch_track", "styleable", "android");
I'm working on a Android application and using this nice class to load a resource file, located in the applications res/raw folder, as a Java String:
public class ResourceReader {
public static String resourceToString(Context context, int id) {
try {
Resources res = context.getResources();
InputStream in_s = res.openRawResource(id);
byte[] b = new byte[in_s.available()];
in_s.read(b);
return new String(b);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
The context is the Activity based application class, the id is found using R.raw.mytext. The resource is a file, created in the mentioned folder.
When used in the app, it is no problem to get the file's content as a string with this line:
String content = ResourceReader.resourceToString(this, R.raw.mytext);
As the resources I read are likely to be used in other applications, I would like to put not only the classes, but also the resources into an external JAR file.
In eclipse I can create an android jar file, complete with resources and associated R class. The integer values associated with the names are accessible as expected, but how do I read the content?
I need to get the resources of the library, not those of the application.
The resourceToString method needs a context:
Resources res = context.getResources();
The Question is: is there a library context? And how do I get this context? - Or any other method to access the content of a library resource?
You can create an Android library. The output shall be an arr file which includes the classes and resources.
You may check Create an Android library for details.
The following is an excerpt from that page:
An Android library is structurally the same as an Android app module. It can include everything needed to build an app, including source code, resource files, and an Android manifest. However, instead of compiling into an APK that runs on a device, an Android library compiles into an Android Archive (AAR) file that you can use as a dependency for an Android app module. Unlike JAR files, AAR files can contain Android resources and a manifest file, which allows you to bundle in shared resources like layouts and drawables in addition to Java classes and methods.
A library module is useful in the following situations:
When you're building multiple apps that use some of the same components, such as activities, services, or UI layouts.
When you're building an app that exists in multiple APK variations, such as a free and paid version and you need the same core components in both.
In either case, simply move the files you want to reuse into a library module then add the library as a dependency for each app module.
I had developed 3 applications in android where the major functionalities are the same but the UI looks different. Images and the background color of the screens are different.
NOw, i want to create a single code base from which i can generate multiple .apk files for the 3 apps.
I tried creating 3 different packages for src folder for the 3 apps. But i dont know how to set the res folder for these apps.
Need pointers on creating a single code base from which we can generate multiple .apk files which includes only the respective src and res folders.
Use an Android Library Project that contains all your common code.
Create separate Android projects that reference the Library Project (you will need to copy your Manifest into each of these and make sure all components are declared with their full Java package name).
Put any resources specific to each app (drawables, colors etc) into the individual project resource folders and they will override similarly named resources in the library project at build time.
i think the best option is to use ant, you'll need to add an ant target for each build and change the resource folder.
if you use the generated build.xml, the res folder is defined like this
<property name="resource.absolute.dir" location="res" /> so you'll want to override that
Can't you put all of your common code into a library project and then just reference that project from each of the 3 unique projects that each contain the relevant resources.
Update: This answer is now obsolete when using the Gradle build system.
Why don't you use a single application, that does three different things based on SharedPreferences values set by the user, or from context at install time. If you really want to separate, you can have three different activities, and you decide which one to launch from a silent main Activity that redirects to either of the different ones.
An alternative is to have a unique activity that inflates itself dynamically from 3 different layouts at onCreate time.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (...custom check for layout... equals(layout1)) {
setContentView(R.layout.main_layout1);
} else if (... equals(layout2)) {
setContentView(R.layout.main_layout2);
} else if (... equals(layout3)) {
setContentView(R.layout.main_layout3);
} else {
throw new IllegalStateException("Unknown layout!");
}
... your onCreate stuff....
}
It will make code maintenance easier (only one code source to modify, only one version-list and changeset to maintain)
Check here:
How to use SharedPreferences in Android to store, fetch and edit values
I would suggest using Gradle flavors.
It seems to explain all the basics really well. I just finished converting to Gradle today, and it works great. Custom app icons, names, and strings, etc.
As the website explains, part of the purpose behind this design was to make it more dynamic and more easily allow multiple APKs to be created with essentially the same code, which sounds similar what you're doing.
Also see a recent question I had, referring to your project structure and using custom code for each app.
I am trying to separate an application into an app project and a library project (besides moving it from Netbeans to Eclipse). The app will contain resources that are used by the library - for this, I had read on Stackoverflow that we can bundle the resources in the library project and then override them in the app project.
But when I did this, I am getting the error:
...\res\values\attrs.xml:5: error: Attribute "pageBackground" has already been defined
Am I doing something wrong here? Any of my assumptions is faulty?
Thanks,
Rajath
I think I had similar problem when I tried to create a kind of 'configuration file' which was placed in application's resources and was meant to alter behavior of library it used. What I found working was using getIdentifier method from Resources instead of refering directly to R class:
final int resId = getResources().getIdentifier("my_resource", "raw", getPackageName());
You can then use the identifier as normal resource ID, e.g.:
if (resId > 0) {
final InputStream is = getResources().openRawResource(resId);
// ...
}
The idea was to handle both situations: when the file was present in app's resources or when it was not. But I think it should also work in your case of "overriding" the resources from library in application, thanks to getPackageName providing appropriate package name for resources' identifiers' resolving.