onKeyEvent & Accessibility Service

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-21 04:43:12

问题


My users will be using TalkBack enabled or some other Accessible Service. I would like to capture the onKeyEvent events in our App but the event is dispatched to the enabled Accessibility Services. I have created the following basic Accessibility Service.

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

When I check the logcat I am getting no response. Is it possible to consume the Volume Down and Up Events prior to TalkBack or other such Accessibility Services?

Thank you.

EDIT:

ADDED THE FOLLOWING FLAG STILL WITH NO LUCK:

info.flags = AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;

回答1:


Try to configure the Accessibility Service like this in the xml resource, if you need more information look this: https://developer.android.com/guide/topics/ui/accessibility/services.html

<?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"
/>

It worked good!




回答2:


Old question, but maybe this answer will help someone.

Yes, it's possible that another accessibility service consumes KeyEvent.

Please have a look at FLAG_REQUEST_FILTER_KEY_EVENTS documentation, there is: Setting this flag does not guarantee that this service will filter key events since only one service can do so at any given time. This avoids user confusion due to behavior change in case different key filtering services are enabled. If there is already another key filtering service enabled, this one will not receive key events.

So another accessibility service can consume KeyEvents.




回答3:


Try removing the info.packageNames or setting it to null. According to the documentation here you will only receive events generated by those application packages.




回答4:


If you specifically want volume key presses from a Service, this will work. It will override volume key action, so avoid using it globally.

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();
        }
    }
}



回答5:


I think you must to implement" onAccessibilityEvent()" method when you extend AccessibilityService;thing like:

@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;
    }


来源:https://stackoverflow.com/questions/25661861/onkeyevent-accessibility-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!