Load resources with variables? - android

I am loading XML file resource like this,
getResources().getXml(R.xml.fiel1);
Now, the scenario is that depending on factors there may be many xml files to choose from. How do I do that?
In this case the filename is similar in the fact that all starts with file only ends with different numbers like
file1, file2,file3 etc., So I can just form a String variable with the file name and add a suffix as per requirement to form a filename like file1 (file+1).
Problem is I keep getting various errors (NullPointerEx, ResourceId Not found etc) in whatever way I try to pass the filename variable to the method.
What is the correct way of accomplishing this?

You could use getIdentifier() but the docs mention:
use of this function is discouraged.
It is much more efficient to retrieve
resources by identifier than by name.
So it's better to use an array which references the xml files. You can declare it as an integer array resource. Eg, in res/values/arrays.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="xml_files">
<item>#xml/file1</item>
<item>#xml/file2</item>
etc...
</integer-array>
</resources>
And then in Java:
private XmlResourceParser getXmlByIndex(int index) {
Resources res = getResources();
return res.getXml(res.getIntArray(R.array.xml_files)[index - 1]);
}
Of course, you'll need to update the array whenever you add a new xml file.

You can use the getIdentifier method of Resources to find the id.
Resources res = getResources();
for(/* loop */) {
int id = res.getIdentifier("file" + i, "xml", "my.package.name");
res.getXml(id);
}

An alternative to the getIdentifier suggestions, assuming the number of resources is fixed at compile time, would be to create a static mapping between an identifier and the resource.
So for example you could use the suffixed numerical ID:
class Whatever {
static final int[] resources = new int[] {
R.xml.file1, R.xml.file2, R.xml.file3
}
}
This would allow you retrieve the resource with a simple index operation.
getResources().getXml(resources[i]);
Alternatively, if you needed a more descriptive mapping you can use any one of java's Map-based classes.
class Whatever {
static final Map<String, Integer> resources = new HashMap<String, Integer>();
static {
resources.put("file1", R.xml.file1);
resources.put("file2", R.xml.file2);
resources.put("file3", R.xml.file3);
resources.put("something_else", R.xml.something_else);
}
}
With this you would then get(String) the value by its name.

Related

Android Studio find xml data file by name

the problem is that I have various XML files with the data that I need for my app and I want to access to read them by the name of the XML file: "fileName.xml" so I can run the pull parser. Since the program only knows which file to load by its name which is given by a string I can't call them using r.id.fileName.xml.
I have tried things like:
int resID = getResources().getIdentifier("r.id.fileName", "id", getPackageName());
and then call it by this resID... but it doesn't seem to work (resID is always 0) :(
Any ideas?
Thank you!
The best solution from a performance standpoint is to have a mapping in your Java code between some string and the resource ID value:
private static HashMap<String, Integer> RESOURCES=new HashMap<>();
static {
RESOURCES.put("thingy", R.xml.thingy);
RESOURCES.put("thingy2", R.xml.thingy2);
// and so on
}
Then, you can just call RESOURCES.get() to retrieve the ID value, without having to use the reflection that goes on inside of getIdentifier().
If you really want to use getIdentifier(), then the syntax would be:
int resID = getResources().getIdentifier("fileName", "xml", getPackageName());
because:
the first parameter is the base name of the resource
the second parameter is the type of the resource, and the files in res/xml/ are not id resources

Can you select a string resource with a name like

I am thinking of creating a small dynamic layout using strings.xml as a base.
I know how to select single resources but is there a way of selecting ALL resources with a name like "Intro_"
A bit like a Select where like query.
So if i had some strings like;
Intro_Welcome
Intro_FirstParagraph
SecondScreen_Welcome
List of strings mList = select all string resources with a name like "Intro_"
mList would now contain the string of Intro_Welcome and Intro_FirstParagraph
Any help is usefull
Thank you
You can't do this like you described. The string resources name that you define in your xml file are mapped into int values. So, when you use they in your code, you use by the int value created.
You may consider using a modified version of this class, that can get the string resource id within the string text.

Resources.getIdentifier(), possible values of deftype argument?

