简体   繁体   English

onKeyEvent和辅助功能服务

[英]onKeyEvent & Accessibility Service

My users will be using TalkBack enabled or some other Accessible Service. 我的用户将使用TalkBack或其他一些Accessible Service。 I would like to capture the onKeyEvent events in our App but the event is dispatched to the enabled Accessibility Services. 我想在我们的应用程序中捕获onKeyEvent事件,但事件将被分派到启用的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. 当我检查logcat时,我没有得到任何回复。 Is it possible to consume the Volume Down and Up Events prior to TalkBack or other such Accessibility Services? 是否可以在TalkBack或其他此类辅助功能服务之前使用降低音量和向上事件?

Thank you. 谢谢。

EDIT: 编辑:

ADDED THE FOLLOWING FLAG STILL WITH NO LUCK: 添加以下标志仍然没有运气:

info.flags = AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;

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资源中配置这样的辅助功能服务,如果您需要更多信息,请查看: 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! 它工作得很好!

Old question, but maybe this answer will help someone. 老问题,但也许这个答案会帮助别人。

Yes, it's possible that another accessibility service consumes KeyEvent. 是的,另一个辅助功能服务可能会消耗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. 请查看FLAG_REQUEST_FILTER_KEY_EVENTS文档,其中包括: 设置此标志并不保证此服务将过滤关键事件,因为在任何给定时间只有一个服务可以这样做。 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. 因此,另一个辅助功能服务可以使用KeyEvents。

Try removing the info.packageNames or setting it to null. 尝试删除info.packageNames或将其设置为null。 According to the documentation here you will only receive events generated by those application packages. 根据此处的文档您只会收到这些应用程序包生成的事件。

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

I think you must to implement" onAccessibilityEvent()" method when you extend AccessibilityService;thing like: 我认为你必须在扩展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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM