Ack! This site is moving to tomhorsley.com since Comcast's efforts to improve their world's worst customer service ranking apparently include terminating web hosting for their existing customers.

Chapter 4 — Android Plays The Blues

Filled with overconfidence and armed with the BluetoothChat example from the Android SDK, I decide to attempt to start on an actual AardRemote demo app. I want to do something that can learn one IR code and then send it back out, just to test communications with the remote device and prove everything works.

One thing I find when poking around in Android and Bluetooth web pages is this: http://stackoverflow.com/questions/4444235/problems-connecting-with-bluetooth-android. It talks about the reflection technique for connection to a bluetooth device (whatever that means). It apparently works better for various classes of squirrely devices, so I should keep it in mind if I have trouble.

Also from the Android Bluetooth pages comes this obscure piece of advice: Hint: If you are connecting to a Bluetooth serial board then try using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. (So bluetooth uses random numbers to convey information? :-).

Seems to be true though: If I go into the BluetoothChatService.java file and change the value of MY_UUID to the magic string above, I can indeed connect with my remote prototype devices using the bluetooth chat example (I can't do anything once I'm there, but the connection is successful).

Another thing to figure out: Java takes pride in not having anything to do with bit twiddling and hardware access, but the protocol to talk to the remote microcode needs specific format binary messages. Since there are lots of existing Java apps that talk various internet protocols with similar issues, I assume there must be some concessions in the language somewhere for getting bit level record formats correct. (The Java ByteBuffer class seems like it might get involved here).

So it looks like there is lots of gibberish to digest before I get anywhere. Adding to the fun is the fact that the emulator can't do bluetooth, so I have to use my real phone for testing anything I write.

I can whip out a cheesy user interface on the emulator, but thats about as far as I can go with it:

And actually trying to use my real phone exposes a couple of problems. The first is a no permission error when I try to connect to the phone after plugging in the USB cable.

Turns out I need to create this file to grant permission for ordinary users like me to get to the phone:

/etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="0489", MODE="0666", GROUP="plugdev"
SUBSYSTEM=="usb", ATTR{idVendor}=="04b0", MODE="0666", GROUP="plugdev"

That vendor ID is for my phone (a Motorola Triumph). A different phone would no doubt have a different vendor id (lsusb can tell you what shows up when you plug your phone in).

Now I can plug the phone in and talk to it with adb, but while it is plugged in, a neverending stream of errors keeps growing in the system logs because the linux usb-storage driver is trying to access the device as a disk, but I haven't told the phone to grant permission to my linux box to access the sdcard. I can make it stop by granting sdcard permission, but then I can't debug apps that access the sdcard locally (because the sdcard is now owned by the linux box, not the phone). I asked if anyone knew how to fix this, and got this answer. Which led to the creation of this file:

/etc/modprobe.d/myphone.conf

options usb-storage quirks=0489:c001:i,04b0:018f:i

That enables the ignore quirk in the usb-storage driver for the specific vendor/device ID that corresponds to my Motorola Triumph phone.

On my fedora system, the usb-storage driver gets loaded during the initial ramfs startup, so I also had to do this:

dracut --force
reboot

After the reboot, I can now plug in the phone, and no message spew ensues. (Of course, I can't mount the sdcard as a USB drive any more, but I always used Wi-Fi to transfer files anyway, so that doesn't really matter to me).

So, now I can use adb to talk to my phone for various debugging activities in my quest for a working demo program.

The simplest debug technique is the Android equivalent of the good old printf debugger. You stick calls to the Log class in your code and monitor them with the adb -d logcat command which sucks the debug log off the phone and spews it to stdout in a terminal.

I also found this blog entry with a good description of how to connect the jdb command line java debugger to your phone, but it is complicated enough that I'll stick with the printf debugger until I get desperate :-).

And this debug technique is paying off! I actually connected to one of my prototypes and sent a bad command, and got back an error response:

A snapshot of this version of the source can be found here: AardRemoteDemo-2012-06-23.tar.bz2

It can't be too much longer before I can send the commands to turn on the receiver and get back an actual learned IR code (I do notice the service sends me the entire 1024 byte buffer even if it only read 4 bytes — I probably ought to do something about that - actually, it sends the size info as well, I just had to pay attention to it).

In AardRemoteDemo-2012-06-25.tar.bz2 I have made a start on the complete code, but I need some semi-complex code to assemble the pieces of the learned remote code, so there is more to do (I can see the pieces show up in the log now, but that's all I do with them at the moment).

I haven't disappeared, but I've been making a lot of detours as I foolishly think about future code. I certainly planned on a complete rewrite or three after getting this demo working, but I keep drifting off into reading up on what I'll need in the future and not actually finishing the demo. For instance, this post seems to indicate that everything I'm doing is wrong :-).

Worse yet, the original BluetoothChat code is wrong in more ways than one. I had to change the code to make a new buffer for each read so I wouldn't wind up reading new data on top of old while the main thread was still working on the old stuff.

I'm also being forced to actually delve deeper into Java to find appropriate classes to handle the bluetooth protocol messages, for instance java.io.ByteArrayOutputStream is what I'm now (trying to) use to build up a complete protocol message from the dribs and drabs I read from the bluetooth socket. I can still imagine the demo working someday (as long as you don't rotate the screen or switch to another app).

Things are slowly happening though. Here you see more messages being exchanged:

When I finally get a complete round trip to happen in the demo, it will be time to try and turn out some production quality code (or at least less error prone code).

And it finally happened! I learned an IR code and sent it back out. This demo program is finished: AardRemoteDemo-2012-06-29.tar.bz2.

It doesn't do anything the “right” way, but by golly, it demonstrates the AardRemote hardware successfully talking my android phone and proves that the eventual goal is possible:

The partial IR code you see above sends a mute to my Samsung TV. For a truly amazing result, I was even able to disconnect from one AardRemote, connect to another, and send the IR code I learned from the first one via the second one (and watch the mute indicator change on my TV, so it even worked).

Android things I learned:

  • Don't trust the SDK examples as good code :-).
  • You need udev and kernel tricks to be able to conveniently use a real device for development via a linux system.
  • Bluetooth programs should include checks to enable bluetooth (I removed that from the demo and I kept forgetting to turn bluetooth on before running the program).
  • Java can be awful primitive compared to C++ (I was looking for something more like std::vector when I finally dug up java.io.ByteArrayOutputStream). I haven't yet found any Java equivalent for memchr() (to do things like search for null bytes in a byte array).
  • It is also a pain in the patoot that Java has no unsigned types, so you spend lots of time casting to (byte) and anding with 0xff.
  • Using the android.util.Log class together with the adb logcat command isn't really that bad a debug tool. See the top level Makefile I included in the tarball for an example of how to filter the output for just the interesting tags.
  • The SDK ddms tool is useful for taking screen shots off a real phone (that's where most of the ones above came from).
  • It is going to be a long hard slog to get from this crude demo to the wondrous system of my dreams :-).
 
[Next] [Top] [Prev]  
Page last modified Fri Jun 29 22:29:10 2012