Android驱动之虚拟按键
来源:互联网 发布:淘宝代销什么产品好 编辑:程序博客网 时间:2024/05/22 06:22
1 背景
nexus one工业设计简洁,类似于iphone只有一个按键的设计,只有中间的一个轨迹球。但是android标准键盘是有 HOME,MENU,BACK,SEARCH等,但是同时要保持工业设计。nexus one是这样解决问题的,显示屏是800X480,但是在电容触摸屏是8xx*480的就是比800要大的地方就变成了虚拟按键,模拟了android标准按键。
2 方案
要实现,虚拟按键,在android里面是靠两层协助实现,底层要把虚拟按键在比显示屏多出的地方规定好虚拟按键的位置大小以及键值等,给上层一文件接口。上层java层启动一个服务来读取这一区域的按键响应,这样就是大体的架构。具体实现如下:
2.1 底层虚拟按键功能实现方案 简而言之,就是在内核中把虚拟按键的所有信息给上层给出,用什么方式?就是用sys文件系统的方式,sys文件系统的路径是约定好的所以代码如下实现。给出信息的协议格式是一段连续的字符串,每个按键有六项分别用冒号分割,按键按键之间也是用冒号分割,六项按顺序分别是: 键类型:键值:按键区域中心x坐标:按键区域中心y坐标:按键区域宽:按键区域高 arch/arm/mach-msm/board-mahimahi.c
- static ssize_t mahimahi_virtual_keys_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
- {
- if (system_rev > 2) {
- /* center: x: back: 55, menu: 172, home: 298, search 412, y: 835 */
- return sprintf(buf,
- __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":55:835:90:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":172:835:125:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":298:835:115:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":412:835:95:55"
- "/n");
- } else {
- /* center: x: home: 55, menu: 185, back: 305, search 425, y: 835 */
- return sprintf(buf,
- __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":55:835:70:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":185:835:100:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":305:835:70:55"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":425:835:70:55"
- "/n");
- }
- }
- static struct kobj_attribute mahimahi_virtual_keys_attr = {
- .attr = {
- .name = "virtualkeys.synaptics-rmi-touchscreen",
- .mode = S_IRUGO,
- },
- .show = &mahimahi_virtual_keys_show,
- };
- static struct attribute *mahimahi_properties_attrs[] = {
- &mahimahi_virtual_keys_attr.attr,
- NULL
- };
- static struct attribute_group mahimahi_properties_attr_group = {
- .attrs = mahimahi_properties_attrs,
- };
- struct kobject *properties_kobj;
- properties_kobj = kobject_create_and_add("board_properties", NULL);
- if (properties_kobj)
- ret = sysfs_create_group(properties_kobj,
- &mahimahi_properties_attr_group);
- if (!properties_kobj || ret)
- pr_err("failed to create board_properties/n");
JAVA上层方案 Java层主要是读取按键信息,然后经过一定的算法,来识别虚拟按键,基本不需要修改,但最好还是熟悉java层的架构这样出问题的时候利于定位 frameworks/base/services/java/com/android/server/KeyInputQueue.java
/*这是虚拟按键的类里面包括了VirtualKey所用到的成员变量和按键定位方法*/
- static class VirtualKey {
- int scancode;
- int centerx;
- int centery;
- int width;
- int height;
- int hitLeft;
- int hitTop;
- int hitRight;
- int hitBottom;
- InputDevice lastDevice;
- int lastKeycode;
- boolean checkHit(int x, int y) {
- return (x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom);
- }
- void computeHitRect(InputDevice dev, int dw, int dh) {
- if (dev == lastDevice) {
- return;
- }
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "computeHitRect for " + scancode
- + ": dev=" + dev + " absX=" + dev.absX + " absY=" + dev.absY);
- lastDevice = dev;
- int minx = dev.absX.minValue;
- int maxx = dev.absX.maxValue;
- int halfw = width/2;
- int left = centerx - halfw;
- int right = centerx + halfw;
- hitLeft = minx + ((left*maxx-minx)/dw);
- hitRight = minx + ((right*maxx-minx)/dw);
- int miny = dev.absY.minValue;
- int maxy = dev.absY.maxValue;
- int halfh = height/2;
- int top = centery - halfh;
- int bottom = centery + halfh;
- hitTop = miny + ((top*maxy-miny)/dh);
- hitBottom = miny + ((bottom*maxy-miny)/dh);
- }
- }
- /*以下就是与底层接口的函数,如果这个函数和底层接口正常,基本上虚拟按键就能够ok*/
- private void readVirtualKeys(String deviceName) {
- try {
- FileInputStream fis = new FileInputStream(
- "/sys/board_properties/virtualkeys." + deviceName);
- /*这里就是读取kernel给出信息的地方,也就是地层与上层接口的地方,所以整个实现的重点就是这里*/
- InputStreamReader isr = new InputStreamReader(fis);
- BufferedReader br = new BufferedReader(isr, 2048);
- String str = br.readLine();
- if (str != null) {
- String[] it = str.split(":");
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "***** VIRTUAL KEYS: " + it);
- final int N = it.length-6;
- for (int i=0; i<=N; i+=6) {
- if (!"0x01".equals(it[i])) {
- Log.w(TAG, "Unknown virtual key type at elem #" + i
- + ": " + it[i]);
- continue;
- }
- try {
- VirtualKey sb = new VirtualKey();
- sb.scancode = Integer.parseInt(it[i+1]);
- sb.centerx = Integer.parseInt(it[i+2]);
- sb.centery = Integer.parseInt(it[i+3]);
- sb.width = Integer.parseInt(it[i+4]);
- sb.height = Integer.parseInt(it[i+5]);
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Virtual key "
- + sb.scancode + ": center=" + sb.centerx + ","
- + sb.centery + " size=" + sb.width + "x"
- + sb.height);
- mVirtualKeys.add(sb);
- } catch (NumberFormatException e) {
- Log.w(TAG, "Bad number at region " + i + " in: "
- + str, e);
- }
- }
- }
- br.close();
- } catch (FileNotFoundException e) {
- Log.i(TAG, "No virtual keys found");
- } catch (IOException e) {
- Log.w(TAG, "Error reading virtual keys", e);
- }
- }
总结 方案基本上就是这样,主要是调试工作可能需要一段时间,还有如果要做虚拟按键,还需要硬件的支持(超过显示区域的触摸屏区域)。本代码基于android 2.1请根据实际情况修改
- android驱动之虚拟按键
- Android驱动之虚拟按键
- Android 虚拟按键驱动实现
- Android 虚拟按键驱动实现
- Android 虚拟按键驱动实现
- Android 虚拟按键驱动实现
- 《android驱动之虚拟按键(触摸屏虚拟按键)》相关几篇文章
- Mstar虚拟按键触摸屏驱动(芯片msg2133,按键使用android虚拟按键实现,特定报点,识别为按键)
- 4412按键驱动移植(按键对应Android系统的三个虚拟按键)
- android虚拟按键
- Android: 发送虚拟按键
- android TP虚拟按键
- android虚拟按键
- android虚拟按键
- android 虚拟按键
- android 隐藏虚拟按键
- android系统移植之按键驱动篇
- android系统移植之按键驱动篇
- c++ 简单实现优先级队列
- 解决------------GetFieldValue 报错:无效的描述符索引
- Circular buffer
- 灵活运用 SQL SERVER FOR XML PATH
- 基于virtio在虚拟机与主机之间传递消息
- Android驱动之虚拟按键
- hdu 1542 Atlantis
- c# 连接短信猫设备源码
- 日志需求
- HOG 理解与源码
- win32 sdk下调用webbrowser控件
- iOS中的模糊效果
- 【性能优化案例】执行计划宁可走全表扫描,也不走索引
- TortoiseSVN 中文版安装问题详解