Android Things:使用者驅動-輸入驅動
阿新 • • 發佈:2019-02-20
一、驅動介紹
輸入使用者驅動程式為應用程式提供介面,向Android的輸入管道注入事件。有了這個API,應用程式可以使用Peripheral I/O模擬一個人機介面的裝置(HID)或者連線外部硬體到輸入系統。比如說,我們可以使用開關按鈕GPIO的訊號輸入,通過輸入驅動API模擬呈鍵盤上按鍵的輸入事件,下面我們會具體演示如何實現。
二、使用步驟
實現輸入使用者驅動,有如下步驟:
1.建立驅動:使用InputDriver.Builder和源型別SOURCE_CLASS_BUTTON建立一個新的輸入驅動例項。
2.註冊驅動:使用UserDriverManager的registerInputDriver()方法註冊這個驅動。
4.注入事件:使用輸入驅動的emit()方法向這個驅動中注入事件。
1.硬體準備:
樹莓派3開發板 1塊
麵包板 1塊
按鈕開關 2個
電阻 2個
杜邦線(母對公,公對公) 若干
廣告時間咯:如果你還沒有自己的開發板和元器件,到我們的“1024工場微店”來逛逛一逛吧(文章底部二維碼),這裡能一次性有買到你想要的!
2.電路搭建:
3.程式碼實現:
InputDemo\app\src\main\java\com\chengxiang\inputdemo\KeyDriverService.java
3.新技術,新未來!歡迎大家關注“1024工場”微信服務號,時刻關注我們的最新的技術訊息。4.加入“Android Things開發”QQ討論群,一起學習一起Hi。(甭客氣!盡情的掃描或者長按!)
輸入使用者驅動程式為應用程式提供介面,向Android的輸入管道注入事件。有了這個API,應用程式可以使用Peripheral I/O模擬一個人機介面的裝置(HID)或者連線外部硬體到輸入系統。比如說,我們可以使用開關按鈕GPIO的訊號輸入,通過輸入驅動API模擬呈鍵盤上按鍵的輸入事件,下面我們會具體演示如何實現。
二、使用步驟
實現輸入使用者驅動,有如下步驟:
1.建立驅動:使用InputDriver.Builder和源型別SOURCE_CLASS_BUTTON建立一個新的輸入驅動例項。
2.註冊驅動:使用UserDriverManager的registerInputDriver()方法註冊這個驅動。
3.轉換事件:當一個硬體事件發生,使用當前的事件程式碼和輸入動作為每個狀態改變構造一個新的KeyEvent。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); } }
4.注入事件:使用輸入驅動的emit()方法向這個驅動中注入事件。
5.處理事件:在前臺Activity通過實現onKeyDown()、onKeyUp()和onGenericMotionEvent()方法來獲取相關事件,並處理。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"); } }
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.javapublic 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);
}
}
4.執行結果:
點選開關按鈕,在輸入框中會輸入對應的A和B字母。3.新技術,新未來!歡迎大家關注“1024工場”微信服務號,時刻關注我們的最新的技術訊息。4.加入“Android Things開發”QQ討論群,一起學習一起Hi。(甭客氣!盡情的掃描或者長按!)