一、驱动介绍
输入用户驱动程序为应用程序提供接口,向Android的输入管道注入事件。有了这个API,应用程序可以使用Peripheral I/O模拟一个人机界面的设备(HID)或者连接外部硬件到输入系统。比如说,我们可以使用开关按钮GPIO的信号输入,通过输入驱动API模拟呈键盘上按键的输入事件,下面我们会具体演示如何实现。
二、使用步骤
实现输入用户驱动,有如下步骤:
1.创建驱动:使用InputDriver.Builder和源类型SOURCE_CLASS_BUTTON创建一个新的输入驱动实例。
2.注册驱动:使用UserDriverManager的registerInputDriver()方法注册这个驱动。

public class TouchpadDriverService extends Service {// Driver parametersprivate static final String DRIVER_NAME = "Touchpad";private static final int DRIVER_VERSION = 1;private InputDriver mDriver;@Overridepublic void onCreate() {super.onCreate();mDriver = InputDriver.builder(InputDevice.SOURCE_TOUCHPAD).setName(DRIVER_NAME).setVersion(DRIVER_VERSION).setAbsMax(MotionEvent.AXIS_X, 255).setAbsMax(MotionEvent.AXIS_Y, 255).build();UserDriverManager manager = UserDriverManager.getManager();manager.registerInputDriver(mDriver);}
}

3.转换事件:当一个硬件事件发生,使用当前的事件代码和输入动作为每个状态改变构造一个新的KeyEvent。
4.注入事件:使用输入驱动的emit()方法向这个驱动中注入事件。

private void triggerEvent(boolean pressed) {int action = pressed ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP;KeyEvent[] events = new KeyEvent[] {new KeyEvent(action, KEY_CODE)};if (!mDriver.emit(events)) {Log.w(TAG, "Unable to emit key event");}
}

5.处理事件:在前台Activity通过实现onKeyDown()、onKeyUp()和onGenericMotionEvent()方法来获取相关事件,并处理。

