31

For automated testing (using Hudson) I have a script that generates a bunch of emulators for many combinations of Android OS version, screen resolution, screen density and language.
This works fine, except for the language part.

I need to find a way to change the Android system locale automatically. Here's some approaches I can think of, in order of preference:

  • Extracting/editing/repacking a QEMU image directly before starting the emulator
  • Running some sort of system-locale-changing APK on the emulator after startup
  • Changing the locale settings on the emulator filesystem after startup
  • Changing the locale settings in some SQLite DB on the emulator after startup
  • Running a key sequence (via the emulator's telnet interface) that would open the settings app and change the locale
  • Manually starting the emulator for each platform version, changing the locale by hand in the settings, saving it and archiving the images for later deployment

Any ideas whether this can be done, either via the above methods or otherwise?

Do you know where locale settings are persisted to/read from by the system?


Solution:
Thanks to dtmilano's info about the relevant properties, and some further investigation on my part, I came up with a solution even better and simpler than all the ideas above!

I have updated his answer below with the details.

Christopher Orr
  • 110,418
  • 27
  • 198
  • 193
  • 1
    do you have some kind of publication (blog, forum post etc) where you describe your automated testing set up? I would love to do automated testing for my apps and I love hudson but until now I have never found a good introduction into this topic. – Janusz Mar 18 '10 at 10:59
  • There's a possibility I might write it up along with some additional Hudson-related improvements I'm working on, but not for several weeks probably. If I do, I'll post an update here. – Christopher Orr Mar 18 '10 at 17:47
  • 1
    FYI: There's now a Hudson plugin that will automate the creation and running of emulators based on various properties like OS version, screen size, language: http://bit.ly/c9qOf8 – Christopher Orr Apr 06 '10 at 15:46

3 Answers3

58

Personally I think the simplest way is to start the emulator, probably a clean instance unless you are running integration tests that depends on other applications and then change locale using adb:

$ adb shell '
setprop persist.sys.language en;
setprop persist.sys.country GB;
stop;
sleep 5;
start'

or whatever locale you want to set. To verify that your change was successful just use

$ adb shell 'getprop persist.sys.language'

You may also want to run emulators on know ports, check my answer in this thread.


Note that you can also set system properties directly when starting the emulator:

emulator -avd my_avd -prop persist.sys.language=en -prop persist.sys.country=GB

This way, you can create a plain old emulator of any type then start it up immediately using the locale of your choice, without first having to make any modifications to the emulator images.

This locale will persist for future runs of the emulator, though of course you can always change it again at startup or during runtime.

Community
  • 1
  • 1
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • This is really interesting to me so I went to try it out, I have tried it through ADB shell on a G1 and a HTC Hero, I can use getprop no problem and get information back. But I want to use setprop but when I do nothing seems to actually get changed? – Donal Rafferty Mar 10 '10 at 18:12
  • 2
    We were talking about emulators, not sure if this could work on a real device. – Diego Torres Milano Mar 10 '10 at 18:42
  • 1
    Cool.. I didn't know about those properties or `stop`/`start`. Works for me. Also worked on my HTC Hero, or at least `stop` and `start` happily rebooted things (when run as root). :) – Christopher Orr Mar 10 '10 at 19:40
  • 1
    I also tried extracting an emulator system image, adding those '`persist`' properties to `/build.prop`, rebuilding, and then adding the image to the AVD. That worked, but seemingly with some inconsistent side effects of not displaying things at the right screen density. Rebooting helped, sometimes. I'll have to experiment tomorrow to see if I can get it working better this way, as I'd rather not have the first run of the emulator be a special case where I need to set these properties and reboot. – Christopher Orr Mar 10 '10 at 19:43
  • 1
    I'm also already using the `emulator -ports` stuff you mentioned, but on a port range outside the normal Android range, so I use `adb connect` to let the adb server know where the emulators are running. – Christopher Orr Mar 10 '10 at 19:49
  • 1
    Probably setting the properties you want to persist in '/data/local.prop' is enough for your needs saving you from building images. – Diego Torres Milano Mar 10 '10 at 22:38
  • 1
    Ah, could be. Anyway, preparing an image is easily automated (essentially a combo of unzip, cat, zip) so it's what I'd prefer over having to start the emulator first and then make changes via adb and reboot etc. I'll have to see whether the `/data` partition can be altered ahead of time. There is a `userdata.img` image for the emulator containing a couple of APKs, but adding `local.prop` didn't seem possible. I'll need have a closer look at the images and QEMU options later. – Christopher Orr Mar 11 '10 at 00:13
  • Ah so a real device has to be rooted to get it to work? Can you try on a non rooted device just to make sure Christopher? – Donal Rafferty Mar 11 '10 at 09:10
  • 2
    I just tried it on my HTC Hero without becoming root and it does not work. Neither `setprop` nor `stop` will work unless you're root. – Christopher Orr Mar 11 '10 at 10:24
  • Thanks for that Christopher, much appreciated – Donal Rafferty Mar 11 '10 at 11:01
  • Just one more thing Christopher can you point me to how you rooted your HTC Hero? – Donal Rafferty Mar 11 '10 at 16:47
  • This is the technique I used, I believe: http://theunlockr.com/2009/08/08/how-to-gain-root-access-on-your-htc-hero/ – Christopher Orr Mar 11 '10 at 19:44
  • dtmilano: Thanks a lot for the info about the properties. I came up with an even awesomer solution and added it to your post so I could accept your answer. – Christopher Orr Mar 11 '10 at 19:55
  • Thank you for your comment. Setting properties on the command line seems much more flexible, mainly when you need a known environment to run the tests. – Diego Torres Milano Mar 11 '10 at 23:29
  • What's with the apostrophe (this: ' ) ? – android developer Apr 24 '15 at 22:34
  • This no longer works. The answer (with update) by @denys is the currently working answer – Mike Hardy May 13 '20 at 18:08