I'm trying to understand an Android app that performs computations on investment portfolios. The portfolios are stored in res/values/portfolio.xml:
When a button is pressed in the app, the portfolio data is retrieved as follows:
String portfolioName = ((TextView) findViewById(R.id.portfolioName)).getText().toString();
Resources res = getResources();
String[] data = res.getStringArray(res.getIdentifier(portfolioName, "array", this.getPackageName()));
I found the Android documentation on the String Array resource type that explains the syntax of the portfolio.xml file, and it explains why the name attribute should be used as the first argument of getIdentifier():
“The filename is arbitrary. The <string-array> element's name will be used as the resource ID.”
But I haven't found any documentation that explains how you know what you're supposed to put for the defTypeargument of getIdentifier (other than that it's a string). In the provided example, "array" works, but where does it come from? And what are the possible values of 'defType' in general?
getIdentifier returns the id of the resource for the given resource name. typeDef refers to the type of the Resource (read more here). Keep in mind that the content of res is parsed at compile time and the R.java class is generated from the result of this parsing. In the end what you are looking for is a field declared in that class. I don't know the internal implementation, but if you provide array as res type, android will look up only on R.array, instead than on the whole R

Android get list of string resources from special file

For example, i have my_string.xml file with strings:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="my_string">My string</string>
<string name="another_string">Another string</string>
{...}
</resources>
Is it possible to get this strings to list/hashmap programmatically? Yeh, i know that i can take it by name or something like this. But i need to get it dynamically programmatically, for example, to HashMap<String, String>
Or all string resources will merge together after building and it's not possible to separate it?
If you want to access all the Strings from the strings.xml file you could use reflection on the R.string class.
Field[] fields = R.strings.class.getFields();
String[] allStringsNames = new String[fields.length];
for (int i =0; i < fields.length; i++) {
allStringsNames[i] = fields[i].getName();
}
You can then store them in Hashmap or wherever you want
Put the file in the raw folder. Then you have to open the file
InputStream in = getResources().openRawResource(R.raw.yourfile);
and parse the content manually, for instance save the list as xml or json and parse it and build your desired HashMap or whatever you like. Keep in mind that this may be a blocking operation and should not run on the main UI thread, run it async, but it depends on the length of the file you try to parse, but in general you should run that in an async thread
---- Update
You could do something like this:
int stringRes[] = {R.string.my_string, R.string.another_string}
List<String> myStrings = new ArrayList<String>();
for (int id : stringRes){
String str = getResources().getString(id);
// TODO do some if check if you want to keep that string or whatever you want to ...
myStrings.add(str);
}
you could store them into a HashMap(but getResources().getString() acts already like a HashMap ) or List
The whole point of the XML file is to act as a "hashmap" kind of... you can always get a string by using context and the R.string reference. I'm assuming you are aware of this, so then you must be trying to create a simplified reference to this?
Creating a HashMap requires either static references (which are not available for XML) or a runtime creation of the list. You can create the list in the Application class, but I would caution against that. You may have trouble referencing the context but again, you can use the Application constructor to make sure you have a reference to context.
Beyond that, you should check into the StringArray resource. It does not allow you to reference a string using another string because it is an array. Here are the docs:
http://developer.android.com/guide/topics/resources/string-resource.html#StringArray
If it's super-important to use a HashMap then you should probably not use XML and should just create a static class. The XML resource files are primarily used for centralized data (to ease modifications to static strings) and, more so, multi-lingual purposes. Static HashMaps are not the proper use-case.

Difference in retrieving String and String Array resources?

I'm new to Android and trying to understand the code I wrote from a tutorial. Meanwhile, I'm referencing the documentation whenever I want to really understand something.
The documentation in question
That page discusses string resources.
For a string, under the String section it states I could retrieve a string defined in an XML file like this: String string = getString(R.string.hello);.
XML in question:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello!</string>
</resources>
Now, for a string array, under the String Array section it states I could retrieve a string string array defined in an XML file like this::
Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);
XML in question:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="planets_array">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
</string-array>
</resources>
How come I have to do Resources res = getResources(); for a String Array, and not for a String in an XML file?
Would String[] planets = getStringArray(R.array.planets_arry); not work? Do resources have more methods, namely for more complex cases like String Arrays? is getString so simple it is fine to not need it under a resource? Where could I find a list separating what requires me to do Resources res = getResources(); versus what doesn't require that?
Lastly, does getResources get me every single resource in my Android project irregardless of what XML file it may be in?
How come I have to do Resources res = getResources(); for a String
Array, and not for a String in an XML file?
getString() is a method of your Context object (mostly an Activity but could also be a Service). The code for that method is:
public final String getString(int resId) {
return getResources().getString(resId);
}
Meaning getString() is just a convenience method that the Context class offers. In the end both calls do the same, namely retrieve a resource through the Resource object.
Would String[] planets = getStringArray(R.array.planets_array); not
work?
No because Context doesn't have a convenience method to retrieve String[].
Do resources have more methods, namely for more complex cases like
String Arrays?
Yes. See http://developer.android.com/reference/android/content/res/Resources.html.
I leave if up to you to decide whether they are more complex than getStringArray.
is getString so simple it is fine to not need it under a resource?
Resource does have a getString(int) method: http://developer.android.com/reference/android/content/res/Resources.html#getString(int)
Where could I find a list separating what requires me to do Resources
res = getResources(); versus what doesn't require that?
There's no such list. The JavaDoc for Context will tell you what convenience method you got:
http://developer.android.com/reference/android/content/Context.html
Lastly, does getResources get me every single resource in my Android
project regardless of what XML file it may be in?
Only if it's in a resource xml file. Layouts or Drawables can't contain String resources.
The call getString() is essentially the same thing as getResources().getStringArray(), as mentioned here the method getString() is just a convenience method, because it's used so often.
public final String getString(int resId) {
return getResources().getString(resId);
}
I'll also add that you can't use getStringArray in other resource files, like XML layouts, where getString() can be.

Categories

Resources