public class HomeActivity extends Activity {@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {// Handle key pressed and repeated eventsreturn true;}@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {// Handle key released eventsreturn true;}@Overridepublic boolean onGenericMotionEvent(MotionEvent event) {// Handle motion input eventsreturn true;}
}

6.注销驱动:当你不在需要关键事件的时候注销驱动。

public class TouchpadDriverService extends Service {@Overridepublic void onDestroy() {super.onDestroy();UserDriverManager manager = UserDriverManager.getManager();manager.unregisterInputDriver(mDriver);}
}

三、案例展示

这里我们实现一个最简单的模拟键盘,通过两个开关按钮的GPIO信号输入,通过输入驱动API分别模拟键盘上a和b字母的输入。
1.硬件准备:
 
树莓派3开发板 1块
  面包板 1块
  按钮开关 2个
  电阻 2个
  杜邦线(母对公,公对公) 若干
广告时间咯:如果你还没有自己的开发板和元器件,到我们的“1024工场微店”来逛逛一逛吧(文章底部二维码),这里能一次性有买到你想要的!
2.电路搭建:

3.代码实现:
InputDemo\app\src\main\java\com\chengxiang\inputdemo\KeyDriverService.java

public class KeyDriverService extends Service {private static final String TAG = KeyDriverService.class.getSimpleName();private static final String A_DRIVER_NAME = "Akey";private static final int A_DRIVER_VERSION = 1;private static final int A_KEY_CODE = KeyEvent.KEYCODE_A;private static final String B_DRIVER_NAME = "Bkey";private static final int B_DRIVER_VERSION = 1;private static final int B_KEY_CODE = KeyEvent.KEYCODE_B;private static final String A_GPIO_NAME = "BCM5";private static final String B_GPIO_NAME = "BCM6";private UserDriverManager mUserDriverManager;private InputDriver mADriver;private InputDriver mBDriver;private Gpio mAGpio;private Gpio mBGpio;private GpioCallback mGpioCallback = new GpioCallback() {@Overridepublic boolean onGpioEdge(Gpio gpio) {Log.d(TAG, "onGpioEdge");try {//获取开关按键的信号输入后,转换成A和B按键的输入事件if (gpio == mAGpio) {triggerEvent(mADriver, gpio.getValue(), A_KEY_CODE);} else if (gpio == mBGpio) {triggerEvent(mBDriver, gpio.getValue(), B_KEY_CODE);}} catch (IOException e) {e.printStackTrace();}return true;}@Overridepublic void onGpioError(Gpio gpio, int error) {Log.w(TAG, gpio + ": Error event " + error);}};public KeyDriverService() {}@Overridepublic void onCreate() {super.onCreate();PeripheralManagerService manager = new PeripheralManagerService();try {mAGpio = manager.openGpio(A_GPIO_NAME);mAGpio.setDirection(Gpio.DIRECTION_IN);mAGpio.setActiveType(Gpio.ACTIVE_LOW);mAGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);mAGpio.registerGpioCallback(mGpioCallback);mBGpio = manager.openGpio(B_GPIO_NAME);mBGpio.setDirection(Gpio.DIRECTION_IN);mBGpio.setActiveType(Gpio.ACTIVE_LOW);mBGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);mBGpio.registerGpioCallback(mGpioCallback);} catch (IOException e) {e.printStackTrace();}//分别创建A字母按键和B字母按键输入驱动实例mADriver = InputDriver.builder(InputDevice.SOURCE_CLASS_BUTTON).setName(A_DRIVER_NAME).setVersion(A_DRIVER_VERSION).setKeys(new int[]{A_KEY_CODE}).build();mBDriver = InputDriver.builder(InputDevice.SOURCE_CLASS_BUTTON).setName(B_DRIVER_NAME).setVersion(B_DRIVER_VERSION).setKeys(new int[]{B_KEY_CODE}).build();//注册A字母按键和B字母按键输入驱动mUserDriverManager = UserDriverManager.getManager();mUserDriverManager.registerInputDriver(mADriver);mUserDriverManager.registerInputDriver(mBDriver);}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic void onDestroy() {super.onDestroy();if (mAGpio != null) {try {mAGpio.unregisterGpioCallback(mGpioCallback);mAGpio.close();mAGpio = null;} catch (IOException e) {Log.w(TAG, "Unable to close GPIO", e);}}if (mBGpio != null) {try {mBGpio.unregisterGpioCallback(mGpioCallback);mBGpio.close();mBGpio = null;} catch (IOException e) {Log.w(TAG, "Unable to close GPIO", e);}}//当你不在需要关键事件的时候注销驱动mUserDriverManager.unregisterInputDriver(mADriver);mUserDriverManager.unregisterInputDriver(mBDriver);}private void triggerEvent(InputDriver inputDriver, boolean pressed, int keyCode) {int action = pressed ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP;KeyEvent[] events = new KeyEvent[]{new KeyEvent(action, keyCode)};//使用emit()方法转换成Android事件if (!inputDriver.emit(events)) {Log.w(TAG, "Unable to emit key event");}}
}

InputDemo\app\src\main\java\com\chengxiang\inputdemo\MainActivity.java

public class MainActivity extends AppCompatActivity {private static final String TAG = MainActivity.class.getSimpleName();private EditText mEditText;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mEditText = (EditText) findViewById(R.id.edittext);//这里我们将输入焦点放在输入框中,故按下开关按钮会输入A和B字母mEditText.requestFocus();}//在前台Activity通过实现onKeyDown()、onKeyUp()和onGenericMotionEvent()方法来获取相关事件@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {Log.d(TAG,"onKeyUp:"  + keyCode);return true;}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {Log.d(TAG,"onKeyDown:"  + keyCode);return true;}public void toNext(View view) {Intent intent = new Intent(this,NextActivity.class);startActivity(intent);}
}

代码库:https://github.com/ThingsDeveloper/inputdemo

4.运行结果:

点击开关按钮,在输入框中会输入对应的A和B字母。

1.抛弃各种找元器件的烦恼,来“1024工场”旗舰店,一次性买到你所想要的:树莓派套装—专为Android Things打造。

电脑用户,点击如下链接进入淘宝宝贝页面:
https://item.taobao.com/item.htm?spm=686.1000925.0.0.3f11c9ed68fPu7&id=549263158263
手机用户,打开淘宝客户端扫描二维码:
2.完整和持续更新的《使用Android打开物联网开发大门——Andoid Thigns开发》文档,欢迎大家阅读! 
https://www.kancloud.cn/workshop1024/android_things_develop/360773 
 
3.新技术,新未来!欢迎大家关注“1024工场”微信服务号,时刻关注我们的最新的技术讯息。
4.加入“Android Things开发”QQ讨论群,一起学习一起Hi。(甭客气!尽情的扫描或者长按!)

Android Things:用户驱动-输入驱动相关推荐

  1. Linux按键输入实验(体验一下输入驱动,实际开发使用input子系统处理)

