onKeyDown in a service? (Global Hot Keys)
Asked Answered
V

2

20

What I'm basically trying to achieve is custom global hot keys or in other words 'things will happen when I push certain buttons no matter which program is currently on top'.
I assume a service is needed.

I have a quick and dirty test that just tells me what has been pressed that will work if it is the active window.

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

But obviously if I change window or go into a text box it doesn't work. If I stick it directly into a service (or an imputmethodservice) and launch said service nothing happens. (Some permissions required maybe?) Any suggestions where I'm going wrong? Or a better way of capturing which button is pressed?

Thanks!

Viradis answered 11/8, 2010 at 1:36 Comment(3)
hiii if u hv a workaround for this then plz let me knw.Bare
@Vincent Romain Guy works in Android team, he said this is impossible. And Fizz, could you please accept Romain's answer?Alcine
possible duplicate of Is it possible to create an Android Service that listens for hardware key presses?Hinckley
C
19

You cannot do this :)

Cohlier answered 11/8, 2010 at 3:34 Comment(6)
Even in an accessibility application? There's no way to react to button or softkey presses in a service?Heptagon
@Romain Guy - Sir, what if on pressing home i would like to set the screen on? How would samsung note II be doing it?Celebrate
@Romain Guy Why not sir?Brassica
@Romain How nougat on my nexus 6p listens to camera on double click?Meyerbeer
Mmmm. I feel that 'cannot' instead of can't and the slightly pass-ag smiley means "You can, but you ought not to.". Ha ha! :)Clo
@Heptagon I'm pretty sure it's possible via accessibility service. A lot of things are possible there...Bingen
E
7

This requires Lollipop (v5.0/API 21) or higher

My goal was to adjust system volume from a Service, so this will only listen for the rocker. Any action can be taken on press though.

It will override volume key action, so using it globally may not be desired.

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 = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

        int STREAM_TYPE = AudioManager.STREAM_MUSIC;
        int currentVolume = audio.getStreamVolume(STREAM_TYPE);
        int maxVolume = audio.getStreamMaxVolume(STREAM_TYPE);

        return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
            @Override
            public void onAdjustVolume(int direction) {
                // Volume Up = AudioManager.ADJUST_LOWER, Volume Down = AudioManager.ADJUST_LOWER, Release = AudioManager.ADJUST_SAME
                // Replace with your action, if you don't want to adjust system volume
                if (direction == AudioManager.ADJUST_RAISE) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                else if (direction == AudioManager.ADJUST_LOWER) {
                    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();
        }
    }
}
Edward answered 10/3, 2018 at 19:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.