How to change activities title in attach()


I want to run a parameterized Instrumentation Test featuring different locales to run the same test with all supported languages.

The observed behavior is that the activity will have the localized title of the first test run also for every following run. So no matter which language my phone is in, the title will be correctly localized for the first parameterized test run, and still be the same for every following one.

While overwriting locales itself works for any resources, it will work only once for the activities title if set by the AndroidManifest.xml.

Activities seem to get their title set once in attach, and whatever is calling attach seems to be caching the title in the locale the app was first launched in.

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
   ---> CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {

Since the resources always get correctly localized, a workaround would be to call setTitle(R.string.title) or just getActionBar().setTitle(R.string.setTitle), but I would like not to change the activities solely for testing purposes.

Question: How can I change the title the activity gets launched with after the first test run? As mentioned above, this seems to get cached and not properly updated, and killing the app to restart it will fail the instrumentation test.

Test setup

The whole test project can be found here on GitHub ( contains the currently failing unit tests with the issue described here) and is using a Parameterized Unit Test in in conjunction with UIAutomator.

The goal is to take a batch of screenshots without knowing too much about the app itself (UIAutomator), and the app not having to be modified for the test either.

Changing the locale:

I’m successfully changing the locale before every test, and my texts get correctly displayed by doing the following, also I have multiple assertions in place making sure that the resources are in fact the right locale.

public LocalizationTest(Locale locale) {
    mLocale  locale;
    Configuration config  new Configuration();

    Resources resources  InstrumentationRegistry.getTargetContext().getResources();
    resources.updateConfiguration(config, resources.getDisplayMetrics());


What doesn’t work:

I obviously tried setting the locale in the same way on the target context, the application context, and the activity (which would probably be too late anyways).

I see that attach gets called from Instrumentation, but just creating a new App and trying to launch the activity will not localize the title either.

Intent intent  context.getPackageManager().getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);
context  InstrumentationRegistry.getInstrumentation().newApplication(App.class,


The title string gets cached within the package manager ApplicationPackageManager in a static sStringCache.

While there is a method static void configurationChanged() which clears the cache, it does not seem to get invoked on manual changes. Hence the decribed problem with the wrongly localized activity title after the first invocation.

The solution to this is made possible using reflection to load the class and invoke the method oneself. This is kinda dirty since it is accessing a private method, but it works.

// as before
Configuration config  new Configuration();

Resources resources  context.getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());

// CLEAR the cache!
Method method  getClass().getClassLoader()

Alternatively you can use public methods on another non-public API which in turn will also invoke the above method. Still dirty but not invoking private methods.

It seems like you can omit resources.updateConfiguration(...); by using this method though since it will also take care of that.

// Clear the cache. 
Object thread  getClass().getClassLoader()
Method method  getClass().getClassLoader()
        .getMethod("applyConfigurationToResources", Configuration.class);
method.invoke(thread, config);

Answered By – David Medenjak

Leave a Comment