OnKeyEvent & Accessibility Service

My users will use TalkBack or some other available services. I would like to capture onKeyEvent events in our application, but the event is dispatched to allowed access services. I 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 logcat, I get no response. Can I use volume down events and events before TalkBack or other such availability services?

Thanks.

EDIT:

ADDED NEXT FLAG, STILL NOT LUCK:

 info.flags = AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS; 
+6
source share
5 answers

Try setting up the accessibility service like this in the xml resource, if you need more information, see: 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 out well!

+5
source

Old question, but maybe this answer will help someone.

Yes, it is possible that another accessibility service is using KeyEvent.

Please see the FLAG_REQUEST_FILTER_KEY_EVENTS documentation: Setting this flag does not guarantee that this service will filter key events, since only one service can do this at any given time. This avoids user confusion due to behavior changes in the case of activation of various key filtering services. If another key filtering service is enabled, it will not accept key events.

So another accessibility service might use KeyEvents.

+4
source

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

+1
source

If you specifically want to press a volume key from the Service, this will work. It will undo the volume key, so do not use 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 onDestroy method public void destroy() { if (mMediaSession != null) { mMediaSession.release(); } } } 
0
source

I think you should implement the onAccessibilityEvent () method when extending the AccessibilityService, for example:

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

Source: https://habr.com/ru/post/974820/


All Articles