工程模式中用来测试按键响应的方法。通过列出测试按钮,按下某个键就设置该键显示变化即可。
(1)放置按钮的layout xml如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="50dip" android:layout_alignParentTop="true" android:background="@android:color/darker_gray" android:gravity="center" android:text="@string/device_key_test" android:textAppearance="@android:style/TextAppearance.Large" /> <TableLayout android:id="@+id/table_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/title"> </TableLayout> </RelativeLayout>
可根据实际情况来修改
(2)新建key类
public static class Key { Button button; int keyCode; String keyName; boolean keyPressed; public Key(int keyCode, String keyName, boolean keyPressed) { this.keyCode = keyCode; this.keyName = keyName; this.keyPressed = keyPressed; } }并在activity的开始初始化数按键序列数组:
private TableLayout mTableLayout; public final static String TAG = "DeviceKeyTest"; private final static int COLUMN = 2; //一行两个按键控件
private static Key[] keyMap = { new Key(KeyEvent.KEYCODE_VOLUME_DOWN, "volume_down", false), new Key(KeyEvent.KEYCODE_VOLUME_UP, "volume_up", false), new Key(KeyEvent.KEYCODE_BACK, "back", false), new Key(KeyEvent.KEYCODE_MENU, "menu", false), };(3)onCreate内容
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for (int i = 0; i < keyMap.length; i++){ keyMap[i].keyPressed = false; } mTableLayout = (TableLayout) findViewById(R.id.table_layout); mTableLayout.setStretchAllColumns(true); int totalCount = keyMap.length; int row = totalCount / COLUMN; int surplus = totalCount % COLUMN; Log.d(TAG, "row = " + row + " , surplus = " + surplus); //在mTableLayout上放置测试按键序列 for (int i = 0; i < row; i++) { TableRow newRow = new TableRow(this); newRow.setWeightSum(COLUMN); for (int k = 0; k < COLUMN; k++) { final Button button = new Button(this); button.setTextAppearance(this, android.R.style.TextAppearance_Large); button.setText(keyMap[i * COLUMN + k].keyName); button.setSingleLine(); button.setTextColor(Color.BLUE); button.setTextSize(21); button.setGravity(Gravity.CENTER); button.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); keyMap[i * COLUMN + k].button = button; newRow.addView(button, new TableRow.LayoutParams()); } mTableLayout.addView(newRow, new TableLayout.LayoutParams()); } //不足一行的按键控件处理 if (surplus > 0) { TableRow surplusRow = new TableRow(this); for (int i = 0; i < surplus; i++) { final Button button = new Button(this); button.setTextAppearance(this, android.R.style.TextAppearance_Large); button.setText(keyMap[row * COLUMN + i].keyName); button.setSingleLine(); button.setTextColor(Color.BLUE); button.setTextSize(21); button.setGravity(Gravity.CENTER); keyMap[row * COLUMN + i].button = button; surplusRow.addView(button, new TableRow.LayoutParams()); } mTableLayout.addView(surplusRow, new TableLayout.LayoutParams()); } }(4)key的处理
public boolean dispatchKeyEvent(KeyEvent event){ Log.d(TAG, "DeviceKeyTest: dispatchKeyEvent "); boolean isPressed = false; if (event.getAction() == KeyEvent.ACTION_DOWN) { for (int i = 0; i < keyMap.length; i++) { if (keyMap[i].keyCode == event.getKeyCode()) { Log.d(TAG, "keyMap[i].keyName = " + keyMap[i].keyName); keyMap[i].keyPressed = true; keyMap[i].button.setVisibility(View.INVISIBLE); isPressed = true; } } if (isPressed) { boolean isAllPressed = true; for (int i = 0; i < keyMap.length; i++) { if (!keyMap[i].keyPressed) { isAllPressed = false; break; } } if (isAllPressed) { this.finish(); } return true; } } return false; }验证结果如下:
========================================================================================================
getevent&sendevent 是android系统下的一个工具,可以获取和模拟多种按键和触屏操作,期间获取和产生的产生的是raw event。关于event设备的获取,在 /proc/bus/input/devices 下面:$ adb shell cat /proc/bus/input/devices得到详细信息
(1)getevent首先在adb shell后执行getevent获取当前系统注册的input event信息。
getevent
add device 1: /dev/input/event4
name: "AVRCP"
add device 2: /dev/input/event0
name: "mtk-kpd"
add device 3: /dev/input/event3
name: "hwmdata"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 4: /dev/input/event2
name: "mtk-tpd"
add device 5: /dev/input/event1
name: "ACCDET"
按下一次按键时显示:
/dev/input/event0: 0001 0074 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0074 00000000
/dev/input/event0: 0000 0000 00000000
其中/dev/input/event0是device的名字,0001是type,0074 是键码,最后一个根据type不同而不同,比如1按下0弹起。其中type如下定义:
#define EV_SYN 0x00
#define EV_KEY 0x01
#define EV_REL 0x02
#define EV_ABS 0x03
...................................
键码的定义就是Linux的标准值,Input.h。
点击一次TP显示(不确定黑色重复部分为何会有):
/dev/input/event2: 0001 014a 00000001 //input_report_key(tpd->dev, BTN_TOUCH, 1);
/dev/input/event2: 0003 0030 00000001 //input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 1);
/dev/input/event2: 0003 0035 000000af //input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
/dev/input/event2: 0003 0036 0000008e //input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
/dev/input/event2: 0003 0039 00000000 //input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, p);
/dev/input/event2: 0000 0002 00000000 //input_mt_sync(tpd->dev);
/dev/input/event2: 0000 0000 00000000 //结束
/dev/input/event2: 0003 0030 00000001
/dev/input/event2: 0003 0035 000000af
/dev/input/event2: 0003 0036 0000008e
/dev/input/event2: 0003 0039 00000000
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0001 014a 00000000 //input_report_key(tpd->dev, BTN_TOUCH, 0);
/dev/input/event2: 0003 0030 00000000 //input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 1);
/dev/input/event2: 0003 0035 000000af //input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
/dev/input/event2: 0003 0036 0000008e //input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
/dev/input/event2: 0000 0002 00000000 //input_mt_sync(tpd->dev);
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0000 0000 00000000 //结束
(2)setevent模拟发送一个input消息,命令格式:
adb shell sendevent [device] [type] [code] [value],发送时间、格式和上面的一样,需要注意的是在get中code显示的是十六进制,而send中需要用十进制。
如果要模拟一次电源键,进adb shell后执行
sendevent /dev/input/event0 0001 0116 00000001
sendevent /dev/input/event0 0000 0000 00000000
sendevent /dev/input/event0 0001 0116 00000000
sendevent /dev/input/event0 0000 0000 00000000
模拟一次TP操作,实验不成功