我看了下4.2的SDK,好像已经不是下面说的那样了,找不到对应的函数。不过原理应该差不多,我总结下,以后再详细跟踪代码:
1.在framwork的service中,有jni包和java包。jni包主要是接受kernel层发过来的按键事件,而java包主要是对jni的函数进行打包,提供回调函数。这样java层就收到按键事件了。java层会在某个文件通过while循环读取input事件,然后会根据按键的种类,分发事件。最后,你就能通过keyevent.KEYCODE_xxx或者其它方式获得事件了。
2.事件分发的时候,还可能经过事件过滤器/view树,最后才达到activity。
下文转自:http://blog.sina.com.cn/s/blog_896b1e670100xfuf.html
公司最近做一个按键触感就对这块研究了一番,以下是个人心得。
1.开始肯定先说的是驱动这块,硬件是软件服务的,在Android这块C和java交互,有两种方式:
- static jboolean
- android_server_KeyInputQueue_readEvent(JNIEnv* env,jobject clazz,
-
jobject event) - {
-
gLock.lock(); -
sp hub = gHub; -
if(hub == NULL) { -
hub = new EventHub; -
gHub = hub; -
} -
gLock.unlock(); -
-
int32_t deviceId; -
int32_t type; -
int32_t scancode, keycode; -
uint32_t flags; -
int32_t value; -
nsecs_t when; -
boolres = hub->getEvent(&deviceId,&type, &scancode,&keycode, -
&flags, &value,&when); -
-
env->SetIntField(event, gInputOffsets.mDeviceId,(jint)deviceId); -
env->SetIntField(event, gInputOffsets.mType,(jint)type); -
env->SetIntField(event, gInputOffsets.mScancode,(jint)scancode); -
env->SetIntField(event, gInputOffsets.mKeycode,(jint)keycode); -
env->SetIntField(event, gInputOffsets.mFlags,(jint)flags); -
env->SetIntField(event, gInputOffsets.mValue,value); -
env->SetLongField(event, gInputOffsets.mWhen, -
(jlong)(nanoseconds_to_milliseconds(when))); -
-
returnres; - }
-->windowManagerService.process{
4.KeyEvent事件的传递主要可以划分为三步:过滤器、View树、Activity.
过滤器部分对应的是(frameworks/base/policy/base/phone/com/Android/internal/policy/impl/PhoneWindowManager.java)PhoneWindowManager.java中的interceptKeyTq和interceptKeyTi这两个方法。它们的代码可以在中看到。
这两个过滤器最大的不同就是interceptKeyTq用于RawEvent,而interceptKeyTi用于KeyEvent。
在一个没有实体键盘的机器上,Power键会被interceptKeyTq这个过滤器吃掉用来调用关机对话框或者使机器休眠。而Home键会被interceptKeyTi这个过滤器吃掉,用来把当前Activity切换到后台并把桌面程序切换到前台。所以,应用程序在View和Activity的onKeyDown/Up中是监听不到这两个按键的。除了这两个键以外的按键,都有机会继续前进。接下来,KeyEvent会先经过interceptKeyTi过滤器,如果这个过滤器不吃掉的话,就会继续前进,进入View树,如果没有被哪个View吃掉的话,最后进入到Activity的onKeyDown/Up方法中。
当一个KeyEvent经过上面的过程还没有被吃掉的话,系统就会利用它做一些定制的功能。比如音量键被系统用来调整声音,多媒体按键用来控制媒体播放,搜索键用来快速打开搜索功能,返回键用来退出当前Activity等。