In December 2016 Google released the first developer preview of Android Things and Android-based operating system designed for IoT devices, formerly known as Brillo. In this series we’ll take a look at some of the basics of Android Things and create a simple weather station.
Before we dive in to our weather station let’s begin by exploring the very basics of Android Things as this will make things much easier to understand as we progress on to some more advanced ares. We’ll begin by learning how to turn on one of the LEDs on the Rainbow HAT.
At the heart of Android Things is IO – the ability to input and output data in various forms. A single colour LED is arguably the most basic of output because it has a simple, binary state – it is either on or off. Similarly a simple on/off switch is the most basic form of input because it also has a simple binary state. These input and output types are encapsulated by Android Things as General Purpose Input Output (or GPIO for short). We can interact with GPIO devices by using the Gpio class which has a getter and setter for the boolean state of the device. The Gpio class is part of the Things support library, so we must include this in our project in order to interact with devices.
For devices such as the Rainbow HAT there are also user-space drivers which provide helpers for accessing their components. We’ll use the Rainbow HAT driver to make life easier, but we’ll also take a look inside to see what it’s actually doing for us.
So our build.gradle
looks like this:
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion '25.0.0' defaultConfig { applicationId "com.stylingandroid.simplethings" minSdkVersion 24 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { provided 'com.google.android.things:androidthings:0.1-devpreview' compile 'com.google.android.things.contrib:driver-rainbowhat:0.1' }
The only things worthy of note here are the compile and target SDK versions of 24 (because the Android Things developer preview is based upon Android Nougat API24) and the inclusion of the Things support library and Rainbow HAT user-space driver as dependencies.
The first major difference from traditional Android development comes when we take a look at the Manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.stylingandroid.simplethings"> <application android:allowBackup="false" android:icon="@android:drawable/sym_def_app_icon" android:label="@string/app_name" tools:ignore="GoogleAppIndexingWarning"> <uses-library android:name="com.google.android.things" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- Launch activity automatically on boot --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.IOT_LAUNCHER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
The first important things here is that we must declare the use of the Things support library (line 11).
Next we have two different intent-filters which specify how the app may be launched. An Android Things device will not have a traditional launcher app (because there is no guarantee of a traditional UI Toolkit user interface being available – as discussed in part 1 of this series). However, we need to declare a launcher intent-filter to enable us to launch the app from Android Studio and that is the sole purpose of this first intent filter (lines 14-18). For production apps it would make sense to only remove this intent-filter from release builds.
The second intent-filter (lines 21-26) is specific to Android Things and it will automatically launch the app on device startup. Typically an Android Things device will have a single function and your app will be responsible for performing that function. For that reason, the app needs to be started automatically following device startup, and this intent does precisely that.
Finally let’s take a look at our Activity:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { Gpio led = RainbowHat.openLed(RainbowHat.LED_RED); led.setValue(true); led.close(); } catch (IOException e) { e.printStackTrace(); } finish(); } }
All of the work is done by the three highlighted lines. First we use the Rainbow HAT user-space driver to create a Gpio instance for the red LED. Next we set the value to true
to turn the LED on. Finally, being a good citizen, we close the Gpio instance.
Fir this simple app we are then calling finish()
to terminate the app, but most Android Things apps will stay running while the device is powered on – we’ll change this later once we get the weather station working.
That’s simple enough, but it’s worth taking a look inside the Rainbow HAT user-space driver to see precisely what it is doing:
public class RainbowHat { . . . @StringDef({LED_RED, LED_GREEN, LED_BLUE}) public @interface LedPin {} public static final String LED_RED = "BCM6"; public static final String LED_GREEN = "BCM19"; public static final String LED_BLUE = "BCM26"; . . . public static Gpio openLed(@LedPin String pin) throws IOException { PeripheralManagerService pioService = new PeripheralManagerService(); Gpio ledGpio = pioService.openGpio(pin); ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); return ledGpio; } . . . }
PeripheralManagerService is part of the Things support library and provides access to the various low level drivers. In this case it is being used to open a Gpio instance for a specific pinout on the Pi. BCM6
is one of the physical GPIO ports on the PI, and the Rainbow HAT attaches the red LED to pin BCM6
of the Raspberry Pi. So by toggling the value of this pin we can turn the red LED on and off.
Before the Gpio instance is returned, the direction is set to ensure that the Gpio instance correctly behaves as a GPIO output device.
If you are looking to reduce the size of your APK (hardware may be limited, after all) it may be advisable to avoid using user-space drivers, and do everything manually. In this case, adding these three lines to MainActivity and removing the Rainbow HAT user-space driver from the project would be easy enough. However, The Rainbow HAT maps all of its components to different IO on the Pi, and if we sue the user-space driver then it will keep our code more maintainable and easier to understand. Also, it is worth remembering that GPIO isn’t the only kind of IO interface type supported by both the Pi and Android Things – there are other, more complex IO interface types such as Pulse Width Modulation and various Serial IO interface types. These can be much more complex than GPIO and often the user-space driver can simplify access to these, as we’ll see later in the series.
If we run this we can see that we have successfully turned on the red LED:
In the next article we’ll start looking at some more complex interface types and actually begin the implementation of our weather station.
The source code for this article is available here.
© 2017, Mark Allison. All rights reserved.
Copyright © 2017 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.