ラベル Android Things の投稿を表示しています。 すべての投稿を表示
ラベル Android Things の投稿を表示しています。 すべての投稿を表示

2017年11月19日日曜日

Android Things をやってみよう - InputDriver 編

User-Space Drivers : input

InputDriver を使うと、タッチイベントやキーイベントをシステムに流すことができます。

これにより、例えば GPIO から入力があったときに Space キーや Enter キーなどの KeyEvent を流すことで、KeyEvent を処理する機能やライブラリをそのまま流用できます。

InputDriver を使うときは com.google.android.things.permission.MANAGE_INPUT_DRIVERS パーミッションが必要です。 <uses-permission android:name="com.google.android.things.permission.MANAGE_INPUT_DRIVERS" />

InputDriver.Builder を使って InputDriver を生成します。

UserDriverManagerregisterInputDriver() で InputDriver を登録し、最後に unregisterInputDriver() で登録を解除します。

InputDriver にキーイベントを流すときは InputDrivder.emit() に KeyEvent を渡します。 class InputDriverActivity : Activity() { private var gpio: Gpio? = null private var inputDriver: InputDriver? = null private val callback: GpioCallback = object : GpioCallback() { override fun onGpioEdge(gpio: Gpio): Boolean { val action = if (gpio.value) KeyEvent.ACTION_DOWN else KeyEvent.ACTION_UP // ドライバーに Enter キーイベントを流す inputDriver?.emit(arrayOf(KeyEvent(action, KeyEvent.KEYCODE_ENTER))) return true } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val pioService = PeripheralManagerService() try { gpio = pioService.openGpio("GPIO_174").apply { setDirection(Gpio.DIRECTION_IN) setEdgeTriggerType(Gpio.EDGE_BOTH) setActiveType(Gpio.ACTIVE_LOW) registerGpioCallback(callback) } } catch (e: IOException) { Log.e(TAG, "Error initializing GPIO", e) } // Enter キーをサポートするドライバーを用意 inputDriver = InputDriver.Builder(InputDevice.SOURCE_CLASS_BUTTON) .setName("Button") .setVersion(1) .setKeys(intArrayOf(KeyEvent.KEYCODE_ENTER)) .build() // ドライバーを登録 UserDriverManager.getManager().registerInputDriver(inputDriver) } override fun onDestroy() { if (inputDriver != null) { // ドライバーの登録を解除 UserDriverManager.getManager().unregisterInputDriver(inputDriver) inputDriver = null } gpio?.unregisterGpioCallback(callback) try { gpio?.close() } catch (e: IOException) { Log.e(TAG, "Error closing GPIO", e) } super.onDestroy() } override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { Log.d(TAG, "onKeyDown : $keyCode") if (keyCode == KeyEvent.KEYCODE_ENTER) { return true } return super.onKeyDown(keyCode, event) } override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { Log.d(TAG, "onKeyUp : $keyCode") if (keyCode == KeyEvent.KEYCODE_ENTER) { return true } return super.onKeyUp(keyCode, event) } companion object { private const val TAG = "InputDriverActivity" } }

contrib-drivers

https://developer.android.com/things/training/first-device/drivers.html#initialize_the_driver_library

contrib-drivers の button にある ButtonInputDriver を利用すると、GPIO の入力を簡単に KeyEvent に割り当てられます。 implementation 'com.google.android.things.contrib:driver-button:0.3' class ButtonInputDriverActivity : Activity() { private var inputDriver: ButtonInputDriver? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) inputDriver = ButtonInputDriver("GPIO_174", Button.LogicState.PRESSED_WHEN_LOW, KeyEvent.KEYCODE_ENTER) } override fun onDestroy() { inputDriver?.unregister() try { inputDriver?.close() } catch (e: IOException) { Log.e(TAG, "Error closing GPIO", e) } super.onDestroy() } override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { Log.d(TAG, "onKeyDown : $keyCode") if (keyCode == KeyEvent.KEYCODE_ENTER) { return true } return super.onKeyDown(keyCode, event) } override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { Log.d(TAG, "onKeyUp : $keyCode") if (keyCode == KeyEvent.KEYCODE_ENTER) { return true } return super.onKeyUp(keyCode, event) } companion object { private const val TAG = "ButtonInputDriverActivity" } }

2017年11月12日日曜日

Android Things をやってみよう - Peripheral 操作編

Peripheral の操作は PeripheralManagerService を使って行います。

GPIO の名前の一覧は PeripheralManagerService.getGpioList() で取得できます。 val pioService = PeripheralManagerService() for (name in pioService.gpioList) { Log.d(TAG, "gpio : $name") } 実行結果 gpio : GPIO_10 gpio : GPIO_128 gpio : GPIO_172 gpio : GPIO_173 gpio : GPIO_174 gpio : GPIO_175 gpio : GPIO_32 gpio : GPIO_33 gpio : GPIO_34 gpio : GPIO_35 gpio : GPIO_37 gpio : GPIO_39

PeripheralManagerService.openGpio() で GPIO を開きます。戻り値は Gpio です。引数には getGpioList() で取得した名前を指定します。 val ledPin = pioService.openGpio(name)
GPIO は General-purpose input/output のことで、GPIO pin はソフトウェアからコントロールできる集積回路上の物理的ピンです。GPIO pin は入力として使って電圧値を読んだり、出力として使って電圧値を変えたりできます。

扱えるのは論理値(true / false)のみで、low value(ピンがグラウンドと同じ電圧値)と high value(ピンが IOREF と同じ電圧値)が論理値にマッピングされます。論理値と high/low のマッピング(true が high/low どちらに対応するか)は設定で変えることができます。

GPIO pin を開くということは、システム全体でこのピンに対するオーナシップを取るということです。これにより close() が呼ばれるまで他から GPIO を開いたりアクセスしたりするのを防ぎます。close() を呼ぶのを忘れると、同じプロセス・アプリに関係なくどこからも GPIO が使えなくなるので注意が必要です。


論理値と high/low のマッピングは Gpio.setActiveType() で指定します。
true に high を対応させるときは Gpio.ACTIVE_HIGH を、true に low を対応させるときは Gpio.ACTIVE_LOW を指定します。 ledPin.setActiveType(Gpio.ACTIVE_HIGH)
ピンの方向(入力 or 出力)は Gpio.setDirection() で指定します。
ピンを入力として使うときは Gpio.Gpio.DIRECTION_IN を指定します。出力として使うときは、初期状態を high にするときは Gpio.DIRECTION_OUT_INITIALLY_HIGH を初期状態を low にするときは Gpio.DIRECTION_OUT_INITIALLY_LOW を指定します。 ledPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
値が変わったときのトリガーのタイミングを Gpio.setEdgeTriggerType() で指定することができます。
ピンを出力として使うときはトリガーの必要がないので Gpio.EDGE_NONE を指定します。
ピンを入力として使う場合、立ち上がり時(low から high になったとき)だけトリガーさせるなら Gpio.EDGE_RISING を指定します。立ち下がり時(high から low になったとき)だけトリガーさせるなら Gpio.EDGE_FALLING を指定します。立ち上がり、立ち下がり両方トリガーさせるなら Gpio.EDGE_BOTH を指定します。 ledPin.setEdgeTriggerType(Gpio.EDGE_NONE)
現在の値を変更するときは Gpio.setValue() を使います。このメソッドはピンが出力として設定されているときだけ使うことができます。 ledPin.value = isChecked
現在の値を読むときは Gpio.getValue() を使います。このメソッドはピンが入力として設定されているときだけ使うことができます。 val value = ledPin.value
ピンの値が変わった時にコールバックを受け取るには Gpio.registerGpioCallback()GpioCallback を登録します。登録した GpioCallback は Gpio.unregisterGpioCallback() で登録解除します。 private val callback: GpioCallback = object : GpioCallback() { override fun onGpioEdge(gpio: Gpio?): Boolean { Log.d(TAG, "onGpioEdge: ${gpio?.name}, ${gpio?.value}") return true } override fun onGpioError(gpio: Gpio?, error: Int) { super.onGpioError(gpio, error) /** error : [android.system.OsConstants] */ Log.d(TAG, "onGpioError: ${gpio?.name}, $error") } } override fun onCreate(savedInstanceState: Bundle?) { ... ledPin.registerGpioCallback(callback) } override fun onDestroy() { super.onDestroy() try { ledPin.unregisterGpioCallback(callback) ledPin.close() } catch (e: IOException) { Log.e(TAG, "Error closing GPIO", e) } }

Android Things をやってみよう - プロジェクト作成編



form factors に Android Things を選ぶ









以下のような build.gradle が作成される apply plugin: 'com.android.application' ... android { ... } dependencies { ... compileOnly 'com.google.android.things:androidthings:+' }


2017年11月11日土曜日

Android Things をやってみよう - セットアップ編

https://developer.android.com/things/index.html

DroidCon SF で Android Things のハンズオンに参加し、Developer Kit をもらったのでいろいろやってみています。

事前準備

- Android Studio 3.0 をインストールする


- システム Image を用意する 1. Android Things Console に行ってサインイン(初回時に Terms of Service の同意が必要)する

2. Create product ボタンをクリックし、プロダクト名と詳細を入力し、対応する SOM type (もらった kit だと NXP Pico i.MX7D) を選択して Create をクリックする



3. 作成されたプロダクトを選択する



4. FACTORY IMAGES タブを選択する

5. Bundles で Empty Bundle を選択する



6. Android Things versions で最新のバージョンを選択し、Click Create Build Configuration をクリックする



7. Build が完了するまで待って、Build configuration list に追加されたアイテムをダウンロードし、解凍する




- Flashing the image 1. ボードと USB ケーブルで接続する (NXP i.MX7D なら USB-C cable が必要)

2. Android SDK の platform-tools/ にパスを通す

3. macOS が High Sierra (10.13) の場合、別の fastboot バイナリをダウンロードする

macOS が High Sierra (10.13) の場合、platform-tools/fastboot に既知の Issue があります。
https://issuetracker.google.com/issues/64292422
#comment8 に添付されているバイナリが使えます。

4. 以下のコマンドを実行してボードが Fastboot モードで起動していることを確認する $ fastboot devices Fastboot モードで起動していない場合は以下のコマンドでデバイスを再起動する $ adb reboot bootloader

5. ダウンロード&解凍した Image 内の flash-all.sh または flash-all.bat を実行する

6. 成功したら再起動するので、以下のコマンドで Android が動いていることを確認する $ adb devices

- WiFi に接続する $ adb shell am startservice -n com.google.wifisetup/.WifiSetupService -a WifiSetupService.Connect -e ssid [network_ssid] -e passphrase [network_pass]

サンプルで遊ぶ

https://developer.android.com/things/sdk/samples.html

ハンズオンでは をやりました。他にもサンプルたくさんあります。

ボードと USB で接続して、普通に Android Studio で開いて実行すれば OK です。別のものをインストールする前に今インストールされているものをアンインストールする必要があるので、忘れないように注意です


コードラボで学ぶ

https://codelabs.developers.google.com/io2017?cat=IoT