Android Question Changing Locale of Android

Alberto Iglesias

Well-Known Member
Licensed User
Anyone know how change the Android Locale?

Is possible with CORE of B4A or need create a library with this routine?

Class localClass = Class.forName("android.app.ActivityManagerNative");
Object localObject = localClass.getMethod("getDefault", null).invoke(localClass, null);
Configuration localConfiguration = (Configuration)localObject.getClass().getMethod("getConfiguration", null).invoke(localObject, null);
localConfiguration.locale = paramLocale;
setUserSetLocale(localConfiguration, true);
localObject.getClass().getMethod("updateConfiguration", new Class[] { Configuration.class }).invoke(localObject, new Object[] { localConfiguration });
 

Alberto Iglesias

Well-Known Member
Licensed User
I´m installed the app MORELOCATE and it´s do this, works for me in google glass

https://www.c-lis.co.jp/our_services/morelocale-2

but I can now put inside my code to not depend this app.

You can choose country and language and then update configuration... done! Works!

Look the code of app (attachement)
 

Attachments

  • More.src.zip
    52.7 KB · Views: 295
Upvote 0

Alberto Iglesias

Well-Known Member
Licensed User
is in MoreLocale.java in source code

but is this:

private static void setUserSetLocale(Configuration paramConfiguration, boolean paramBoolean)
{
Class localClass = paramConfiguration.getClass();
try
{
localClass.getField("userSetLocale").set(paramConfiguration, new Boolean(paramBoolean));
return;
}
catch (IllegalAccessException localIllegalAccessException) {}catch (NoSuchFieldException localNoSuchFieldException) {}
}
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
You can compile this code to a library with SLC:

B4X:
package aaa.bbb;

import java.util.Locale;

import android.content.res.Configuration;
import anywheresoftware.b4a.BA.ShortName;

@ShortName("ChangeLocale")
public class test {
   
   public void ChangeLocale(String language, String country) throws Exception {
     Class localClass = Class.forName("android.app.ActivityManagerNative");
     Object localObject = localClass.getMethod("getDefault", null).invoke(localClass, null);
     Configuration localConfiguration = (Configuration)localObject.getClass().getMethod("getConfiguration", null).invoke(localObject, null);
     localConfiguration.locale = new Locale(language, country);
     setUserSetLocale(localConfiguration, true);
     localObject.getClass().getMethod("updateConfiguration", new Class[] { Configuration.class }).invoke(localObject, new Object[] { localConfiguration });
   }

   private static void setUserSetLocale(Configuration paramConfiguration, boolean paramBoolean)
   {
     Class localClass = paramConfiguration.getClass();
     try
     {
       localClass.getField("userSetLocale").set(paramConfiguration, new Boolean(paramBoolean));
       return;
     }
     catch (IllegalAccessException localIllegalAccessException) {}catch (NoSuchFieldException localNoSuchFieldException) {}
   }
}

Locale documentation: http://docs.oracle.com/javase/7/docs/api/java/util/Locale.html
 
Upvote 0

Alberto Iglesias

Well-Known Member
Licensed User
Erel,

Is working but only save configuration after I exitapplication, look

Dim objVisualNet As VisualNet
objVisualNet.Initialize("VisualNet")
objVisualNet.ChangeLocale("fr","FR")
Log("CheckPermission = " & objVisualNet.CheckPermission("android.permission.CHANGE_CONFIGURATION"))
LogColor("Locale_country = " & objVisualNet.Locale_country,Colors.Red)
LogColor("Locale_language = " & objVisualNet.Locale_language,Colors.Red)


After 1o run (Not changed)
** Activity (main) Create, isFirst = true **
CheckPermission = true
Locale_country = US
Locale_language = en

After 2o run (changed)
** Activity (main) Create, isFirst = true **
CheckPermission = true
Locale_country = FR
Locale_language = fr


Do you know why? Some update when you exit of application?
 
Upvote 0

Alberto Iglesias

Well-Known Member
Licensed User
Erel,

I found.. look below, I put exactly the same line before setUserSetLocale to save first and then apply to user configuration and works!


public void ChangeLocale(String language, String country) throws Exception
{
Class localClass = Class.forName("android.app.ActivityManagerNative");
Object localObject = localClass.getMethod("getDefault", null).invoke(localClass, null);
Configuration localConfiguration = (Configuration)localObject.getClass().getMethod("getConfiguration", null).invoke(localObject, null);
localConfiguration.locale = new Locale(language, country);
localObject.getClass().getMethod("updateConfiguration", new Class[] { Configuration.class }).invoke(localObject, new Object[] { localConfiguration });
setUserSetLocale(localConfiguration, true);
localObject.getClass().getMethod("updateConfiguration", new Class[] { Configuration.class }).invoke(localObject, new Object[] { localConfiguration }); }


I do this based in this code: Look the sub changeTheme in this code
https://code.google.com/p/my-projec...c/com/cybercom/rcs/skin/SkinFactory.java?r=21

