Monday, May 28, 2012

Sony SmartWatch as name tag

As I mentioned earlier, I got a Sony SmartWatch at AnDevCon. I have been trying to come up with app ideas, but most of them didn't pass the "I can just pull out my phone" test. I was chatting with some friends, and one of them unclipped the watch from its strap and clipped it on his shirt. Now that's an awesome name tag!

I decided to write an app that reads images out of a folder on the SD card and show them on the watch as a slideshow. I first wrote a widget, but that did not work well because there was a loading screen between each refresh. I looked into the SDK some more, and decided to write a control instead. I refactored my widget code to add a control, but the control simply would not show up on the watch. I was studying the sample code very carefully and just could not figure out why. So I went to bed.

The next morning I started a fresh project to write the control. That worked. I then added a widget. Now the widget would not show up. It suddenly occurred to me that perhaps the LiveWare manager stored the app properties in a database, and did not reset the state when I reinstalled the app, so it did not recognize the additional control/widget.

To test that theory, I went to "Manage Applications" and cleared the data of the LiveWere manager. Well well, now it didn't even know about the SmartWatch! I uninstalled the SmartWatch app and reinstalled it from Google Play. And then I did the Bluetooth pairing again. Finally I installed my extension, and indeed, now my control showed up. That was really difficult to debug!

At this point the control was just displaying some hard-coded images. I swapped in a MediaStore query to get images from the phone:

String[] projection = {
  MediaStore.Images.Media._ID,
  MediaStore.Images.Media.DATA,
  MediaStore.Images.Media.ORIENTATION
};
Cursor cursor = mContext.getContentResolver().query(
  MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
  projection,
  MediaStore.Images.Media.DATA + " LIKE ?",
  new String[] { folder + "/%"},
  MediaStore.Images.Media.DATA);

A few notes here:

  • I use ORIENTATION to rotate the image before displaying.
  • The "where" part of the query is specified by data binding. It is a safe way to say MediaStore.Images.Media.DATA + " LIKE '" + folder + "/%'"

The SmartWatch dims the screen to save battery, but a dimmed name tag is a bit useless, so I added an option to leave the screen on.

setScreenState(alwaysOn ? 
  Control.Intents.SCREEN_STATE_ON : 
  Control.Intents.SCREEN_STATE_AUTO);

After adding the option to change the slide duration, I was ready to deploy. Very curiously, I got a fatal lint error, complaining that I did not localize my app to zh-rTW and ja. I could disable the lint, but as luck has it I speak both Chinese and Japanese, so I decided to localize the app!

The extension is now available on Google Play:
https://play.google.com/store/apps/details?id=com.sqisland.smartwatch.slideshow

You can also check out the Chinese and Japanese descriptions. I got lazy for Japanese, so I did not talk about selecting a folder or using it as a name tag. If you have a good translation, let me know!

The extension took me 2 days end to end. Overall it was a pretty good experience, except the part where I needed to clear data from the LiveWare manager when adding a control to an installed extension.

If you are an Android developer and you would like to get a SmartWatch for writing your own apps, you can submit a request to Sony using this link: https://www.surveymonkey.com/s/VT9D25X. If you do, ping me. I'm curious what you'll do with the SmartWatch!

No comments:

Post a Comment

Inline coding questions will not be answsered. Instead, ask on StackOverflow and put the link in the comment.