一、驱动介绍
输入用户驱动程序为应用程序提供接口,向Android的输入管道注入事件。有了这个API,应用程序可以使用Peripheral I/O模拟一个人机界面的设备(HID)或者连接外部硬件到输入系统。比如说,我们可以使用开关按钮GPIO的信号输入,通过输入驱动API模拟呈键盘上按键的输入事件,下面我们会具体演示如何实现。
二、使用步骤
实现输入用户驱动,有如下步骤:
1.创建驱动:使用InputDriver.Builder和源类型SOURCE_CLASS_BUTTON创建一个新的输入驱动实例。
2.注册驱动:使用UserDriverManager的registerInputDriver()方法注册这个驱动。
public class TouchpadDriverService extends Service {    // Driver parameters    private static final String DRIVER_NAME = "Touchpad";    private static final int DRIVER_VERSION = 1;    private InputDriver mDriver;    @Override    public 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 {    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        // Handle key pressed and repeated events        return true;    }    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        // Handle key released events        return true;    }    @Override    public boolean onGenericMotionEvent(MotionEvent event) {        // Handle motion input events        return true;    }}
6.注销驱动:当你不在需要关键事件的时候注销驱动。
public class TouchpadDriverService extends Service {    @Override    public 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() {        @Override        public 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;        }        @Override        public void onGpioError(Gpio gpio, int error) {            Log.w(TAG, gpio + ": Error event " + error);        }    };    public KeyDriverService() {    }    @Override    public 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);    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        throw new UnsupportedOperationException("Not yet implemented");    }    @Override    public 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;    @Override    protected 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()方法来获取相关事件    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        Log.d(TAG,"onKeyUp:"  + keyCode);        return true;    }    @Override    public 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。(甭客气!尽情的扫描或者长按!)
            

更多相关文章

  1. Android嵌套滑动-Behavior方案实战及细节注意
  2. Android(安卓)Monkey工具
  3. android Studio keytool' 不是内部或外部命令,也不是可运行的程序
  4. "Android系统框架"-Androi的面试必问部分
  5. Android(安卓)自动化测试之Monkey参数介绍及其停止办法
  6. Android(安卓)小应用 - "Smart Help" 之模块介绍
  7. 完全理解android事件分发机制
  8. 点击事件分发机制 关键源码笔记
  9. Android(安卓)实现item可左右滑动移除的GridView

随机推荐

  1. 如何卸载内核代码中的文件系统
  2. 我的电脑认为有符号整数比-1小?
  3. Linux服务器权限管理实践——添加用户只
  4. 《深入理解Linux网络技术内幕》阅读笔记(
  5. Linux Tcp/ip UDP基本概念(6.8)
  6. Codeigniter2.25部署Linux(php5.6)
  7. 在Linux上确定陈旧的Samba挂载的最快方法
  8. Linux无法连接网络解决方案
  9. Linux环境下注册函数的调用顺序
  10. 浅谈如何学习linux