Sign in

Tag: android

Timer

v0.1
May 2007 - present (active)
A repeating timer that can wait for acknowledgement before starting the next interval, such as for taking tablets.

Android keymaps

2010-08-22 15:32:41

I recently bought a Bluetooth keyboard to use on Android; unfortunately some keys weren't recognised at all and others weren't quite mapped as I'd like. This is fairly easy to fix as an end user, as long as you have a rooted device (adb remount must succeed). Here's a quick howto, since I couldn't find one.

It shouldn't need saying, but you do this at your own risk. You can easily break your device's response to keys, and possibly make your device unbootable too if the file is invalid.

It's pretty much as described under Keymaps and Keyboard Input in the porting documentation. What we're going to do is edit one file: /system/usr/keylayout/qwerty.kl. This file maps scancodes to Android keycodes. For example: key 30 A means scancode 30 (decimal) maps to KEYCODE_A (29), the A key. As the porting docs say, a separate Key Character Map file deals with what characters, if any (e.g. "a", "A", "#"), should be generated given the keycode and the state of the modifiers (Shift, Fn/Sym, etc). A different KCM can be loaded for Bluetooth keyboards depending on their device name, but at least by default, the same key layout file (including your changes) is used for Bluetooth and the built-in keyboard (if any).

So, first we need to fetch your current key layout, and it's a good idea to keep backups (both on the device and locally).

1 adb pull /system/usr/keylayout/qwerty.kl qwerty.kl
2 cp qwerty.kl qwerty-orig.kl
3 adb shell cp /system/usr/keylayout/qwerty.kl /sdcard/qwerty-orig.kl

Now, edit qwerty.kl as you like. It should look initially look similar to this Nexus One example. You might find it helpful at this point to see what scancodes your keyboard is sending. There really ought to be a tool for this in Dev Tools or Spare Parts, but it seems there isn't. I've made a dirt-simple app to show you KeyEvent.toString(), which was the work of 5 minutes and could certainly be improved.

My particular keyboard is a white roll-up 87-key variety, that you can still find on eBay. It has F-keys doubling as media keys: if you get this model, be aware that the Fn key is really F-lock (toggles the state rather than acting as a modifier). Here is my layout file in case it's helpful. This layout mostly follows the principle of least surprise, except that the button with "Home" printed on it is Call, to mirror "End" being Hangup. F1 with F-lock on (Home symbol) is the Android "Home" keycode (goes to the home screen).

Now copy the layout back onto the device:

1 adb remount
2 adb push qwerty.kl /system/usr/keylayout/qwerty.kl

(If the remount fails, you probably don't have a rooted device.) It seems you need to reboot for the changes to take effect, so go ahead and do that, and your keys should then behave as you've specified. :-)

Comments (0)

What next?

2010-07-03 01:39:03, updated at 2010-08-10 09:38:14

Now that my various projects seem to be mostly behaving themselves, it's time to decide what to write next. I've had a few requests and a few ideas, so here's a rundown of possibilities.

  • Locale condition: ping. Let Locale ask "is that machine awake?" It could ping something in a private IP range, deduce that you're at home and your PC is on, and stop notifying you about things you're already likely to see on the PC. There seems to be a usable ping command in Android's busybox, but for bonus points, allow a TCP ping, maybe check the banner on a service, to guard against collisions with private IPs in other places.
  • Locale action: K9 settings. Adjust K9's settings from Locale situations. This could include poll intervals as well as notification settings, so similarly to the above example: check my work email, unless I'm at work and already have a desktop MUA doing that.
  • Locale action: ConnectBot. You can already configure a ConnectBot session to immediately run a command. Launching a remote shell script securely from Locale would add some nice flexibility: aggressive notification using PCs around the house, X10 home automation, garage doors… you could do this from ASE with an ssh client binary, but that's a little harder to install, especially without root.
  • Locale condition: Timer. My timer, not yet formally released, could trigger the aforementioned aggressive notification if alarms have gone unanswered for half an hour. Update: Done.
  • Port this site to Rails 3. This can wait until v3 is actually out.
  • Puzzles improvements. Some ideas languishing in the bug tracker, including multiplayer.
  • Set up mpd (with neompc on an old Palm Treo) at home. Probably no new code needed, but included for completeness.

Most of these will probably happen eventually, but it's always useful to know which ideas are useful to a wider audience, so feel free to comment or contact me if you're keen to see one of these created, or if you can think of improvements or existing projects I ought to be aware of. I'll also be writing up any interesting aspects of these projects as I implement them, and suggestions for posts of that kind that you'd like to see are also welcome.

Comments (0)

Lock on unplug

2010-06-23 00:32:04

Here's a hack for Gnome (vaguely relevant to Android too) that I've been using for a little while. When I get up from a computer, I generally want to lock the screensaver. I also pick up my phone from a USB dock (not the Nexus One Desktop Dock; that doesn't connect to a computer). So why not have the screensaver lock automatically when the phone disappears from USB? This is helpful when you're hurriedly picking up the phone to answer a call, and might otherwise forget to lock the screen. Of course, if you get a lot of calls that you want to answer while looking at your computer, this is not for you. :-)

