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 パーミッションが必要です。
  1. <uses-permission android:name="com.google.android.things.permission.MANAGE_INPUT_DRIVERS" />  


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

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

InputDriver にキーイベントを流すときは InputDrivder.emit() に KeyEvent を渡します。
  1. class InputDriverActivity : Activity() {  
  2.   
  3.     private var gpio: Gpio? = null  
  4.     private var inputDriver: InputDriver? = null  
  5.   
  6.     private val callback: GpioCallback = object : GpioCallback() {  
  7.         override fun onGpioEdge(gpio: Gpio): Boolean {  
  8.             val action = if (gpio.value) KeyEvent.ACTION_DOWN else KeyEvent.ACTION_UP  
  9.             // ドライバーに Enter キーイベントを流す  
  10.             inputDriver?.emit(arrayOf(KeyEvent(action, KeyEvent.KEYCODE_ENTER)))  
  11.             return true  
  12.         }  
  13.     }  
  14.   
  15.     override fun onCreate(savedInstanceState: Bundle?) {  
  16.         super.onCreate(savedInstanceState)  
  17.   
  18.         val pioService = PeripheralManagerService()  
  19.   
  20.         try {  
  21.             gpio = pioService.openGpio("GPIO_174").apply {  
  22.                 setDirection(Gpio.DIRECTION_IN)  
  23.                 setEdgeTriggerType(Gpio.EDGE_BOTH)  
  24.                 setActiveType(Gpio.ACTIVE_LOW)  
  25.                 registerGpioCallback(callback)  
  26.             }  
  27.         } catch (e: IOException) {  
  28.             Log.e(TAG, "Error initializing GPIO", e)  
  29.         }  
  30.   
  31.         // Enter キーをサポートするドライバーを用意  
  32.         inputDriver = InputDriver.Builder(InputDevice.SOURCE_CLASS_BUTTON)  
  33.                 .setName("Button")  
  34.                 .setVersion(1)  
  35.                 .setKeys(intArrayOf(KeyEvent.KEYCODE_ENTER))  
  36.                 .build()  
  37.   
  38.         // ドライバーを登録  
  39.         UserDriverManager.getManager().registerInputDriver(inputDriver)  
  40.     }  
  41.   
  42.     override fun onDestroy() {  
  43.         if (inputDriver != null) {  
  44.             // ドライバーの登録を解除  
  45.             UserDriverManager.getManager().unregisterInputDriver(inputDriver)  
  46.             inputDriver = null  
  47.         }  
  48.   
  49.         gpio?.unregisterGpioCallback(callback)  
  50.         try {  
  51.             gpio?.close()  
  52.         } catch (e: IOException) {  
  53.             Log.e(TAG, "Error closing GPIO", e)  
  54.         }  
  55.   
  56.         super.onDestroy()  
  57.     }  
  58.   
  59.     override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {  
  60.         Log.d(TAG, "onKeyDown : $keyCode")  
  61.         if (keyCode == KeyEvent.KEYCODE_ENTER) {  
  62.             return true  
  63.         }  
  64.         return super.onKeyDown(keyCode, event)  
  65.     }  
  66.   
  67.     override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {  
  68.         Log.d(TAG, "onKeyUp : $keyCode")  
  69.         if (keyCode == KeyEvent.KEYCODE_ENTER) {  
  70.             return true  
  71.         }  
  72.         return super.onKeyUp(keyCode, event)  
  73.     }  
  74.   
  75.     companion object {  
  76.         private const val TAG = "InputDriverActivity"  
  77.     }  
  78. }  


contrib-drivers

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

contrib-drivers の button にある ButtonInputDriver を利用すると、GPIO の入力を簡単に KeyEvent に割り当てられます。
  1. implementation 'com.google.android.things.contrib:driver-button:0.3'  
  1. class ButtonInputDriverActivity : Activity() {  
  2.   
  3.     private var inputDriver: ButtonInputDriver? = null  
  4.   
  5.     override fun onCreate(savedInstanceState: Bundle?) {  
  6.         super.onCreate(savedInstanceState)  
  7.   
  8.         inputDriver = ButtonInputDriver("GPIO_174",  
  9.                 Button.LogicState.PRESSED_WHEN_LOW,  
  10.                 KeyEvent.KEYCODE_ENTER)  
  11.     }  
  12.   
  13.     override fun onDestroy() {  
  14.         inputDriver?.unregister()  
  15.         try {  
  16.             inputDriver?.close()  
  17.         } catch (e: IOException) {  
  18.             Log.e(TAG, "Error closing GPIO", e)  
  19.         }  
  20.         super.onDestroy()  
  21.     }  
  22.   
  23.     override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {  
  24.         Log.d(TAG, "onKeyDown : $keyCode")  
  25.         if (keyCode == KeyEvent.KEYCODE_ENTER) {  
  26.             return true  
  27.         }  
  28.         return super.onKeyDown(keyCode, event)  
  29.     }  
  30.   
  31.     override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {  
  32.         Log.d(TAG, "onKeyUp : $keyCode")  
  33.         if (keyCode == KeyEvent.KEYCODE_ENTER) {  
  34.             return true  
  35.         }  
  36.         return super.onKeyUp(keyCode, event)  
  37.     }  
  38.   
  39.     companion object {  
  40.         private const val TAG = "ButtonInputDriverActivity"  
  41.     }  
  42. }  

0 件のコメント:

コメントを投稿