Im using 2 different xml Files to store data i need. When starting the App i want to read those 2 resources and generate Objects from it.
Let me explain, what it is i'm doing:
The first resource stores event-names like this: /res/values/event_names.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="event_a">AAAA</string>
<string name="event_b">BBBB</string>
<string name="event_c">CCCC</string>
<string name="event_d">DDDD</string>
</resources>
The seconds resource stores the times, that given events kick off: /res/values/event_times.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="event_a">
<item>02:00</item>
<item>11:30</item>
<item>17:00</item>
</string-array>
<string-array name="event_b">
<item>03:00</item>
<item>12:30</item>
<item>18:00</item>
</string-array>
<string-array name="event_c">
<item>04:00</item>
<item>13:30</item>
<item>19:00</item>
</string-array>
<string-array name="event_d">
<item>04:30</item>
<item>10:00</item>
<item>15:00</item>
<item>20:00</item>
</string-array>
</resources>
Note, that event names and times have their name in commom. On startup the App will read the event-names first and then find out their correspondent timestamps.
Can i do it the way i planned this out? I'd have to read all the identifiers from the name-resource and then by that identifier get the times.
Why don't you add all the event names as the first element in your <string-array>. This way your event names will be tightly coupled to their respective times.
Quick idea:
You can probably save all your information on a file with JSON format in the asset folder as #amalBit suggested in a comment.
Then you don't have to make the parsing since Android comes with a JSON library, and you won't be needing to parse any txt with a custom format.
Or in an uglier way (and I am not writing this hehe), you can just put a JSON directly in your strings.xml in one entry alone. That would save you from reading the asset manually. But I wouldn't do this, because strings.xml has another meaning (which is to store strings you want to translate hehe)
If you want I can post you some code of the first case later.
<!-- ================= -->
<!-- Event Mappings -->
<!-- ================= -->
<eat-comment />
<array name="event_lists">
<item>#array/event_a</item>
<item>#array/event_b</item>
<item>#array/event_c</item>
</array>
<!-- =========== -->
<!-- Event Lists -->
<!-- =========== -->
<eat-comment />
<string-array name="event_a">
<item>Event A</item>
<item>02:00</item>
<item>11:30</item>
<item>17:00</item>
</string-array>
<string-array name="event_b">
<item>Event B</item>
<item>03:00</item>
<item>12:30</item>
<item>18:00</item>
</string-array>
<string-array name="event_c">
<item>Event C</item>
<item>04:00</item>
<item>13:30</item>
<item>19:00</item>
</string-array>
Code:
List<Event> events = new ArrayList<Event>(); // putting all events into a list
TypedArray eventMappings = getResources().obtainTypedArray(R.array.event_lists);
for (int mappingVar = 0; mappingVar < eventMappings.length(); mappingVar++) {
int eventId = eventMappings.getResourceId(mappingVar, 0);
String[] eventInfos = getResources().getStringArray(eventId);
Event event = new Event(); // your event domain class or whatever info holding class
for (int infosVar = 0; infosVar < eventInfos.length; infosVar++) {
switch (j) {
case 0:
event.setName(eventInfos[infosVar]);
break;
default:
event.addTime(eventInfos[infosVar]);
break;
}
events.add(event);
}
}
eventMappings.recycle(); // important
Hope that helps :-)
Related
I'm working an Android app and want to translate it to Persian language.
All String values in the project are saved into an resource XML file.
Some String values are used in layout files and some in classes (R.String). When using Persian text in Android, it has to be reshaped to be displayed correctly.
I want to reshape all resource String values without calling reshape method for every String value.
Can anyone explain me how to do this?
Some idea:
override String class
override getResource class
Android provides already functionality (well documented) to have a multilanguage app. Instead of replacing your text and having severall versions of your app for each language, its better to use the frameworks function. In that case the app chooses a suitable language from the available languages you provided depending on the device locale settings.
So basically you would start by creating the required directory structure (link above):
MyProject/
res/
values/
strings.xml
values-fa/
strings.xml
and then you fill in String values into the files, e.g.:
English (default locale), /values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">My Application</string>
<string name="hello_world">Hello World!</string>
</resources>
Persian, /values-fa/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">...</string>
<string name="hello_world">...</string>
</resources>
(quoted and adapted from the link above)
Solution for reshape farsi language
The reshape function has to be used for every Farsi String value, so setting string in the XML layout isn't possible (AFAIK), so the following proposals assume, that all String values are set programatically.
Using a global static wrapper function #1
public static final String getLocalizedString(int resId) {
if(Locale.getDefault().toString().equals("fa_IR")) {
return PersianReshape.reshape(getResources().getString(resId));
}else{
return getResources().getString(resId);
}
You can now use this function to load the String (you have to change each occurence) or you override e.g. the getRessource method. I personally would prefer using a static function instead of overriding because of possible other problems regarding loading resources of other type than String, side effects etc.
Creating a custom class with overriding setText() for each used ui widgets #2
Another possibility is to create custom ui widgets that do a call to PersianReshape.reshape() when display. E.g. for EditText:
class CustomTextField extends EditText {
#Override
public void setText(String text) {
super.setText(PersianReshape.reshape(text));
}
}
[...]
CustomTextField myTextBox = new CustomTextField();
myTextBox.setText("....");
How do you access the values in the res/values/string.xml resource file from the Android Activity class?
Well you can get String using,
getString(R.string.app_name);
And, you can get string-array using
String arr[] = getResources().getStringArray(R.array.planet);
for (int i = 0; i < arr.length; i++) {
Toast.makeText(getBaseContext(),arr[i], Toast.LENGTH_LONG).show();
}
strings.xml:
<string name="some_text">Some Text</string>
Activity:
getString(R.string.some_text);
Put this code in res/values/string.xml
<string-array name="planet">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
</string-array>
This code to be placed in res/layout/main.xml and remove default widgets present in main.xml.
<ListView android:id="#+id/planet"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:entries="#array/planet"/>
</LinearLayout>
If getString(R.string.app_name); isn't working for you, you can pass context like this:
context.getString(R.string.app_name);
If you have the context of Activity, go with:
getString(R.string.app_name);
If you don't have the context, try below, you can get the context from activity using Constructor.
mContext.getString(R.string.app_name);
I am trying to create preferences for an experimental app for android. However I can get the preferences to work.
The preference that I want to use determine the display langue and use this function to retrieve it:
private String selectLang()
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String lang = preferences.getString("lang", "n/a");
return lang;
}
Then inside onCreate method for the ListActivity I use this code to display the right language:
String lang = selectLang();
String title = (lang == "english") ? "English" : "Arabic";
title is a column in the database. The code does not seem to work and I get Arabic no matter what. I used this code just to know the value of lang:
Toast.makeText(this, lang, Toast.LENGTH_LONG).show();
and I get "english" but the English language does not display.
Here is is my XML for the list:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="lang">
<item>Arabic</item>
<item>English</item>
</string-array>
<string-array name="langValues">
<item>arabic</item>
<item>english</item>
</string-array>
</resources>
I have read in number of answers here on SO that I should use SharedPreference editor but I could not get a full working example of that.
Can you please help?
This: lang == "english" should be lang.equals("english").
Compare strings (as any other object) using equals or equalsIgnoreCase. The == operator compares object references, not content of objects, so your check always evaluated as false.
I would like to create a list of Integers in the /res folder of an android project. However, I want those integers to point resources in /res/raw. So for example, I would like something like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="built_in_sounds">
<item>#raw/sound</item>
</integer-array>
</resources>
But id doesn't look like I can do that, is there any way to do this? Or should I just create the list in a java class?
Thank you
And the correct answer is actually, TypedArray
The documentation shows examples of lists of resources:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="icons">
<item>#drawable/home</item>
<item>#drawable/settings</item>
<item>#drawable/logout</item>
</array>
<array name="colors">
<item>#FFFF0000</item>
<item>#FF00FF00</item>
<item>#FF0000FF</item>
</array>
</resources>
And the code to retrieve the values:
Resources res = getResources();
TypedArray icons = res.obtainTypedArray(R.array.icons);
Drawable drawable = icons.getDrawable(0);
TypedArray colors = res.obtainTypedArray(R.array.icons);
int color = colors.getColor(0,0);
Okay, I finally found out how to do this. What I did, was just create a database. The database stored all of the primitives I needed to store, and than pointers to the objects that I needed to reference. Apparently the android SDK comes with support for SQLite.
To do this in XML without a database, see:
http://developer.android.com/guide/topics/resources/more-resources.html#Integer
Just a quickie,
i have an xml resource in res/values/integers.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="UserBases">
<item>2</item>
<item>8</item>
<item>10</item>
<item>16</item>
</integer-array>
</resources>
and ive tried several things to access it:
int[] bases = R.array.UserBases;
this just returns and int reference to UserBases not the array itself
int[] bases = Resources.getSystem().getIntArray(R.array.UserBases);
and this throws an exception back at me telling me the int reference R.array.UserBases points to nothing
what is the best way to access this array, push it into a nice base-type int[] and then possibly push any modifications back into the xml resource.
I've checked the android documentation but I haven't found anything terribly fruitful.
You need to use Resources to get the int array; however you're using the system resources, which only includes the standard Android resources (e.g., those accessible via android.R.array.*). To get your own resources, you need to access the Resources via one of your Contexts.
For example, all Activities are Contexts, so in an Activity you can do this:
Resources r = getResources();
int[] bases = r.getIntArray(R.array.UserBases);
This is why it's often useful to pass around Context; you'll need it to get a hold of your application's Resources.
get an array from xml resources of android project can be accessed.
from array.xml
<string-array name="weather_values">
<item>sunny</item>
<item>cloudy</item>
<item>rainy</item>
</string-array>
in Activity
String[] stringsArray = getApplicationContext().getResources().getStringArray(R.array.weather_values);
in Fragment
String[] stringsArray = getContext().getResources().getStringArray(R.array.weather_values);
for output in log
System.out.println("Array Values " + Arrays.toString(stringsArray));
output is
I/System.out: Array Values [sunny, cloudy, rainy]