Capture events on volume button

Asked

Viewed 598 times

0

I’m trying to record and capture events on the volume buttons of Android, so I can start and stop a service.

Researching I found several solutions using Broadcastreceiver, but it seems that none is working for my case.

What I’ve done so far is basically this (which isn’t working):

I created a Broadcastreceiver:

public class MediaButtonReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("MediaButtonReceiver", "onReceive");
        Toast.makeText(context, "Receiver!", Toast.LENGTH_LONG).show();
        if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
            KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            switch (event.getKeyCode()){
                case KeyEvent.KEYCODE_VOLUME_DOWN:
                    Toast.makeText(context, "Volume down!", Toast.LENGTH_LONG).show();
                    break;
                case KeyEvent.KEYCODE_VOLUME_UP:
                    Toast.makeText(context, "Volume up!", Toast.LENGTH_LONG).show();
                    break;
            }
        }
    }
}

I registered the receiver in the AndroidManifest.xml:

<receiver android:name=".MediaButtonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

And registered on onCreate of my Activity main:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    ComponentName rec = new ComponentName(this, MediaButtonReceiver.class);
    mAudioManager.registerMediaButtonEventReceiver(rec);
}

But it seems that something is missing, or something is incorrect, because the method onReceive of MediaButtonReceiver, is not being called by pressing the device’s volume buttons.

I’m running on Android 5.0.

I’ve seen it before that similar question that is unsolved.

  • I accept solutions that require root access (rooted devices).
  • Fernando, it would have to be from a Activity your app or need to know even without your app being in use?

  • @Wakim, it would have to be outside the App, it’s kind to start a service from anywhere, but the app has to be in the background.

1 answer

3

Instead of action android:name="android.intent.action.MEDIA_BUTTON" use action android:name="android.media.VOLUME_CHANGED_ACTION" in the Intent-filter of your receiver:

<receiver android:name=".MediaButtonReceiver">
    <intent-filter>
        <action android:name="android.media.VOLUME_CHANGED_ACTION" />
    </intent-filter>
</receiver>

Thank the author of this reply in the Soen.

You will need to change the receiver to treat the Extras bygone:

public class MediaButtonReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        int prevVolume;
        int volume;
        if ("android.media.VOLUME_CHANGED_ACTION".equals(intent.getAction())) {
            volume = (int)intent.getExtras().get("android.media.EXTRA_VOLUME_STREAM_VALUE");
            prevVolume = (int)intent.getExtras().get("android.media.EXTRA_PREV_VOLUME_STREAM_VALUE");
            if(volume < prevVolume) {
                Toast.makeText(context, "Volume down!", Toast.LENGTH_SHORT).show();

            }else if(volume > prevVolume){
                Toast.makeText(context, "Volume up!", Toast.LENGTH_SHORT).show();
            }

        }
    }
}

The problem you will encounter with this implementation is that when the volume reaches the minimum or maximum value, the volume and prevVolume will always be equal, not allowing knowing which of the buttons was pressed.

One thing I checked, for which I found no explanation, was that the receiver is called twice every time you press a button.
The first time the values are different, the second are equal.
The way the code looks the second call is ignored.

  • Yesterday at the end of the day, I had found something of the kind you talked about, using android.media.VOLUME_CHANGED_ACTION, When testing I found the same that you mentioned, that for some reason the method was called twice and it was not clear which of the buttons would have been pressed. I did an implementation of onReceive in the same idea as yours, ignoring the second call, but because the volume when reaching the extremes is not possible to identify the button, I am ignoring the button pressed and treating only as a single event. I will wait for some other possible solution, if there is not, I will use this.

  • Did you ever find some other solution?

  • 1

    No, I ended up abandoning this implementation!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.