I’ve really been enjoying playing with my Nexus 7 but have discovered a slight problem. I decided to purchase a bluetooth keyboard and so grabbed myself a Perixx PERIBOARD-804. This won out over the Zagg Keys Flex and the Logitech keyboards thanks to compact size, internal USB-rechargeable battery and UK keyboard layout. Unfortunately, while testing this out on the Nexus 7 I discovered that the Nexus doesn’t come with UK keyboard layouts for external keyboards. I haven’t been this annoyed by a keyboard layout since I bought a Mac. Anyway, after a bit of digging around online I found that it’s possible (with root) to upload a custom character mapping for my device to make it work as expected. You can read more about the specs of these files over at the Android Open Source Project.
New Configuration
Two files need to be created to ensure that all the buttons work as expected:
- A Keyboard Layout which defines which android key code results from a key press. This lives in
/system/usr/keylayout
and is named Vendor_<VendorID>_Product_<ProductID>.kl - A Key Character Map which defines which android key code produces which character (with modifiers). This lives in
/system/usr/keychars
and is named Vendor_<VendorID>_Product_<ProductID>.kcm
Identifying the Device
The VendorID and ProductID in the filenames are used to match the configuration to the specific device. With the keyboard connected this can be found in a shell (adb or on device) by looking in /proc/bus/input/devices
.
shell@android:/ $ cat /proc/bus/input/devices ... I: Bus=0005 Vendor=04f2 Product=1063 Version=0505 N: Name="Bluetooth Keyboard " P: Phys=10:BF:48:F3:8B:E2 S: Sysfs=/devices/platform/tegra_uart.2/tty/ttyHS2/hci0/hci0:12/input4 U: Uniq=90:7F:61:8E:78:A4 H: Handlers=sysrq event3 keychord B: PROP=0 B: EV=12001f B: KEY=4c37fff 72ff32d bf544456 0 0 1 30f90 8b17c007 ffff7bfa d951dfff febeffdf ffefffff ffffffff fffffffe B: REL=40 B: ABS=101 30000 B: MSC=10 B: LED=1f
Here my Vendor ID is 042f
and my Product ID is 1063
. Once you’ve created your baseline files by copying (adb pull
is your friend) the generic configuration and renaming to match your Vendor & Product IDs you can jump into them and make the changes you require.
Changing Keys
In my case most of the work was in the key character map file (moving quote marks, tilde, etc.) and you may not need to make any changes to the keyboard layout at all. One change I had to make was to support the # key on a UK keyboard (which has the ~ character above it). The generic keyboard layout was sending it as a backslash, along with the actual backslash key. To find which key to change I needed to know the shortcode being sent by the keyboard and for this you can use KeyTest.apk
made by Chris Boyle. This app will run and report the short code for all key presses so you can hunt down the one you’re interested in. In my case this meant changing key 43 BACKSLASH
to key 43 POUND
in my layout file and then putting a corresponding entry in my key character map:
key POUND { label: '#' base: '#' shift: '~' }
Note that this format for the character map is supported from Android 3.0+ (the Nexus 7 is on 4.1 at the time of writing). It’s worth digging into the documentation to read up on the various modifier keys you can react to. Power users may decide that they want alt
characters for all of their keys to produce special characters. The AOSP docs explain a bit more about any escape characters you might need to use in special cases as well as how to represent more exotic characters as unicode code points. Wikipedia should serve to provide a reference for the latter.
Installation
Once you’re done with your new configuration you’ll want to deploy this to your device. I did all of this using adb as follows.
- Put my new configuration in two local directories:
keylayout
andkeychars
- Create a
keyboard
folder in the root of your/sdcard
partition. adb push
your configuration to the device:adb push keylayout /sdcard/keyboard/keylayout adb push keychars /sdcard/keyboard/keychars
- Launch
adb shell
and run the following commands:su mount -o remount rw /system cat /sdcard/keyboard/keylayout/Vendor_04f2_Product_1063.kl > /system/usr/keylayout/Vendor_04f2_Product_1063.kl cat /sdcard/keyboard/keychars/Vendor_04f2_Product_1063.kcm > /system/usr/keychars/Vendor_04f2_Product_1063.kcm chmod 644 /system/usr/keychars/Vendor_04f2_Product_1063.kcm chmod 644 /system/usr/keylayout/Vendor_04f2_Product_1063.kl reboot
- Wait for your device to reboot
- Profit
Profit
Voila! You should now have a working keyboard layout for your device! If you’ve also got the Perixx 804 then you can take my configuration files from a repo on GitHub. Please feed back any mistakes you find and shout if you’d like any more layouts uploaded. If I have time I might try to get an app together for installing any configs from git and/or editing these config files on the device.
Troubleshooting
If you’re trying to do this yourself and having difficulty troubleshooting what’s happening, keep an eye on adb logcat
when you’re connecting your bluetooth device. A message should appear telling you which layout and character map files are being used. This helped me identify what was failing on my first attempt and I eventually tracked a problem to a duplicate definition for POUND in the character map.
A shout out to this post on the Thrive forums for getting me on the right track.