公司项目有个需求,就是拦截VR眼镜上的返回按键,既然要拦截按键,私以为有以下两种方式:
1. accessibilityService,Android辅助工具可以实现拦截按键、焦点变化、触摸时间、姿势等。
2. 使用adb shell命令,getevent方式分析获取到的按键的值。
第一种方法最简单,代码如下:
AccessibilityService.java
public class AccessBackKeyService extends AccessibilityService { PRivate static final String TAG = "AccessBackKeyService"; @Override protected boolean onKeyEvent(KeyEvent event) { Log.i(TAG, "onKeyEvent"); if(event.getAction() == KeyEvent.ACTION_DOWN){ return super.onKeyEvent(event); } Log.i(TAG, "onKeyEvent ACTION_DOWN"); int key = event.getKeyCode(); switch(key){ case KeyEvent.KEYCODE_VOLUME_DOWN: break; case KeyEvent.KEYCODE_VOLUME_UP: break; case KeyEvent.KEYCODE_BACK: Log.i(TAG, "KEYCODE_BACK"); break; case KeyEvent.KEYCODE_ESCAPE: break; } return super.onKeyEvent(event); } @Override public void onInterrupt() { } @Override public void onCreate() { super.onCreate(); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); String eventTypeName = ""; switch (eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: eventTypeName = "TYPE_VIEW_CLICKED"; break; case AccessibilityEvent.TYPE_VIEW_FOCUSED: eventTypeName = "TYPE_VIEW_FOCUSED"; break; case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED: eventTypeName = "TYPE_VIEW_LONG_CLICKED"; break; case AccessibilityEvent.TYPE_VIEW_SELECTED: eventTypeName = "TYPE_VIEW_SELECTED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED: eventTypeName = "TYPE_VIEW_TEXT_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: eventTypeName = "TYPE_WINDOW_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: eventTypeName = "TYPE_NOTIFICATION_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: eventTypeName = "TYPE_TOUCH_EXPLORATION_GESTURE_END"; break; case AccessibilityEvent.TYPE_ANNOUNCEMENT: eventTypeName = "TYPE_ANNOUNCEMENT"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: eventTypeName = "TYPE_TOUCH_EXPLORATION_GESTURE_START"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: eventTypeName = "TYPE_VIEW_HOVER_ENTER"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: eventTypeName = "TYPE_VIEW_HOVER_EXIT"; break; case AccessibilityEvent.TYPE_VIEW_SCROLLED: eventTypeName = "TYPE_VIEW_SCROLLED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: eventTypeName = "TYPE_VIEW_TEXT_SELECTION_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: eventTypeName = "TYPE_WINDOW_CONTENT_CHANGED"; break; } Log.i(TAG, "eventType:" + eventType); Log.i(TAG, "eventTypeName:" + eventTypeName); } @Override protected boolean onGesture(int gestureId) { return super.onGesture(gestureId); }}AndroidMenifest.xml <service android:name="com.test.accessbackkey.AccessBackKeyService" android:enabled="true" android:exported="true" android:label="@string/app_name" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" > <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/access_backkey_service" /> </service>access_backkey_service.xml<?xml version="1.0" encoding="utf-8"?><accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagRequestFilterKeyEvents" android:canRetrieveWindowContent="true" android:canRequestFilterKeyEvents="true" android:description="@string/access_description" android:notificationTimeout="100"/>完成了以上的工作后,在MainActivity.java去启动辅助功能设置,手动打开开关之后就可以开始拦截按键了。 private void startService() { Intent intent = new Intent(); intent.setAction(Settings.ACTION_ACCESSIBILITY_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }http://blog.csdn.net/dd864140130/article/details/51794318 AccessibilityService其他的知识可以参考这篇文章。经测试,虚拟按键BACK键、HOME键、最近任务键和音量键全部拦截到,然而我们另一项任务却没有完成,始终拦截不到VR眼镜的返回键,甚至keyEvent都没有,这是为什么呢?莫非它是一个MotionEvent,让我们来验证一下。在MainActivity.java中复写onKeyDown方法
@Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); Log.i("key", "event source:"+event.getSource()); return super.onTouchEvent(event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK){ Log.i("key", " main KEYCODE_BACK source:"+event.getSource()); } return super.onKeyDown(keyCode, event); }}我们按下VR眼镜的BACK键之后onTouchEvent并没有反应,反倒是onKeyDown收到了,证明了VR眼镜的BACK键是Key事件,而不是MotionEvent。为什么AccessibilityService的onKeyEvent没有收到BACK键,而这里却收到了呢?下一篇我们将从源码进行分析。
新闻热点
疑难解答