Help us understand the problem. What is going on with this article?

User Driverを使って、電子部品とAndroid Frameworkをつなぐ

More than 1 year has passed since last update.

AndroidThingsでは、デバイスごとにつけているセンサーやGPS、周辺機器が異なるため、一部のAndroid Frameworkで利用できる機能がデフォルトでは使えなくなっています。

例えばGPSはRaspberry Piには乗っていないため、GPSに関連する機能はデフォルトでは使えません。
ただし、電子部品として追加する分にはGPS等をつけることは可能です。

この時、追加したGPSや温度センサー等をAndroid Frameworkで利用できるようにするのがUser Driverです。
※ドキュメントだと、User-Space Drivers、User Driversと若干表記ゆれがある気がします.

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

User Driverのメリット

主にUser Driverのメリットには以下があります。

  • 移植性
  • 再利用性
  • 統合

色々メリットはありますが、単純に「様々な周辺機器ラップしてAndroid Framework上から触れたほうが、既存のコードやライブラリも使えるし、移植性も高いでしょ」という感じでイメージすればいいと思います。

User Driverの種類

主に3種類あります。

  • GPS
    • GPSです。AndroidのLocation Serviceと統合できます。
  • HID - Human Interface Devices
    • ユーザの入力を扱うDriverです。AndroidのKey EventsやMotion Events(Touchとか)を統合することが出来ます。
    • 例えば物理ボタンとKey Eventsを紐付けたり出来ます。
  • Sensor
    • センサーです。 AndroidのSensorManagerと統合できます。
    • PIOで追加した様々なセンサーをAndroid Framework上(SensorManager)経由で扱う事ができるようになります。

User Driverを試してみる

とりあえず一番簡単なボタンのUser Driverを試してみます。めんどくさいので公式のsample-buttonをそのまま使います。

ハードウェア構成

以下です。

userdriver.png

コード

一応kotlinにして、いらないところやコメントを追加してあります。

MainActivity.kt
package com.github.soundtricker.androidthings.samleuserdriver

import android.app.Activity
import android.os.Bundle
import java.io.IOException
import android.util.Log
import android.view.KeyEvent
import com.google.android.things.contrib.driver.button.Button
import com.google.android.things.contrib.driver.button.ButtonInputDriver
import com.google.android.things.pio.Gpio
import com.google.android.things.pio.PeripheralManagerService


class MainActivity : Activity() {

    companion object {
        private val TAG = MainActivity::class.java.simpleName
        private val GPIO_BUTTON_PIN_NAME= "BCM21"
        private val GPIO_LED_PIN_NAME = "BCM6"
    }

    private var mButtonInputDriver: ButtonInputDriver? = null
    private var mLedGpio: Gpio? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupButton()
        setupLed()
    }

    override fun onDestroy() {
        super.onDestroy()
        destroyButton()
        destroyLed()
    }

    private fun setupButton() {
        try {
            mButtonInputDriver = ButtonInputDriver(GPIO_BUTTON_PIN_NAME,
                    Button.LogicState.PRESSED_WHEN_LOW,
                    KeyEvent.KEYCODE_SPACE
            )
            mButtonInputDriver!!.register()
        } catch (e: IOException) {
            Log.e(TAG, "failed initialize button driver", e)
            return
        }
    }
    private fun setupLed() {
        try {
            val pioSerivce = PeripheralManagerService()
            mLedGpio = pioSerivce.openGpio(GPIO_LED_PIN_NAME)
        } catch (e: IOException) {
            Log.e(TAG, "failed initialize led", e)
            return
        }
    }


    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_SPACE) {
            // Turn on the LED
            setLedValue(true)
            return true
        }

        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_SPACE) {
            // Turn off the LED
            setLedValue(false)
            return true
        }

        return super.onKeyUp(keyCode, event)
    }

    private fun setLedValue(value: Boolean) {
        try {
            mLedGpio!!.value = value
        } catch (e: IOException) {
            Log.e(TAG, "Error updating GPIO value", e)
        }

    }

    private fun destroyButton() {
        Log.i(TAG, "Closing button")
        mButtonInputDriver?.unregister()
        try {
            mButtonInputDriver?.close()
        } catch (e: IOException) {
            Log.e(TAG, "Error closing Button driver", e)
        } finally {
            mButtonInputDriver = null
        }

    }
    private fun destroyLed() {
        try {
            mLedGpio!!.close()
        } catch (e: IOException) {
            Log.e(TAG, "Error closing LED", e)
        } finally {
            mLedGpio = null
        }
    }}


上の

mButtonInputDriver = ButtonInputDriver(GPIO_BUTTON_PIN_NAME,
                    Button.LogicState.PRESSED_WHEN_LOW,
                    KeyEvent.KEYCODE_SPACE
            )
            mButtonInputDriver!!.register()

部分がAndroid FrameworkにUser Driverを登録している部分です。
Android FrameworkとしてUser Driverを登録することで以下のように物理Buttonの押し離しをKey Eventとして、扱う事ができるようになります。

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_SPACE) {
            // Turn on the LED
            setLedValue(true)
            return true
        }

        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_SPACE) {
            // Turn off the LED
            setLedValue(false)
            return true
        }

        return super.onKeyUp(keyCode, event)
    }

なお、上記コードを動かすためには、AndroidManifest.xmlに以下を追加する必要があります。

AndroidManifest.xml
<uses-permission android:name="com.google.android.things.permission.MANAGE_INPUT_DRIVERS" />

まとめ

User Driverによって、Androidらくしセンサーなどを扱えるのはAndroid Thingsのメリットだと思います。
多分

soundTricker
Google API、Google Apps、Google App Engine、Angular(1&2)、Google Apps Scriptらへんの人 一応Google Developer Expert(Apps Script)です。 https://developers.google.com/experts/people/keisuke-oohashi
https://plus.google.com/u/0/112329532641745322160/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした