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.
Related
I would like to check programmatically whether an sd card is installed, and if yes, give the user the choice to switch between external and internal storage.
I have my other static settings organized inside a preferences.xml.
It seems that I have to rewrite all the settings of the xml file in code if I start to work with preferences more dynamically.
Or is there an option to enhance the preferences from the xml with preferences from code which get used just once needed?
Thanks
Add this to manifest for install app on sd card if is possible:
android:installLocation="preferExternal">
To verify is sd card writable and readable use this method:
private boolean isExternalStorageWritable() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);}
To get folder of appfiles on sdCard (externalStorageVolumes[0] is primary folder):
File[] externalStorageVolumes =
ContextCompat.getExternalFilesDirs(getApplicationContext(), null);
Oficial documentation
I found out myself, it looks a bit clumsy, but it works.
Once again: My problem is that I have certain setting options pre configured in an xml file as described here:
Preferences with XML
Here is my preferences.xml:
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="#string/download_header">
<SwitchPreferenceCompat
app:key="dl_background"
app:title="#string/background_behaviour"
app:defaultValue="false"/>
<ListPreference
app:title="#string/dl_qual"
app:defaultValue="#string/low_qual"
app:key="dl_qual"
app:entries="#array/dl_qual_arry"
app:entryValues="#array/dl_qual_arry"/>
</PreferenceCategory>
<PreferenceCategory app:title="#string/tc_header">
<SwitchPreferenceCompat
app:key="tc_installed"
app:title="#string/tc_behaviour"
app:defaultValue="false"/>
<ListPreference
app:title="#string/dl_dir_root"
app:key="dl_dir_root"/>
</PreferenceCategory>
</PreferenceScreen>
Here you can define arrays which map to ListPrefrence objects.
Each option list is then populated from a resource xml file holding the actual list entries.
I used this approach for the first ListPreference "dl_qual" above.
This is the resource.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="dl_qual_arry">
<item>Higher quality (128kbps)</item>
<item>Lower quality (64kbps)</item>
</string-array>
</resources>
But then I had the idea to insert a ListPreference where the values of the options list are only known at runtime.
This is my second ListPreference above "dl_dir_root".
I was too lazy to rewrite (and read how to do it in advance) the complete settings activity from code.
So I ended up with this SettingsFragment inside my SettingsActivity:
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
//First, lets check whether we have initialized preferences already
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
String selectedDir = prefs.getString("dl_dir_root", "INIT");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
PreferenceScreen root = getPreferenceScreen();
ListPreference dlDirRoot = root.findPreference("dl_dir_root");
CharSequence[] arryValues = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
CharSequence[] arryEntrys = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
dlDirRoot.setEntries(arryEntrys);
dlDirRoot.setEntryValues(arryValues);
if(selectedDir.equals("INIT")) {
//Initialize value/index
dlDirRoot.setDefaultValue(arryValues[0]);
dlDirRoot.setValueIndex(0);
}
else{
//Position at already selected value/index
dlDirRoot.setDefaultValue(selectedDir);
dlDirRoot.setValue(selectedDir);
dlDirRoot.setValueIndex(dlDirRoot.findIndexOfValue(selectedDir));
}
}
}
The pre defined xml is applied first, then the ListPreference object for "dl_dir_root" is acessed and the options are added:
ListPreference dlDirRoot = root.findPreference("dl_dir_root");
CharSequence[] arryValues = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
CharSequence[] arryEntrys = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
dlDirRoot.setEntries(arryEntrys);
dlDirRoot.setEntryValues(arryValues);
The rest is checking/keeping state between the calls to the activity.
If anyone knows of a more elegant way, I would be curious.
Best
Matthias
I have a data in Firebase like:
-Moon1
sm_1 : "Titan"
-Moon2
sm_2 : "Europa"
-Moon3
sm_3 : "Triton"
-Moon4
sm_4 : "Io"
My strings.xml file is like below
<string name="sm_1">/*Data from firebase*/</string>
<string name="sm_2">/*Data from firebase*/</string>
<string name="sm_3">/*Data from firebase*/</string>
<string name="sm_4">/*Data from firebase*/</string>
I want the string sm_1 to have the data Titan, sm_2 = Europa and likewise. I am able to retrieve the data from Firebase and assign to a Listview.
But how to assign to a string in strings.xml?
I am fairly sure you cannot create string resources on runtime as they are compiled into your apk when you are bundling your project. What you are thinking is persisting your data from Firebase, which can be done in many ways.
You could save your instance state, create a Room database, a SQL database, use shared preferences even. However since you already seem to have a Firebase database set up maybe use that always.
It is actually possible by following codes but however, this ain't a good practice at run time. Instead, try saving strings in a variable then setting your data to adapter or etc.
In your Strings.xml:
<string name="sm_1">%1$s</string>
In Java-Kotlin side:
val yourString = "Titan" // Or you can set this from FireBase output
val formatted = getString(R.string.my_xml_string, yourString)
I'm working on a project where I've defined several strings to use on my project.
I want to use a string to be displayed as my subtitle of the page on the toolbar. The reason I'm using strings is because I want my app to be translation supported.
Here is how I use subtitles on the toolbar of my activity:
android.support.v7.app.ActionBar ab = getSupportActionBar();
ab.setTitle("Title");
ab.setSubtitle("Subtitle");
I want to use a string on java (like #string/helloworld in xml) but I don't know how can I do that.
Can anyone help me?
In your "res" directory, there might be "strings.xml" file. (If you didn't remove it). Add string tags like bellow code snippets.
<string name="title">Title Message</string>
<string name="sub_title">Sub Title Message</string>
And in your java file.
String mStringTitle = getString(R.string.title);
String mStringSubTitle = getString(R.string.sub_title);
You can also use these string resources in your layout XML like follows.
<TextView
android:text="#string/title" />
For more information, please refer to the bellow URLs.
What is the string resource in Android? android_string_resources
How to support multiple locales?
support_different_language //
different-locales
In this case, use R.string.helloworld, because these methods require a resource ID.
This is the code -
R.string.message_failure
Implementation of the above code -
snackbar = Snackbar.make(constraintLayout,R.string.message_failure, Snackbar.LENGTH_SHORT)
//String_file.xml code -
<string name="message_failure">Failure</string>
I've read others posts about this link warning but they didn't solve my problem and I still don't get what I've doing wrong.
In default file strings.xml, I have:
<string name="rating_dialog">You\'re about to rate this app with %s stars.</string>
Later, I call it inside an override onClick method:
v.getContext().getString(R.string.rating_dialog, String.valueOf(rating))
It's appearing like:
You're about to rate this app with {String.valueOf(rating)} stars.
Link Warning:
Format string is not a valid format string so it should not be passed to string.format
Note:
v is a View and rating is an int value.
I've checked other strings.xml files for other languages, and all translations seems alright.
Solved: for hindi string.xml, instead of %s, there was only %.
You need to assign a position to each placeholder you define in your XML.
Your string then becomes:
<string name="rating_dialog">You\'re about to rate this app with %1$s stars.</string>
You can do it like below:
In string.xml:
If you want to assign integer value then use "%1$d" and if String then use "%1$s"
1 is use for defining position. If you want to use multiple values then you can use "%1$d","%2$d",....etc
<string name="rating_dialog">You\'re about to rate this app with %1$d stars.</string>
Then in code do it like :
v.getContext().getString(R.string.rating_dialog, rating);
Hope it helps you.
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("....");