Android Things: first look

Jan6th, 201710:55 am

What is Android Things?

Android Things is an alternative Android version, announced at Google I/O 2015, and released as a first developer preview in December 2016. Its purpose is to develop embedded IoT devices, with a known and widely documented Android ecosystem basis.

It’s currently running on three different boards: the Intel Edison, the NXP Pico i.MX6UL, and the Raspberry Pi 3. Some higher-end boards are coming soon.

On the SDK side, Android Things comes with a specific support library to ease low-level hardware usage. It consists in two parts: the Peripheral I/O API, which supports GPIO, PWM, I2C, SPI and UART, and the User Driver API, which allows a developer to write a hardware-specific, high-level driver, to ease hardware reusability by injecting events into the Android framework. Other applications can in turn use those events without having to interact with the hardware directly.

There’s a down side: the bundled Android is not as complete as the one you can find on a phone. Most of the standard applications aren’t installed (Calendar, Phone…), and standard content providers are absent too (MediaProvider, Dictionary…).

Android Things supports displays, with the default Android UI toolkit. However, the display is a little bit different from what you’re used to see on an Android device: there’s no notification bar, navigation bar or anything, the running application will use the full display. That is, if it uses it at all: displays are purely optional.

Installing Android Things

Installation depends on the device you’re targeting. Up-to-date, device-specific instructions are available in the official documentation.

Note that there is no emulator available (yet?), you’ll need to install Android Things on a real board.

The next steps of this post assume your local adb is connected to your device (that is, adb devices is listing it as attached).

Creating a new application

Android Things uses the same Activity, Service… lifecycles you’re used to see in any Android application. As so, creating an Android Things project is really close to creating an Android one:

create a blank project on Android Studio (selecting a form factor is mandatory, and Android Studio doesn’t support Things yet, keep Phone and Tablet selected), without any activities

in the build.gradle, remove all the dependencies and add the Things support library:

the last step is to create an Activity: create a new blank, without layout, non-support Activity from Android Studio. You’ll also need to add a Things-specific intent-filter to this Activity in the Manifest, so it will start automatically on boot. Keep the Launcher intent-filter to make it easier to start this Activity from Android Studio:

You can run it from Android Studio, and you should see the onCreate mention in the logs.

Lights, action!

I won’t cover Android UI in this post, as it’s something really standard you can already find all over the web. Let’s do a much more fun UI: a blinking LED to indicate the application is running.

Connecting the LED

I only have a Raspberry Pi 3, so I won’t be able to cover the other boards for this part. You can find the Pi pinout details here.

The circuit is dead simple: connect the LED’s cathode to Pi’s ground, a small resistor in series with your LED’s anode (Pi’s GPIOs are 3v3), and the other side of the resistor to the Pi’s BCM6. You can use any pin labelled as GPIO in the diagram.

Pimp your ‘droid

Time to go back to Android Studio. First step: listing the available GPIOs on your board. There’s a new class in the support library to access the GPIOs: PeripheralManagerService.

Now, the only thing left to do is to toggle the GPIO value. This is a single call: ledGpio.setValue(!ledGpio.getValue());. Toggling it every second comes with a purely Android-oriented solution: a Handler, and a delayed Runnable.

