Android中添加自定义按键 ---- 非标准做法

本文介绍在Android设备上添加自定义按键的过程,包括修改Linux内核驱动以支持按键及其长按和短按功能,并展示了如何在Android层通过uevent观察器捕获这些事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里我来介绍一下怎么在Android中添加自定义按键,首先要打通kernel中的驱动,然后是Android层,我这里介绍一种不是很标准的方法,项目需要。

首先是Linux中,我这里只是把已有的search 按钮替换成我们的用户按钮,并提供长按和短按功能。

修改板级文件,我这边使用的事Freescale imx53的开发板

kernel/arch/arm/mach-mx5/mx53_smd.c

定义按键与哪个GPIO连接

//+++++add our own user button #define MX53_MDK_KEY_USER (1*32 + 23) /* GPIO_2_23 */ #define MX53_MDK_KEY_SEARCH (1*32 + 23) /* GPIO_2_23 */
然后定义这个按键的信息

static struct gpio_keys_button smd_buttons[] = { #ifdef CONFIG_MACH_MX53_MIPAD GPIO_BUTTON(MX53_MIPAD_KEY_VOL_UP, KEY_VOLUMEUP, 1, "volume-up", 0), GPIO_BUTTON(MX53_MIPAD_KEY_VOL_DOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0), #elif defined(CONFIG_MACH_MX53_MDK) //+++++modify for user button by Jay // GPIO_BUTTON(MX53_MDK_KEY_SEARCH, KEY_SEARCH, 1, "search", 0), GPIO_BUTTON(MX53_MDK_KEY_USER, KEY_F1, 1, "user", 0), GPIO_BUTTON(MX53_MDK_KEY_HOME, KEY_HOME, 1, "home", 0), GPIO_BUTTON(MX53_MDK_KEY_BACK, KEY_BACK, 1, "back", 0), GPIO_BUTTON(MX53_MDK_KEY_MENU, KEY_MENU, 1, "menu", 0), GPIO_BUTTON(MX53_SMD_KEY_VOL_UP, KEY_VOLUMEUP, 1, "volume-up", 0), GPIO_BUTTON(MX53_SMD_KEY_VOL_DOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0), #else GPIO_BUTTON(MX53_SMD_KEY_VOL_UP, KEY_VOLUMEUP, 1, "volume-up", 0), GPIO_BUTTON(MX53_SMD_KEY_VOL_DOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0), #endif };
这里我把键值定义为KEY_F1

然后我们在按键驱动中添加新的按键和功能,

/kernel/drivers/input/keyboard/gpio_keys.c

static void gpio_keys_report_event(struct gpio_button_data *bdata) { struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; //+++add by Jay struct device *dev = &bdata->input->dev; char event_string[20]; char *envp[] = { event_string, NULL }; //---- #ifdef CONFIG_MACH_MX53_MIPAD input_event(input, type, button->code, !state); #else //++++++add user button by Jay if(button->code == KEY_F1) { if(state) { startKeyTime = (jiffies*1000)/HZ; user_button_state = 1; user_thread = kthread_run(user_thread_handler, dev, "user-button"); } else { user_button_state = 0; if((jiffies*1000)/HZ - startKeyTime < 1500) { sprintf(event_string, "EVENT=shortpress"); kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); printk("short press\r\n"); } } } //----- else input_event(input, type, button->code, !!state); #endif input_sync(input); }

首先在按键中断到来的时候我们要判断出是我们定义的user button,当按下的时候产生一个下降沿中断,按下的时候state应该为1,先记录按下时的时间,然后开启一个线程,看下线程中做了什么

//++++add by Jay #include <linux/kthread.h> static int startKeyTime = 0; static int user_button_state = 0; static struct task_struct *user_thread; static int user_thread_handler(void *arg) { struct device *dev = arg; while(user_button_state == 1) { char event_string[20]; char *envp[] = { event_string, NULL }; msleep(100); if(((jiffies*1000)/HZ) - startKeyTime > 1500) { sprintf(event_string, "EVENT=longpress"); kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); printk(KERN_INFO "user button long press.\n"); break; } } return 0; } //-----
在线程中我们不断判断state的值,如果一直按下,就判断按下了多久,当达到我们定义的长按时间的话,就会像上层发送一个长按的uevent事件,否则返回。

在按键抬起的时候也会产生中断,这样的话在else语句中会做判断,然后向user space发送一个uevent事件。

-------------------------------------------------

接下来我们看下在android中我们如何捕获

我们使用ueventObserver的方式去捕获uevent事件,详细的不多说了,可以参考我之前的博文有介绍uevent在android中的用法,直接贴代码,本人对java不是很熟悉,简单的代码就不来卖弄了,呵呵。

我们把代码加载ActivityManagerService.java中

//+++++add for our uevent by Jay private Handler UeventHandler=new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what==0) Toast.makeText(mContext,"short press!" ,Toast.LENGTH_SHORT).show(); if(msg.what==1) Toast.makeText(mContext,"long press!" ,Toast.LENGTH_SHORT).show(); } }; private UEventObserver mShortUEventObserver = new UEventObserver() { @Override public void onUEvent(UEventObserver.UEvent event) { UeventHandler.sendEmptyMessage(0); } }; private UEventObserver mLongUEventObserver = new UEventObserver() { @Override public void onUEvent(UEventObserver.UEvent event) { UeventHandler.sendEmptyMessage(1); } }; //------end add final void finishBooting() { //+++++add by Jay for user button mShortUEventObserver.startObserving("EVENT=shortpress"); mLongUEventObserver.startObserving("EVENT=longpress"); //------- IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); mContext.registerReceiver(new BroadcastReceiver() {
当bootFinish的时候我们就开始侦测这2个uevent时候被发生,然后用toast来显示。

最后重新编译,烧到我们的开发板中,当短按的时候会有信息吐出来,长按超过1.5s也会有信息吐出来。


分享工作经验,结束。

=========================================================

mail & MSN :zhangjie201412@live.com

=========================================================




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值