AndroidのプログラミングができればRaspberry Piだって動かせる！

# はじめに

[Life is Tech！#1 Advent Calendar](https://qiita.com/advent-calendar/2020/life-is-tech)の1日目を担当します，Androidメンターのあみだです！ よろしくお願いします！
初日の内容ですが，ラズパイで動くAndroidこと**Android Things**についてプログラムの作成から実機で稼働させるところまで書いていきたいと思います！

# Android Thingsとは

まずはAndroid Thingsの概要についてざっくり説明していきたいと思います．

Android ThingsとはGoogleがIoT機器向けに提供しているプラットフォームで，その名の通りAndroidが元になっています．
そのためAndroidのプログラミング経験があれば簡単に開発が可能です．
しかし2019年2月にはIoT全般からスマートスピーカーとスマートディスプレイ向けとターゲット規模が縮小し，ハードウェアもRaspberry Pi 3BとNXP Pico i.MX7Dのみの対応になるなど，あまり成功したとは言えない形で幕を引きつつあります．

廃れ気味ではありますが，AndroidのGUIを使いつつGPIOなども利用できるため個人で遊ぶ分には十分に楽しめると思います．

# アプリ開発

Android Thingsの概要に触れたところで，早速開発に移りたいと思います．
今回はGUI上のボタンをタップすることでLEDが点灯/消灯する簡単なアプリを作成します．言語はKotlinで書いていきます．

通常のAndroidアプリ制作と同様に，Android Studioを利用します．
新規プロジェクトの作成時にAndroid Thingsタブを選択し，空のアクティビティを選択して次へを押します．
![新規プロジェクトの作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/828239/4efbde09-02fa-0608-a6cf-72dea8125bc7.jpeg)
minSDKは27以上にします．Android Things用の新しいAPIが使えるそうです．
あとは特に変更する必要がないので，そのまま進めましょう．
通常のAndroidアプリ制作時と同じような画面が出てくると思います．

### レイアウト
まずレイアウトを作成しますが，必要な部品はボタンだけですので解説は省略します．コードは以下のとおりです．

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
```

また，[こちらの記事](https://qiita.com/ikemura23/items/d52da200995ea48fef47#%E5%88%9D%E5%9B%9E%E3%83%93%E3%83%AB%E3%83%89%E3%81%AF%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%8B)のようにActivityに`Theme.AppCompat`を使わないとエラーが発生するため，themes.xmlも編集します．

```xml
<resources>
    <style name="Theme.App" parent="Theme.AppCompat.Light.DarkActionBar" />
</resources>
```

### プログラム
次にプログラムを記述します．
まず全体像としては以下のような形になります．

```kotlin:MainActivity.kt
package test.samplethings

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import com.google.android.things.pio.Gpio
import com.google.android.things.pio.PeripheralManager

/**
 * Skeleton of an Android Things activity.
 *
 * Android Things peripheral APIs are accessible through the PeripheralManager
 * For example, the snippet below will open a GPIO pin and set it to HIGH:
 *
 * val manager = PeripheralManager.getInstance()
 * val gpio = manager.openGpio("BCM6").apply {
 *     setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
 * }
 * gpio.value = true
 *
 * You can find additional examples on GitHub: https://github.com/androidthings
 */
class MainActivity : AppCompatActivity() {
    lateinit var gpio: Gpio
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val manager = PeripheralManager.getInstance()
        gpio = manager.openGpio("BCM21").apply {
            setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
            setActiveType(Gpio.ACTIVE_HIGH)
        }

        findViewById<Button>(R.id.button).setOnClickListener {
            gpio.value = !gpio.value
        }
    }

    override fun onDestroy() {
        gpio.close()
        super.onDestroy()
    }
}
```

次に各コードの解説をしていきます．

```kotlin:GPIOの準備
val manager = PeripheralManager.getInstance()
gpio = manager.openGpio("BCM21").apply {
    setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
    setActiveType(Gpio.ACTIVE_HIGH)
}
```

まずこの部分ではPeripheralManagerのインスタンスを生成し，そこから指定したGPIOを開いています．
今回はBCM21，つまり物理ピンで40番を設定します．
次にsetDirectionですが，これはこのピンが入力用か出力用か，また出力であれば初期はLow（0V）かHigh（3.3V）かを設定するメソッドです．
今回はLEDを点滅させるため，出力かつ初期値Lowに設定しています．
setActiveTypeはBoolean型で表されるGPIO出力のtrueが，Low（0V）かHigh（3.3V）かを設定するメソッドです．
今回はHighをtrueに設定しています．

```kotlin:On/Off
findViewById<Button>(R.id.button).setOnClickListener {
    gpio.value = !gpio.value
}
```

ボタンをタップした際に出力の値を反転させます．

```kotlin:片付け
override fun onDestroy() {
    gpio.close()
    super.onDestroy()
}
```

onCreate内で開いたGPIOを終了時に閉じます．

### Manifestの設定

GPIOを操作するためにはパーミッションの設定が必要になります．
なのでAndroidManifest.xmlに`<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />`の一文を追加します．
また，レイアウトで触れたエラーの対応として`<application android:label="@string/app_name">`に`android:theme="@style/Theme.App"`を追加します．

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

    <uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />

    <application android:label="@string/app_name"
        android:theme="@style/Theme.App">
        <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>
            <!-- Make this the first activity that is displayed when the device boots. -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```

