【问题标题】:onKeyEvent & Accessibility ServiceonKeyEvent 和无障碍服务
【发布时间】:2014-09-04 09:28:46
【问题描述】:

我的用户将使用启用 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;

【问题讨论】:

    标签: android accessibility keyevent android-a11y


    【解决方案1】:

    尝试在 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"
    />
    

    效果很好!

    【讨论】:

    • 谢谢,我能够获得音量增大和音量减小事件。不检测软键盘按键/
    • @ashishdhiman2007 你有软键的解决方案吗?像背压
    • @Hamza 不,我没有
    【解决方案2】:

    老问题,但也许这个答案会对某人有所帮助。

    是的,有可能另一个无障碍服务使用了 KeyEvent。

    请查看FLAG_REQUEST_FILTER_KEY_EVENTS 文档,有: 设置此标志并不能保证此服务将过滤关键事件,因为在任何给定时间只有一个服务可以这样做。这避免了在启用不同密钥过滤服务的情况下由于行为变化而引起的用户混淆。如果已经启用了另一个密钥过滤服务,则此服务将不会接收到密钥事件。

    所以另一个无障碍服务可以使用 KeyEvents。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        如果您特别希望从服务中按下音量键,这将起作用。它将覆盖音量键操作,因此请避免在全局范围内使用它。

        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】:

        我认为您在扩展 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;
            }
        

        【讨论】:

          猜你喜欢
          • 2021-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-19
          • 1970-01-01
          相关资源
          最近更新 更多