公司项目有个需求,就是拦截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.youkuaiyun.com/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键,而这里却收到了呢?下一篇我们将从源码进行分析。
本文介绍了如何使用Android的AccessibilityService来拦截VR眼镜上的返回按键。通过代码示例展示了如何设置AccessibilityService以拦截按键事件,并讨论了在实际应用中遇到的问题:虽然能捕获常规按键,但无法捕获VR眼镜的返回键。作者计划在后续文章中通过源码分析解决这一问题。
5986

被折叠的 条评论
为什么被折叠?