11

Accepted answer doesn't work anymore. persist.sys.language and persist.sys.country are gone from emulator properties.

My solution is to use preinstalled on android emulator "Custom locale" application. Simply send intent with extra language parameter to it as below:

adb shell am broadcast -a com.android.intent.action.SET_LOCALE --es com.android.intent.extra.LOCALE EN

More information here - prepare android emulator for UI test automation.

UPDATE: based on comment from Jonas Alves the following command works on API 28+:

adb shell am broadcast -a com.android.intent.action.SET_LOCALE --es com.android.intent.extra.LOCALE "en_US" com.android.customlocale2
denys
  • 6,834
  • 3
  • 37
  • 36
  • This solution doesn't seem to work any more on API 26+ – kosev Jun 11 '18 at 09:48
  • 5
    This does work in all APIs including 28 BUT implicit broadcasts don't work anymore, so you need to add the target package name to the broadcast command: `adb shell am broadcast -a com.android.intent.action.SET_LOCALE --es com.android.intent.extra.LOCALE "en_US" com.android.customlocale2` – Jonas Alves Jun 18 '18 at 14:31
  • This is the best way to do it currently, thanks @denys! – Mike Hardy May 13 '20 at 18:07
  • Could you clarify why you use 2 locale values -- `com.android.intent.action.SET_LOCALE --es` and `com.android.intent.extra.LOCALE "en_US"` ? And what's the difference between `"SET_LOCALE"` and `"LOCALE"` ? – Mr-IDE Aug 01 '20 at 16:07
4

Seems that Android emulator now supports setting the locale when starting it:

emulator -avd <avd-name> -change-locale fr-CA

Source - https://androidstudio.googleblog.com/2019/09/emulator-29112-stable.html

Amit Kotlovski
  • 1,848
  • 1
  • 18
  • 13
  • That sounds fantastic but I just tried it and it does not work in Travis nor on my local linux commandline at the moment, that's with the 30.x emulator release series at the moment – Mike Hardy May 13 '20 at 17:39
  • This solution only works on images without Play Store – cuzi Sep 12 '21 at 09:47