以上でThingsアプリの作成は完了です．
あとはAndroidアプリ制作時と同様にBuidからAPKを作成しておきましょう．

# ラズパイへのインストール
まずは[Android Things Console](https://partner.android.com/things/console)にログインしましょう．
Googleアカウントがあれば規約に同意することで使えるようになります．

次にCreate Productを選択し，出てきた項目を埋めていきましょう．
SOM TypeはRaspberry Pi3を選択します．
![popup](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/828239/3f880530-e15f-9677-9ad9-f9a3672d9beb.png)

作成すると以下のような画面が開くと思います．このModelsにある項目（図では6h16o0）を選択しましょう．
![menu](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/828239/18ba426b-f1e9-f594-76ad-70c48aebe54f.png)

次の画面でCREATE A BUILD CONFIGURATIONを選択し，項目を埋めていきます．
以下は特に設定する項目です．

- Select your Android Things versionは最新のものを選択．
- Select AppsはADD AN APPの項目を選択し，UPLOAD NEW APPから先程ビルドしたAPKをアップロード．
- アップロードされたアプリにチェックを入れてAPPLYを選択．パーミッションの許可が求められますので許可してSAVE．

他の項目は適当に入力したりNEXTで飛ばしたりして大丈夫です．
作成が完了したら以下のように表示されると思います．
![list](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/828239/6b47b18a-0445-1b3f-0d34-aa6a6d89915a.png)
このDownloadの項目を選択し，Developmentを押すとイメージのダウンロードが始まります．
ダウンロードが完了したらbalenaEtcherなどでmicroSDに書き込みましょう．
これでインストールも完了です．

# 動作確認

あとはラズパイのGNDと40番を抵抗とLEDに繋げ，ラズパイとディスプレイを接続した状態で電源を点ければ完成です！　写真は少々見づらいですがちゃんとLEDをOn/Offできます．
![完成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/828239/164885f1-7ca4-10ab-852c-17287a7224ff.jpeg)
今回はAPKをアップロードしてイメージを使いましたが，ADBを使って無線接続してデバッグすることも可能です．
その場合はAndroid Thingsの設定からIPアドレスを確認して`adb connect [IP address]`，または`adb connect Android.local`で接続しましょう．

# おわりに

「AndroidのプログラミングができればRaspberry Piだって動かせる！」ということで，Android Thingsを使った開発を行っていきました！
今回はGPIOをそのまま使いましたが，PWMやSPIなども使えるので他のセンサを使うこともできますし，ハーフミラーフィルムを貼ったディスプレイを使ってスマートミラーを作ってみても面白いと思います．
これまでAndroidではスマホアプリしか作ってこなかったけれど，ラズパイで動かせばもっと違うことができて面白そうと思ってもらえると幸いです！