3

I'm working on an activity instrumentation test case which automates verification of an AUT using the Robotium framework. There are several language tests I want to automate. I've attempted to change language via Robotium by pulling the resources from the AUT and forcing the local locale configuration to a different language, but to no avail:

    Locale locale = new Locale(lang);
    Locale.setDefault(locale);
    Configuration config = res.getConfiguration();      
    config.locale = locale;
    res.updateConfiguration(config, res.getDisplayMetrics());

I've also heard that it used to be possible that one could change the language using ADB using the activity manager, but I've been unable to find a working solution for V4.2.2. Short of embedding code in the application itself or rooting the device, is there any way to change locale remotely, through Robotium or otherwise?

Thanks in advance

2 Answers2

2

I had a similar problem some time ago and came to the following solution:

private void changeActivityLocale(final Activity a, String locale ){
    Resources res = a.getResources();
    DisplayMetrics dm = res.getDisplayMetrics();
    Configuration conf = res.getConfiguration();
    conf.locale = new Locale(locale);
    res.updateConfiguration(conf, dm);
    a.getResources().updateConfiguration(conf, dm);

    getInstrumentation().runOnMainSync(new Runnable() {
        public void run() {
            a.recreate();
        }
    });
}

I call this method inside my test case before starting some locale specific tests. Hope it helps you.

Best regards,

Peter

Peter
  • 10,910
  • 3
  • 35
  • 68
  • It worked for me in a simple test! I like this as I don't have to add/modify permissions to the android manifest. Good trick recreating the activity with the new Locale! – Richard Guion Feb 09 '14 at 05:29
1
protected void changeLocale(Locale locale)
        throws ClassNotFoundException, SecurityException,
        NoSuchMethodException, IllegalArgumentException,
        IllegalAccessException, InvocationTargetException,
        NoSuchFieldException {       
    @SuppressWarnings("rawtypes")
    Class amnClass = Class.forName("android.app.ActivityManagerNative");
    Object amn = null;
    Configuration config = null;

    // amn = ActivityManagerNative.getDefault();
    Method methodGetDefault = amnClass.getMethod("getDefault");
    methodGetDefault.setAccessible(true);
    amn = methodGetDefault.invoke(amnClass);

    // config = amn.getConfiguration();
    Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
    methodGetConfiguration.setAccessible(true);
    config = (Configuration) methodGetConfiguration.invoke(amn);

    // config.userSetLocale = true;
    @SuppressWarnings("rawtypes")
    Class configClass = config.getClass();
    Field f = configClass.getField("userSetLocale");
    f.setBoolean(config, true);

    // set the locale to the new value
    config.locale = locale;

    // amn.updateConfiguration(config);
    Method methodUpdateConfiguration = amnClass.getMethod(
            "updateConfiguration", Configuration.class);
    methodUpdateConfiguration.setAccessible(true);
    methodUpdateConfiguration.invoke(amn, config);
}

You will need permission in your application:

android.permission.CHANGE_CONFIGURATION

for api level >= 17 you have to grant it via adb:

adb shell pm grant application_package android.permission.CHANGE_CONFIGURATION
maszter
  • 3,680
  • 6
  • 37
  • 53
  • A very belated thank you for this post. After a 9 months hiatus, I've finally been able to try out this solution, unfortunately even with the permission in the app and granting it via adb I'm still getting a SecurityException. I attempted to configure the locale in a separate broadcast receiver and that worked, sort of. The language changed but the app lost focus. Any hints, or do I need to sign with a firmware key as suggested in [link](http://stackoverflow.com/questions/13440045/android-4-2-filters-out-change-configuration-permission) – Mike Putnam May 06 '14 at 22:00