2014-09-04 20 views
5

I miei utenti utilizzeranno TalkBack abilitato o altri servizi accessibili. Vorrei acquisire gli eventi onKeyEvent nella nostra app ma l'evento viene inviato ai servizi di accessibilità abilitati. Ho creato il seguente servizio di accessibilità di base.onKeyEvent & 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 

Quando controllo il logcat sto ottenendo alcuna risposta. È possibile consumare gli eventi Volume Down e Up prima di TalkBack o di altri servizi di accessibilità di questo tipo?

Grazie.

EDIT:

aggiunto il seguente bandiera ancora senza fortuna:

info.flags = AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS; 

risposta

-2

penso che è necessario per attuare "onAccessibilityEvent()" metodo quando si estende AccessibilityService; cosa del genere:

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

Vecchia domanda, ma forse questa risposta aiuterà qualcuno.

Sì, è possibile che un altro servizio di accessibilità utilizzi KeyEvent.

Si prega di dare un'occhiata al FLAG_REQUEST_FILTER_KEY_EVENTS documentazione, c'è: L'impostazione di questa bandiera non garantisce che questo servizio sarà filtrare gli eventi chiave dal momento che solo un servizio può farlo in qualsiasi momento. Ciò evita la confusione dell'utente a causa del cambiamento di comportamento nel caso in cui siano abilitati diversi servizi di filtraggio delle chiavi. Se esiste già un altro servizio di filtraggio chiavi abilitato, questo non riceverà eventi chiave.

Così un altro servizio di accessibilità può consumare KeyEvents.

5

tenta di configurare il servizio di accessibilità come questo nella risorsa xml, se avete bisogno di ulteriori informazioni guardare questo: 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" 
/> 

ha funzionato bene!

+0

Grazie, sono stato in grado di ottenere eventi volume su e volume giù. Non rileva le pressioni dei tasti della tastiera virtuale / – ashishdhiman2007

1

Provare a rimuovere info.packageNames o impostarlo su null. Secondo la documentazione here riceverai solo eventi generati da quei pacchetti di applicazioni.

0

Se si desidera che il tasto del volume preme da un servizio, funzionerà. Sostituirà l'azione della chiave del volume, quindi evita di utilizzarla a livello globale.

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