publicclassMainActivityextendsActivity{privatestaticfinalintINTERVAL_BETWEEN_BLINKS_MS=1000;privatestaticfinalStringGPIO_PIN_NAME_LED="BCM6";privateHandlerhandler=newHandler();privateGpioledGpio;privateRunnableblinkRunnable=newRunnable(){@Overridepublicvoidrun(){// Exit if the GPIO is already closedif(ledGpio==null){return;}try{ledGpio.setValue(!ledGpio.getValue());handler.postDelayed(blinkRunnable,INTERVAL_BETWEEN_BLINKS_MS);}catch(IOExceptione){Log.e("MainActivity","Error on PeripheralIO API",e);}}};@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);PeripheralManagerServiceservice=newPeripheralManagerService();try{ledGpio=service.openGpio(GPIO_PIN_NAME_LED);ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);handler.post(blinkRunnable);}catch(IOExceptione){Log.e("MainActivity","Error on PeripheralIO API",e);}}}

User drivers

Google already ships some user-drivers, ready to use, in the form of Gradle libraries. Let’s take the Button driver as an example.

Installation

Usage

The button driver provides a simple class which you feed with the GPIO name to use, and a callback:

MainActivity.java

123456789101112131415161718192021222324252627282930313233343536

publicclassMainActivityextendsActivity{privatestaticfinalStringGPIO_PIN_NAME_BUTTON="BCM6";Buttonbutton;@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);Log.d("MainActivity","onCreate");try{button=newButton(GPIO_PIN_NAME_BUTTON,Button.LogicState.PRESSED_WHEN_HIGH);button.setOnButtonEventListener(newButton.OnButtonEventListener(){@OverridepublicvoidonButtonEvent(Buttonbutton,booleanpressed){Log.d("MainActivity","Button has been pressed!");}});}catch(IOExceptione){Log.e("MainActivity","Unable to configure the button",e);}}@OverrideprotectedvoidonDestroy(){super.onDestroy();try{button.close();}catch(IOExceptione){Log.e("MainActivity","There's been an error while closing the button");}}}

Notice that you’ll have to close the GPIO when you leave your Activity (button.close()).

And with those simple dozen lines of Java, you can use your hardware button to trigger things in your application. The button driver also provides a way to bind your hardware button to a software event, then any application can simply listen to the software key event. This is an example binding the button to the key A:

publicclassMainActivityextendsActivity{privatestaticfinalStringGPIO_PIN_NAME_BUTTON="BCM6";ButtonInputDriverinputDriver;@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);try{inputDriver=newButtonInputDriver(GPIO_PIN_NAME_BUTTON,Button.LogicState.PRESSED_WHEN_HIGH,KeyEvent.KEYCODE_A// the keycode to send);inputDriver.register();}catch(IOExceptione){Log.e("MainActivity","Error while binding button",e);}}@OverrideprotectedvoidonDestroy(){super.onDestroy();inputDriver.unregister();try{inputDriver.close();}catch(IOExceptione){Log.e("MainActivity","Error while unregistering the button driver",e);}}@OverridepublicbooleanonKeyDown(intkeyCode,KeyEventevent){if(keyCode==KeyEvent.KEYCODE_A){Log.d("MainActivity","Button has been pressed");returntrue;}returnsuper.onKeyDown(keyCode,event);}}

Conclusion

Even if it may be early to conclude anything from this preview, I have mixed feelings regarding the state of Android Things.

While having the whole UI toolkit available is great for industry-oriented hardware, I don’t really see the point of it in consumer products. Most of the connected devices uses LEDs or a screen with minimal information. From my point of view, a connected device should be set up then forgot, and work without requesting anything from me past the initial configuration. I don’t want to press a button to turn the lights on. I don’t want to take my phone, unlock it, start the relevant application, then press a button to turn the lights on. I want the lights to turn on when I need it. Using a motion sensor, location tracking from my phone, whatever. As long as I have to interact with the lights, they are not smarter than my good old light bulbs with their big button I can use even in the dark with both hands full.

The first thing I expected from this preview was Weave integration. Which is completely absent (I guess it will come eventually). You can start making a connected device powered by Google technologies, but you can’t use the standard Google tries pushing forward to control it. You’ll have to write your own control interface (probably a REST API, which means integrating a web-server in your Android Things application).

Having the ability to work on the IDE I’m used to, with an SDK I already know, and being able to reuse the ton of existing Java libraries is really great though. It makes the entry barrier much lower than usual embedded development. That is, when you have someone else to do the hardware part for you.

I know computing power and storage comes nearly free nowadays, but being used to use AVRs, MSPs…, I can’t help thinking a Raspberry Pi 3 is totaly overkill for that kind of use. I just used a 1.2 GHz, quad-core SoC and 600 MB of storage to blink an LED. Most of those devices will only be remote-controlled and will send data for analysis anyway. An ESP8266 is much smaller, uses less power, comes with built-in Wi-Fi, for a couple bucks.

In the end, I think Google shouldn’t have used Android as a basis for that kind of IoT platform. While it surely looks attractive, it comes with multiple drawbacks inherent to the idea itself. A Google-branded toolchain for something like the ESP8266 with built-in Weave support and first-class Firebase/Google Cloud client libraries would have been a much better approach.