onKeyEvent和无障碍服务

9

我的用户将使用TalkBack启用或其他辅助服务。 我想在我们的应用程序中捕获onKeyEvent事件,但该事件被分派到已启用的辅助服务。 我创建了以下基本的辅助服务。

public class Accessibility_Service extends AccessibilityService {

    private String TAG = Accessibility_Service.class.getSimpleName();

    @Override
    public boolean onKeyEvent(KeyEvent event) {
        int action = event.getAction();
        int keyCode = event.getKeyCode();
        if (action == KeyEvent.ACTION_UP) {
            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
                Log.d("Hello", "KeyUp");
            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                Log.d("Hello", "KeyDown");
            }
            return true;
        } else {
            return super.onKeyEvent(event);
        }
    }

    /**
     * Passes information to AccessibilityServiceInfo.
     */
    @Override
    public void onServiceConnected() {
        Log.v(TAG, "on Service Connected");
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.packageNames = new String[] { "com.camacc" };
        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        info.notificationTimeout = 100;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
        setServiceInfo(info);

    }// end onServiceConnected

    /**
     * Called on an interrupt.
     */
    @Override
    public void onInterrupt() {
        Log.v(TAG, "***** onInterrupt");

    }// end onInterrupt

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // TODO Auto-generated method stub

    }
}// end Accessibility_Service class

当我查看logcat时,没有响应。在TalkBack或其他辅助功能服务之前,是否有可能消耗音量减小和增大事件?

谢谢。

编辑:

添加了以下标志,仍然没有运气:

info.flags = AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;
5个回答

10

如果您需要更多信息,请查看以下链接:https://developer.android.com/guide/topics/ui/accessibility/services.html。在xml资源中尝试像这样配置辅助功能服务。

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeContextClicked|typeViewClicked"
android:packageNames="com.example.andres.eventcapture"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="50"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:canRequestFilterKeyEvents="true"
/>

它运行得很好!


谢谢,我已经成功获取了音量增加和音量减少事件。但是它无法检测到软键盘按键的按下。 - ashishdhiman2007
@ashishdhiman2007,你有软键盘的解决方案吗?比如返回按键。 - Hamza
@Hamza 我没有。 - ashishdhiman2007

4

虽然这是一个旧问题,但也许我的答案能帮到某个人。

是的,另一个辅助功能服务可能会消耗KeyEvent。

请查看FLAG_REQUEST_FILTER_KEY_EVENTS文档,其中写道: 设置此标志并不能保证此服务将过滤关键事件,因为任何时候只有一个服务可以这样做。这避免了由于启用了不同的按键过滤服务而导致的用户混淆行为变化。如果已经启用了另一个按键过滤服务,则此服务将无法接收按键事件。

因此,另一个辅助功能服务可能会消耗KeyEvents。


2
尝试移除info.packageNames或将其设置为null。根据文档,您只会收到由这些应用程序包生成的事件。

0
如果您想从服务中专门获取音量键按下事件,那么这个方法可以实现。但是请注意,它会覆盖音量键的默认行为,因此请避免在全局范围内使用它。
public class VolumeKeyController {

    private MediaSessionCompat mMediaSession;
    private final Context mContext;

    public VolumeKeyController(Context context) {
        mContext = context;
    }

    private void createMediaSession() {
        mMediaSession = new MediaSessionCompat(mContext, KeyUtil.log);

        mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mMediaSession.setPlaybackState(new Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0)
                .build());
        mMediaSession.setPlaybackToRemote(getVolumeProvider());
        mMediaSession.setActive(true);
    }

    private VolumeProviderCompat getVolumeProvider() {
        final AudioManager audio = mContext.getSystemService(Context.AUDIO_SERVICE);

        int STREAM_TYPE = AudioManager.STREAM_MUSIC;
        int currentVolume = audio.getStreamVolume(STREAM_TYPE);
        int maxVolume = audio.getStreamMaxVolume(STREAM_TYPE);
        final int VOLUME_UP = 1;
        final int VOLUME_DOWN = -1;

        return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
            @Override
            public void onAdjustVolume(int direction) {
                // Up = 1, Down = -1, Release = 0
                // Replace with your action, if you don't want to adjust system volume
                if (direction == VOLUME_UP) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                else if (direction == VOLUME_DOWN) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                setCurrentVolume(audio.getStreamVolume(STREAM_TYPE));
            }
        };
    }

    // Call when control needed, add a call to constructor if needed immediately
    public void setActive(boolean active) {
        if (mMediaSession != null) {
            mMediaSession.setActive(active);
            return;
        }
        createMediaSession();
    }

    // Call from Service's onDestroy method
    public void destroy() {
        if (mMediaSession != null) {
            mMediaSession.release();
        }
    }
}

它的作用是监听音量按钮,并相应地更改音量吗? - android developer
它不必改变音量。您可以使其在单击时执行任何操作。 - Gibolt
1
正确的,当前的代码更改音量。它跳过了对媒体/铃声的设备检查,总是更改媒体音量。 - Gibolt
我明白了。谢谢! - android developer

-3

我认为当你扩展AccessibilityService时,必须实现“onAccessibilityEvent()”方法;像这样的东西:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    final int eventType = event.getEventType();
    switch(eventType) {
        case AccessibilityEvent.TYPE_VIEW_CLICKED:
            do somthing
            break;
        case AccessibilityEvent.TYPE_VIEW_FOCUSED:
            do somthing
            break;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接