So, I found out that there are two approaches to get system's locale in Android:
Locale.getDefault()
And
getResources().getConfiguration().locale
Basically question is - can output differ for these two? Or are they always the same and I can use the first one, since it does not require Context object?
Quoted from this page:
Be wary of the default locale
Note that there are many convenience methods that automatically use the default locale, but using them may lead to subtle bugs.
The default locale is appropriate for tasks that involve presenting data to the user. In this case, you want to use the user's date/time formats, number formats, rules for conversion to lowercase, and so on. In this case, it's safe to use the convenience methods.
The default locale is not appropriate for machine-readable output. The best choice there is usually Locale.US – this locale is guaranteed to be available on all devices, and the fact that it has no surprising special cases and is frequently used (especially for computer-computer communication) means that it tends to be the most efficient choice too.
A common mistake is to implicitly use the default locale when producing output meant to be machine-readable. This tends to work on the developer's test devices (especially because so many developers use en_US), but fails when run on a device whose user is in a more complex locale.
For example, if you're formatting integers some locales will use non-ASCII decimal digits. As another example, if you're formatting floating-point numbers some locales will use ',' as the decimal point and '.' for digit grouping. That's correct for human-readable output, but likely to cause problems if presented to another computer (parseDouble(String) can't parse such a number, for example). You should also be wary of the toLowerCase() and toUpperCase() overloads that don't take a Locale: in Turkey, for example, the characters 'i' and 'I' won't be converted to 'I' and 'i'. This is the correct behavior for Turkish text (such as user input), but inappropriate for, say, HTTP headers.
Locale current = getResources().getConfiguration().locale;
You may find that this value is updated more quickly after a settings change if that is necessary for your application.
Which is not in your another method
AFAIK, you can use either, unless your app itself tampers with locale using one way but not the other (Locale.setDefault() but not config.locale or vice versa)
Here's why:
ResourcesManager.applyConfigurationToResourcesLocked() #275:
public final boolean applyConfigurationToResourcesLocked(Configuration config,
CompatibilityInfo compat)
...
// set it for java, this also affects newly created Resources
if (config.locale != null) {
Locale.setDefault(config.locale);
}
Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
ApplicationPackageManager.configurationChanged();
...
Related
I am working on android application my application running across the world so I my using local times of all around the world to calculate times of daily activities. The problem which i am facing is that when i want to get time of local country like for example when i use Locale.getDefault() it some times returns values in user's device language for example if a user have a device language Arabic it will return me those values in Arabic format. my logic is design only for English numeric characters when language changes it gives me exception of number format. there is another option which is Locale.English it returns me values in English I want to Ask that if i use Locale.english instead of Locale.getDefault() is there any thing wrong in it or I am doing it in a currect way?
Locale.getDefault().toString() and context.getResources().getConfiguration().locale.toString()
should return the same value.
The only major difference between the two is that the
Locale.getDefault() can be directly overridden by Locale.setDefault(locale). (Which will also affect context.getResources().getConfiguration().locale.toString())
I would like to use two locales for resource values in an app.
For example, I want some specific strings to depend on what country the user is in right now (like phone numbers), while the rest of the strings will depend on the phone's language/locale settings.
Is there a clean way of doing this without programatically getting a string resource from a different locale? Or should I be using resources in the first place?
You can set forcefully based on device locale and you will need to handle that pattern when locale check returns true for the particular locale. Also, check for a relevant pattern that needs to be set for example phone number.
I have support for 3 languages in my app. And depending on what language the phone is set to use I want my app to run a function based on that.
You can determine this by looking for the devices Locale using the following syntax:
Locale current = getResources().getConfiguration().locale;
Generally best practice is not to use different code for different languages, just use different resources. However if you still need it you can use the Locale class.
If you want to get the selected language of your device:
Locale.getDefault().getDisplayLanguage();
If you're interested in just getting the ISO code (e.g. for if or switch statements) use:
Locale.getDefault().getISO3Language();
if you want change the App language use the file strings for each language supported
I have released an android app downloadable in the UK, but I wish to release a (very slightly different) version of the app for the U.S. Currently I believe I need to do the following for the new version of the app ...
1. Change the 'package' attribute in the manifest file to something different.
2. Ensure that on Google Play only the US can download the app.
Is there anything else I am yet to discover I need to do, or any other problems I am yet to consider?
Edit 19th July 13:19 GMT - I am currently warming towards using TelephonyManager.getNetworkCountryIso() as an initial country guess, and falling back on the locale if this fails (because of no SIM card). What do people think? Using GPS is also an option though, but is that overkill?
Since you say you're just changing a couple of strings (we'll think of the URL as just a string, too), I would suggest the following:
Create the resource directories res/values and res/values-en-rUS.
In each of these, create a strings.xml resource file
Define your default (UK specific) string values in the res/values directory, and your US specific string values in the res/values-en-rUS folder.
Then, to refer to these strings, simply use #string/my_string_name when referring to them from an XML document, or getResources().getString(R.string.my_string_name) when referring to them from code.
For more details on the types of resource qualifiers, check out this page, also for the list of qualified country codes you can use, see this page.
I'm sure anyone determined enough could change their region to US -- I'm honestly not sure offhand how the region is determined -- but for all intents and purposes this should do the trick without having to maintain two separate applications. I would just evaluate how critical it is that UK users be unable to access the US specific functions of the application, and with that in mind determine whether it is worth the maintenance of two applications.
EDIT Some more additional searching leads me to believe the region is locked into the build.prop file, which is not editable outside of rooting your device (i.e. it is not going to happen accidentally). That said, if it's still imperative that they have the correct option, I might suggest a popup dialog only on the first run of the application that confirms the locale with the user, saves it as a SharedPreference, and then choose your Strings programmatically based on that preference. That way you're still only maintaining one application, but you still have the flexibility of handling the two regions.
This is correct. The Play Store goes off of two things for who can download and if they can update. The first is the packagename com.andya.myukapp -> com.andya.myusapp should work, as long as none of your existing customers are expecting to switch freely between the two (assuming it's a paid app)
I eventually decided that the best policy was to use TelephonyManager to check the country of the Network.
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String networkCountryCode = tm.getNetworkCountryIso();
If that failed, I got the locale.
String locale = context.getResources().getConfiguration().locale.getCountry();
This would happen once at the start of the app. The results of this would then be saved and be configurable in the settings screen.
I use a bunch of locale-dependent Regular Expressions in my project,
For example (a simplest one):
\b(one|two|three|...|\d+)\b
So I want to store those regular expressions in something like values-en/re.xml and then use them through Context/R.re.* to parse the string that entered by user.
<string name="number_re">\b(one|two|three|...|\d+)\b</string>
So if he uses Russian locale and enters some phrase in Russian, I will use values-ru/re.xml with some value like:
<string name="number_re">\b(один|два|три|...|\d+)\b</string>
Is it the proper way intended (and it will not fail on some special characters used in both string resources and regular expressions) or there is another way to do it that I've missed?
I don't know what's considered proper or not proper (that's more of a app by app case). This seems like a reasonable approach. I mean you have separated out the locale specific aspect of your algorithm into place that has a mechanism for loading content by locale. Technically these regexes are resources. If it works for you and you aren't hindered by it now, I don't forsee this coming back and causing issues later.