2

I want to handle long press (about 10sec) of volume button (volume up or volume down doesn't matter).

For this reason I used own implementation of MediaKeyListener

private class LoongPressKeyListener extends MediaKeyListener {

    public boolean mediaAction(int action, int source,
            Object paramObject) {

        System.out.println("::: action=" + action + ";source=" + source + ";object=" + paramObject);
    }

    public boolean keyDown(int keycode, int status) {
        switch (Keypad.key(keycode)) {
            case Keypad.KEY_VOLUME_UP:
            case Keypad.KEY_VOLUME_DOWN:
                System.out.println("volume keyDown");
                return true;
            default:
                return super.keyDown(keycode, status);
        }
    }

    public boolean keyUp(int keycode, int status) {
        switch (Keypad.key(keycode)) {
            case Keypad.KEY_VOLUME_UP:
            case Keypad.KEY_VOLUME_DOWN:
                System.out.println("volume keyUp");
                return true;
            default:
                return super.keyUp(keycode, status);
        }
    }
}

But for some reason keyUp and keyDown method have been called only when application in foreground. mediaAction has been called only when app in background.

Can someone explain is this a correct behavior? And is it possible to handle long volume button press from background?

CAMOBAP
  • 5,523
  • 8
  • 58
  • 93

1 Answers1

2

What you're seeing is correct behaviour, but you can still get volume up/down events while in the background. From the BlackBerry documentation for MediaKeyListener (bold is mine):

Applications would create a concrete subclass of this class that implements the methods defined in MediaActionHandler. Then, an instance of that class can be registered as a KeyListener either by using Application.addKeyListener() or Screen.addKeyListener(), which will handle media key presses while the application is in the foreground. Then, the same instance of MediaKeyListener can be registered using Application.addMediaActionHandler() in order to respond to media key presses while in the background, as well as media actions from other sources.

So, you need to make sure to call Application#addMediaActionHandler(), to add your LoongPressKeyListener instance.

Also, from the MediaActionHandler class API docs:

Media Actions from Background Key Presses

If a MediaActionHandler is registered via Application.addMediaActionHandler() then it will be notified of media key presses that occur while the application is in the background. If the application that happens to be in the foreground consumes a media key press then it will not be posted as a media action to media action handlers. Invocations of mediaAction() resulting from background key presses will have source==MediaActionHandler.SOURCE_BACKGROUND_KEY and context==null.

Here is a sample for detecting volume up, volume down, and volume long presses while in the background:

public class MediaKeyHandler extends MediaKeyListener {

    public MediaKeyHandler() {
        // use this to register for events while in the background:
        UiApplication.getUiApplication().addMediaActionHandler(this);
        // use this to register for events while in the foreground:
        //UiApplication.getUiApplication().addKeyListener(this);
    }

    public boolean mediaAction(int action, int source, Object context) {
        System.out.println("mediaAction(" + action + "," + source + ",context)");

        if (source == MediaActionHandler.SOURCE_BACKGROUND_KEY) {
            switch (action) {
            case MediaActionHandler.MEDIA_ACTION_VOLUME_DOWN:
                // handle volume down key pressed
                break;
            case MediaActionHandler.MEDIA_ACTION_VOLUME_UP:
                // handle volume up key pressed
                break;
            case MediaActionHandler.MEDIA_ACTION_NEXT_TRACK:
                // handle volume up key long-pressed
                break;
            case MediaActionHandler.MEDIA_ACTION_PREV_TRACK:
                // handle volume down key long-pressed
                break;
            default:
                break;
            }
            return true;  // keypress consumed
        } else {
            // keypresses while app is in foreground come here

            return false;  // keypress not consumed
        }
    }

Note: I know of no way to detect a 10-second volume key press while in the background. In the foreground, both KeyListener#keyRepeat() and MediaKeyListener#mediaAction() get called repeatedly, as you hold the key, but not in the background. The code I show above works with a long-press of about a second (not 10 seconds).

Nate
  • 31,017
  • 13
  • 83
  • 207
  • So, as I understood from your answer, I haven't chance to handle releasing volume button (and haven't chance to handle long press). correct? – CAMOBAP Jul 07 '13 at 00:00
  • 1
    @CAMOBAP, unfortunately, that's correct. When in the background, you don't receive a key-up event, so you can't tell when the volume key press ends. However, the VOLUME_DOWN event is different from the PREV_TRACK event, so you can handle long presses by listening for PREV_TRACK. But, that *long* press is only about one second, not 10. See the update to my answer for more. – Nate Jul 07 '13 at 23:45
  • I have no words to express my gratitude to you!) Your answers is always detailed and supported by reference to documentation. thank you ever so much!!! – CAMOBAP Jul 08 '13 at 06:07
  • @CAMOBAP, you're very kind! You're welcome, and best of luck with your apps! – Nate Jul 08 '13 at 06:41