Android IOT - Einstieg

Mit dem Release der Developer Preview von Android IOT bringt Google Android auf Embedded Devices. Insbesondere Android-Entwicklern soll so die IOT-Welt zugänglicher gemacht werden, da die generelle Programmstruktur bzw. der Application-Lifecycle dem einer Android-App sehr ähnlich sind.

Vorerst werden lediglich Intel Edison, Intel Joule, NXP Pico und Raspberry Pi 3 Boards unterstützt. Mein vorhandener Raspberry Pi 1 leider nicht, ich nehme an, dass die älteren RaspberryPi-Boards zu wenig RAM für Android haben und deshalb offiziell nicht unterstützt werden.
Der Raspberry Pi 3 stellt den günstigsten Einstieg in Android IOT dar. Für den RasPi 3B, eine SanDisk Extreme 16GB microSD-Card und das offizielle Gehäuse habe ich insgesamt knapp 58€ gezahlt. Ein Micro-USB-Netzteil war noch von meinem Raspberry Pi 1 vorhanden. Ebenso habe ich bereits früher ein Sunfounder Super Kit V2.0 gekauft welches einen Grundschatz an LEDs, Widerständen, Display, Motor, Breadboard ... bereitstellt. Dies ist sehr nützlich um mit IOT-Projekten jeglicher Art zu starten (Arduino, RaspberryPi, ...) wenn man sich nicht ausschließlich auf Konsolenausgaben limitieren möchte. Ein vergleichbares Kit kann man beispielsweise unter folgendem Link erwerben: Sunfounder Starter Kit.

Die SanDisk Extreme Speicherkarte bietet sehr gute Transferraten und das offizielle Gehäuse ist sehr flexibel, da es Modular aufgebaut ist und Möglichkeiten hat die GPIO-Ports und Anschlüsse wahlweise zu bedecken oder zugänglich zu machen.

Zum Start mit Android IOT ist es empfehlenswert sich auf den offiziellen Google-Seiten einzulesen (https://developer.android.com/things/preview/index.html). Google bietet auch einen Elektronik-Crashkurs / Basiswissen - falls man noch nie an Elektronik gebastelt hat oder sein Wissen auffrischen möchte, ist die folgende Page lesenswert: https://developer.android.com/things/hardware/hardware-101.html.

Benötigte Software:

Bootstrapping

Ich arbeite unter macOS, deshalb beziehen sich alle folgenden Konsolen-Codesnippets auf den Mac. Unter Windows muss man alternativ wahrscheinlich die adb.bat / oder adb.exe verwenden.

Um die erste IOT-App auf den RaspberryPi zu deployen sind folgende Schritte notwendig:

  1. Android-IOT muss auf der MicroSD-Karte des RaspberryPi installiert werden.
  1. MicroSD-Karte mit vorinstalliertem Image in RaspberryPi stecken, Display per HDMI und Netzwerk per LAN-Kabel anschließen.
  • Display wird initial benötigt, da nach dem Bootvorgang die IP des RaspberryPi im Display eingeblendet wird.
  • LAN-Verbindung brauchen brauchen wir initial um eine erste Internetverbindung bereitzustellen (IP per DHCP). Darüber kann das WIFI-Setup durchgeführt werden.
  1. AndroidIOT booten indem man den RaspberryPi per MicroUSB mit Strom versorgt.
  • Nach erfolgreichen Boot wird unten im Display die IP des RaspberryPi angezeigt
  1. Testen ob man sich auf den RaspberryPi verbinden kann.
$ cd <AndroidSdkPath>/platform-tools
$ ./adb connect <IP des RaspberryPi>
  1. Wifi installieren.
$ adb shell am startservice \
    -n com.google.wifisetup/.WifiSetupService \
    -a WifiSetupService.Connect \
    -e ssid <WLAN-Name> \
    -e passphrase <WLAN-Passwort>
  • Nach einem Neustart wird auch die WLAN-IP im Display angezeigt und man kann das Netzwerkkabel entfernen und sich mittels ADB (adb connect) per WLAN mit dem RaspberryPi verbinden.

Hello World

Um zu schauen ob alles funktioniert, können wir eine erste kleine App erstellen, welche lediglich die verfügbaren GPIO-Ports in die Konsole postet.

  • Neues Android Studio Projekt anlegen (File > New > New Project) mit folgenden Eckdaten:
    • App-Name: IotTest
    • Target Android Devices: Phone and Tablet, Minimum SDK API 24 (AndroidIOT ist noch nicht als Target aufgeführt, ist aber an der Stelle kein Problem, da Wir das Projekt später dahingehend anpassen werden)
    • Activity-Template: Empty Activity
    • Activity-Name: HomeActivity
    • IOT-Apps sind sehr ähnlich zu den normalen Android-Apps. Aus diesem Grund können wir auch das "Phone and Tablet" Template nehmen.
  • Wir müssen unsere App mitteilen, dass sie die IOT-Systemlibrary nutzen soll, dazu müssen wir die dependencies-Section der Build.gradle des app-Projekts um folgende Zeile Code ergänzen:
    provided 'com.google.android.things:androidthings:0.1-devpreview'
  • Des Weiteren müssen wir in der AndroidManifest.xml ergänzen, dass die IOT-Library genutzt wird (<uses-library android:name="com.google.android.things"/>) und mindestens einen Intent-Filter hinzufügen, damit das System unsere App nach dem Booten startet.
          <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>

Wir werden einen weiteren Intent-Filter setzen, damit Android-Studio unsere HomeActivity beim Klick des Run-Buttons startet.

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

Am Ende sieht meine AndroidManifest.xml wie folgt aus:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="csdev.it.iottest">

    <application
        android:allowBackup="true"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <uses-library android:name="com.google.android.things"/>

        <activity android:name=".HomeActivity">
            <!-- Launch activity as default from Android Studio -->
            <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>

Da wir kein UI verwenden können wir einige überflüssige Sachen die mit dem App-Template reinkamen aus dem Manifest löschen, wie z.B.:

  • android:icon="@mipmap/ic_launcher"
  • android:roundIcon="@mipmap/ic_launcher_round"
  • android:supportsRtl="true"
    Wichtig an dieser Stelle ist, dass android:theme="@style/AppTheme"enthalten bleibt, da die App sonst nicht startet.

In den Resource-Files des Projekts (res) kann man ebenfalls alle Layouts (aktuell nur eins), sowie alles unter mipmap (die Icons) löschen, da wir keine UI verwenden.

  • Als letztes muss noch unsere HomeActivity angepasst werden. In der onCreate() Methode geben wir unser Hallo World aus und lassen uns vom PeripheralManagerService alle verfügbaren GPIO-Ports auflisten.
    Meine HomeActivity sieht wie folgt aus:
package csdev.it.iottest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.google.android.things.pio.PeripheralManagerService;

public class HomeActivity extends AppCompatActivity {

    private static final String TAG = "HomeActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d(TAG, "Hello World");

        PeripheralManagerService service = new PeripheralManagerService();
        Log.d(TAG, "Available GPIO: " + service.getGpioList());
    }
}