    目录 Linux下按键驱动原理(使用原子操作) 硬件原理图分析 实验程序编写 修改设备树文件 按键驱动程序编写 编写测试APP(循环读取按键值) 运行测试 编译驱动程序和测试APP 运行测试(whil ...

  2. Android 平台电容式触摸屏的驱动基本原理

    Android 平台电容式触摸屏的驱动基本原理 Android 平台电容式触摸屏硬件基本原理 Linux 与 Android 的多点触摸协议 Linux输入子系统:事件的编码 转载于:https:// ...

  3. Android深度探索--HAL与驱动开发----第五章读书笔记

    第五章主要学习了搭建S3C6410开发板的测试环境.首先要了解到S3C6410是一款低功耗.高性价比的RISC处理器它是基于ARMI1内核,广泛应用于移动电话和通用处理等领域. 开发板从技术上说与我们 ...

  4. Android系统 linux内核按键驱动开发

    Android系统 linux内核按键驱动开发 前言 刚入门的小白,在csdn的帮助下完成了第一个按键驱动,特写此文记录学习并分享给有需要的人. 1.修改设备树.dts 我是用的开发板是rp-rk32 ...

  5. Android MTK LCM Driver 屏驱动

    Android MTK LCM Driver 屏驱动 ---- 屏驱动小结 手机驱动调试第一就是LCM,也就是我们说的LCD屏,因此要求驱动第一时间将确认和点亮.此篇就简单描述了在MTK 6765(A ...

  6. Android系统韦根调试从驱动到应用(二)

    Android系统韦根调试从驱动到应用 软件开发平台:android P 源码. 硬件开发平台:nxp imx8m mini开发板. 本文记录在nxp 8m mini 硬件平台, androidP 源 ...

  7. android向windows推送驱动,Windows上安装完美的Android手机驱动

    无论什么Android手机,若想和电脑进行连接,都必须在电脑上面安装Android手机的USB连接驱动,这个过程非常简单,以下是相关的流程: 眼尖的可以看到这个驱动是Desire的,其实驱动是通用的, ...

  8. android edittext输入邮箱,[Android教程]EditText怎样限制用户的输入?数字/字母/邮箱

    有输入必有验证.为了防止用户随便输入确保提交数据的合法性,程序不得不在文本输入框(EditText)中增加限制或验证. 关于输入类型有数字.字母.邮箱.电话等形式,这些具体得根据业务来.那么Andro ...

  9. linux平台驱动运行空间,UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍...

    UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由搜集整理) UIO(Userspace I/O)是运行在用户空间的I/O技术.Linux系统中一般的驱动设备都是 ...

最新文章

  1. 语义分割--DeconvNet--Learning Deconvolution Network for Semantic Segmentation
  2. vue 打包体积过大 实现懒加载 ????
  3. kafka抑制启动时的log INFO为WARN级别
  4. C# 对接微信支付时生成符合 RFC3339 标准的日期时间字符串
  5. Java 身份证工具类
  6. Python HTTP库:requests快速入门
  7. 用数组建立二叉树(LeetCode二叉树测试)
  8. 阿里P8架构师谈:如何搭建亿级并发系统的性能指标体系
  9. C#——SqlParameter的使用方法及注意事项
  10. 解决ubuntu与virtualbox共享文件夹访问权限问题
  11. Windows程序设计-位图和位块传输
  12. 绕过tp路由器管理密码_TP-Link路由器登录密码怎么重置【详细介绍】
  13. 暴力破解压缩包原理及方法
  14. BeyondCompare的三种破解方法
  15. UVM jelly_bean
  16. linux 把进程调到前台,【如何将后台运行的程序转到前台来?】
  17. 基于Hashids的高效游戏礼包兑换码系统完整设计
  18. 只要有心,学好Linux并非难事
  19. MATLAB绘制正弦函数与余弦函数的线性组合曲线
  20. 使用do-while结构计算常数e的值。

热门文章

  1. 安装Python 出现0x80072f7d错误的解决办法
  2. 比较容易考前计算机好的985大学,容易考的985有哪些?附性价比高的985大学排名...
  3. 024空格沙悟净死亡
  4. How to deploy the apk file on your Android Phon...
  5. SQLSERVER 多表联合查询(join)
  6. mysql多表联合查询练习题
  7. waterdrop(token方式)连接星环科技云平台tdc(kerberos认证)
  8. Android 利用系统下载管理器下载apk
  9. Linux——Linux驱动之设备树下platform总线驱动编写实战(手把手教你设备树下platform总线利用GPIO控制蜂鸣器完整实现过程)
  10. WindowManager