This is pretty easy to achieve using udev. First we ask udev to run a script when this device disappears. The following goes in /etc/udev/rules.d/51-android.rules (or a similar name; the number is used for ordering). While I'm at it, I'll set sensible permissions and group ownership, using the first line.

 1 # Set mode and group for (some) devices made by HTC
 2 SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", MODE="0660", GROUP="mygroup"
 3 # Nexus One without debugging enabled
 4 SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4e11", \
 5   ATTRS{serial}=="HT123P456789", ENV{IS_MY_PHONE}="yes"
 6 # Nexus One with debugging enabled
 7 SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4e12", \
 8   ATTRS{serial}=="HT123P456789", ENV{IS_MY_PHONE}="yes"
 9 # You could unlock on connect if you want:
10 #ENV{IS_MY_PHONE}=="yes", ACTION=="add", RUN+="/somewhere/unlock"
11 # Lock when my phone goes away
12 ENV{IS_MY_PHONE}=="yes", ACTION=="remove", RUN+="/somewhere/lock"
  • The device doesn't have to be a Nexus One or a phone at all, run lsusb to find your idVendor/idProduct values (for Android, this may differ when you turn on/off USB debugging).
  • To find your device's serial number, run sudo lsusb -v and look for iSerial (or run adb devices if you already set that up).
  • Pick somewhere to put the lock script referenced in the last line.
  • The contents of that script should be:
1 #!/bin/sh
2 exec su user -c ". /home/user/.dbus/session-bus/*-0; \
3 export DBUS_SESSION_BUS_ADDRESS; \
4 gnome-screensaver-command --lock"

The unlock script would be the same with --deactivate. Replace user with your username, and if your display isn't :0 then you might need to do something smarter to get the right session bus. Oh, and I'm on Ubuntu Karmic (9.10); adjustments may be required for other environments. When you've done all that, run sudo reload udev to pick up the changes, unplug the phone, and watch the screen fade to black.

Question: how easy is it to fake a serial number of a USB device? Equivalently, how silly is it to have the unlock line uncommented? I'm guessing fairly easy.

Comments (2)

Chrome to Phone CL

2010-06-19 18:57:01, updated at 2010-06-25 19:24:48

A couple of recent Google offerings gave me an idea. First there was the demo of cloud-to-device messaging at Google I/O, with which I look forward to seeing the Android development community do great things, and to demonstrate it they used a Chrome extension, Chrome to Phone. Then yesterday, GoogleCL appeared, providing access to several Google services from the command-line.

Chrome to Phone is very nice, but it needn't be limited to just a browser button. Looking at the source of their Chrome extension, it's actually pretty easy to wire up as a bash script that just POSTs to the same backend. It should go without saying that this is a horrible hack, and if you write an app around this without first asking someone at Google, they'll probably block it. The approved way to push events to Android is to sign up for the C2DM beta with your own app. But if you want to play around with what's possible, or just cause your phone to open URLs from the command-line of your own machine, and your phone is running Froyo (Android 2.2), here's how:

  1. Get Chrome to Phone working as designed, as a Chrome extension.
  2. Extract the SACSID cookie for chrometophone.appspot.com: Spanner, Options, Under the Bonnet, Content settings, Cookies, Show cookies, search for chrometophone, click on SACSID, and on the long string next to Content, right-click, Select All, Copy.
  3. apt-get install libnotify-bin if you want notification of the result.
  4. Use a script like this one:
 1 #!/bin/sh
 2 u=`echo "$@" |sed -e 's/^market:\/\//http:\/\/market.android.com\//' \
 3   |sed -e 's/&/%26/g'`
 4 r=`curl -d "title=&url=$u&sel=" -H 'Cookie: SACSID=...your cookie here...' \
 5   -H 'X-Extension: true' 'https://chrometophone.appspot.com/send?ver=3'`
 6 cd /usr/share/icons/gnome/scalable/status
 7 case "$r" in
 8   *OK*) notify-send --icon=dialog-information.svg "$r" ;;
 9   *) notify-send --icon=dialog-warning.svg "$r" ;;
10 esac

Now you can give your script a URL, and your phone will open it. Note that the cookie might be IP-address-specific, in which case you'd need to redo the steps above to get it to work from a different IP. That fixup of market:// URLs means you can also register this script as the handler for them in GNOME…

1 gconftool-2 --set --type=string /desktop/gnome/url-handlers/market/command \
2   "/your/script/here \"%s\""
3 gconftool-2 --set --type=bool /desktop/gnome/url-handlers/market/enabled true
…and then the next time you see in a desktop browser that some idiot has created a page with a market:// link on it, you can click it and your phone will open the relevant Market listing.
Comments (0)