onKeyDown en un servicio? (Global Hot Keys)

Lo que básicamente bash lograr son teclas de acceso rápido globales personalizadas o, en otras palabras, “las cosas sucederán cuando presione ciertos botones sin importar qué progtwig esté actualmente en la parte superior”.
Supongo que se necesita un servicio.

Tengo una prueba rápida y sucia que simplemente me dice qué se ha presionado que funcionará si es la ventana activa.

public boolean onKeyDown(int keyCode, KeyEvent event) { char pop; pop = (char)event.getUnicodeChar(); Toast.makeText(this, Character.toString(pop) , Toast.LENGTH_SHORT).show(); return super.onKeyDown(keyCode, event); } 

Pero obviamente, si cambio de ventana o entro en un cuadro de texto, no funciona. Si lo incluyo directamente en un servicio (o un servicio de imputmethod) y lo ejecuto, no ocurre nada. (¿Algunos permisos necesarios tal vez?) ¿Alguna sugerencia de dónde me estoy equivocando? ¿O una mejor forma de capturar qué botón se presiona?

¡Gracias!

No puedes hacer esto 🙂

Esto requiere Lollipop (v5.0 / API 21) o superior

Mi objective era ajustar el volumen del sistema desde un servicio, así que esto solo escuchará al mecedor. Sin embargo, cualquier acción puede tomarse en la prensa.

Anulará la acción de la tecla de volumen, por lo que su uso global puede no ser deseable.

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