Capturing events on volume button

0

I'm trying to record and capture the events on the Android volume buttons in order to start and stop a service.

Researching found several solutions, using BroadcastReceiver, but it seems that none is working for me.

What I did so far was basically this (which is not 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 AndroidManifest.xml :

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

And I will log into 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 looks like something is missing, or something is wrong, because the onReceive MediaButtonReceiver method is not being called by pressing the device volume buttons.

I'm running on Android 5.0.

  

I've seen this similar question that is unsolved.

     
  • I accept solutions that require root access (rooted devices).
  •   
    
asked by anonymous 02.07.2015 / 19:51

1 answer

3

Instead of action android:name="android.intent.action.MEDIA_BUTTON" use action android:name="android.media.VOLUME_CHANGED_ACTION" in 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 response in SOen.

You'll need to change the receiver to handle past Extras :

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, volume and prevVolume will always be equal, not allowing you to know which button was pressed.

One thing I checked, which I could not find an explanation for, was that the receiver is called twice each time you press a button. The first time the values are different, in the second they are the same.
As the code is, the second call is ignored.

    
02.07.2015 / 23:49