首页 > 系统 > Android > 正文

Android AccessibilityService拦截事件及VR眼镜返回按键捕捉

2019-11-07 23:05:45
字体:
来源:转载
供稿:网友

公司项目有个需求,就是拦截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键,而这里却收到了呢?下一篇我们将从源码进行分析。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表