THANKSSSSSSSSSSSSSSSS
 
Upvote 0

warwound

Expert
Licensed User
I've had to do this at the start of the week.
Did some research and created this library method:

B4X:
	/**
	 * Set the default Locale used to get resources.
	 */
	public static void SetDefaultLocale(java.util.Locale Locale1){
		android.content.res.Resources currentResources = BA.applicationContext.getResources();
        AssetManager assetManager = currentResources.getAssets();
        DisplayMetrics displayMetrics = currentResources.getDisplayMetrics();
        Configuration configuration = new Configuration(currentResources.getConfiguration());
        configuration.locale = Locale1;
        new android.content.res.Resources(assetManager, displayMetrics, configuration);
	}

Calling the Resources class constructor results in the global instance of the AssetManager to be re-constructed and it'll be re-constructed using the Locale of the Configuration passed to it's constructor.
This is not officially documented but is widely reported on forums to be true...
Methods that return a localized value will now return a localized value based on that passed Locale - and this means call to Resources will return localized strings.

Now in my b4a code i can do:

B4X:
Dim ApplicationResources As Resources
ApplicationResources.Initialize(ApplicationResources.RESOURCE_SOURCE_APPLICATION)
Dim DeviceLocale As Locale
DeviceLocale=DeviceLocale.GetDefault

Log("Device Locale: "&DeviceLocale.GetLanguage)

Dim SupportedLocales() As Locale=Array As Locale(DeviceLocale.CHINESE, DeviceLocale.ENGLISH, DeviceLocale.JAPANESE, DeviceLocale.KOREAN)
For Each SupportedLocale As Locale In SupportedLocales
	ApplicationResources.SetDefaultLocale(SupportedLocale)
	ApplicationResources.Initialize(ApplicationResources.RESOURCE_SOURCE_APPLICATION)
	Log("Processing values for Locale: "&SupportedLocale.GetLanguage)
	'	here i fetch application resources such as strings
	'	and have created xml string resources for 4 different languages
	'	so i'm iterating through each Locale that i have defined
Next

'	restore the device's original Locale
'	if you don't do this then the application will continue with the previous Locale passed to ApplicationResources.SetDefaultLocale
ApplicationResources.SetDefaultLocale(DeviceLocale)
ApplicationResources.Initialize(ApplicationResources.RESOURCE_SOURCE_APPLICATION)

Alternatively, the java Locale class does have a (simple) static method setDefault(Locale locale).
Here's the official documentation:

Overrides the default locale. This does not affect system configuration, and attempts to override the system-provided default locale may themselves be overridden by actual changes to the system configuration. Code that calls this method is usually incorrect, and should be fixed by passing the appropriate locale to each locale-sensitive method that's called.

The android R class has no getter methods that allow you to pass a Locale instance, my working code was the only solution i found.

Library files attached if you want to try them.

Martin.
 

Attachments

  • Resources_library_files_20140521.zip
    10.6 KB · Views: 371
Upvote 0

Anuj_Singh

Member
Licensed User
But still not get, how to change Locale programmatically.
Is there any library through which we can set Locale for our device ?
 
Upvote 0

Alberto Iglesias

Well-Known Member
Licensed User
Hey Anuj_Singh,

I create a little library to to this for me, and I put this simple lines in my Actvity_Create to change locale when I need.


Look this example: To change the locate to PORTUGUESE/BRAZIL, I put this lines and thats it!

Dim objVisualNet As VisualNet
objVisualNet.Initialize("VisualNet")
objVisualNet.ChangeLocale("pt","BR")



Hugs!
 

Attachments

  • VisualNetLib110.zip
    3.6 KB · Views: 294
Upvote 0

Anuj_Singh

Member
Licensed User
In my Samsung Android device and others like Micromax, Motorola & HTC.
Language conversion works fine using xml Resources file & your with your Library
 
Upvote 0

lorebarita

Member
Licensed User
Hi I like this library to change the language dynamically. It works well in my Samsung Android device but it does not work in a Chinise phone(Rugged phone). My app is meant for this type of phone. Any help will be appreciated.

This is the error I get even after adding AddPermission(android.permission.CHANGE_CONFIGURATION)


java.lang.reflect.InvocationTargetException


at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.visualnet.lib.visualnet.ChangeLocale(visualnet.java:196)
at com.etc.utils.nfc.main._img_france_click(main.java:879)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:162)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:158)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:66)
at android.view.View.performClick(View.java:4212)
at android.view.View$PerformClick.run(View.java:17476)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5371)


at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.SecurityException: Permission Denial: updateConfiguration() from pid=20946, uid=10088 requires android.permission.CHANGE_CONFIGURATION
at android.os.Parcel.readException(Parcel.java:1425)
at android.os.Parcel.readException(Parcel.java:1379)
at android.app.ActivityManagerProxy.updateConfiguration(ActivityManagerNative.java:2965)
... 21 more
java.lang.reflect.InvocationTargetException
 
Last edited:
Upvote 0
Top