Auch hier kann man setContentView(R.layout.activity_main); löschen, da wir kein XML-Layout nutzen.
Vielleicht kommt in einer der nächsten Android-Studio-Versionen ein "bereinigtes" IOT-Template von Google hinzu.

  • Um die App auszuprobieren müssen wir uns zunächst per ADB mittels WLAN/LAN mit dem RaspberryPi verbinden, dazu kann man am einfachsten die in Android-Studio mitgelieferte Konsole nutzen oder alternativ ein Terminal aufmachen:
$ ./adb connect <IP des RaspberryPi>
  • Eine erfolgreiche Verbindung zum RaspberryPi wird mit folgender Ausgabe quittiert:
* daemon not running. starting it now at tcp:5037 *
* daemon started successfully *
connected to <IP des RaspberryPi:Port>
  • Nachdem die Verbindung hergestellt ist, können wir unsere HelloWorld-App mit Android-Studio auf dem RaspberryPi deployen. Dazu einfach den grünen Run-Button drücken und anschließend den RaspberryPi (z.B. "unknown Iot_rpi3 (Android 7.0, API24) in der Deployment-Target-Liste auswählen und den "OK"-Button drücken. Daraufhin wird die App gebaut und auf dem RaspberryPi installiert sowie die HomeActivity gestartet.
    Über Android-Studio (Android Monitor > logcat)können wir die Konsolenausgabe des RaspberryPi aufrufen und schauen ob unser HelloWorld ausgegeben wird (alternativ per Terminal $ ./adb logcat). In den Logs sollten 2 Zeilen ähnlich den folgenden zu finden sein:
03-18 14:19:02.048  1754  1754 D HomeActivity: Hello World
03-18 14:19:02.055  1754  1754 D HomeActivity: Available GPIO: [BCM12, BCM13, BCM16, BCM17, BCM18, BCM19, BCM20, BCM21, BCM22, BCM23, BCM24, BCM25, BCM26, BCM27, BCM4, BCM5, BCM6]

Mit diesem HelloWorld-Beispiel schafft ihr den ersten Durchstich um Apps auf AndroidIOT zu deployen. Wesentlich spannender ist die Interaktion der IOT-Apps mit externen Hardwarekomponenten, auf welche ich hoffentlich in künftigen Blogposts eingehen kann.