13
votes

Is there any way to listen to the event of volume change on Android, without just taking over the volume buttons?

The only thing I've found that works is here, but it works only after the volume control has disappeared.

Not all devices have volume buttons, and I need to capture the volume changes as soon as they occur, and not after the volume dialog is gone.

4
Use ContentObserver and get the volumes from audiomanager. I recently used it and it works great.Check this Solution in stackoverflow - user2503849
it´s an older post, but it´s paltry that there isn´t a broadcat implemented until now in Android....5 years later, still no broadcast... - Opiatefuchs
@Opiatefuchs Maybe create a request for it, here: issuetracker.google.com/issues . I will star it :) - android developer
you are right. Done...issuetracker.google.com/issues/62158875 But it´s my first created suggestion, I have no code sample for something like a broadcast. I hope they will accept it... - Opiatefuchs

4 Answers

24
votes

Better, you can register a ContentObserver as follows:

  getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, new ContentObserver(){...} );

Your ContentObserver might look like this:

public class SettingsContentObserver extends ContentObserver {
    private AudioManager audioManager;

    public SettingsContentObserver(Context context, Handler handler) {
        super(handler);
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return false;
    }

    @Override
    public void onChange(boolean selfChange) {
        int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

        Log.d(TAG, "Volume now " + currentVolume);
    }
}

When done:

getApplicationContext().getContentResolver().unregisterContentObserver(mContentObserver);

One caution, though - sometimes the notifications seem to be delayed if there are lots of button presses quickly.

2
votes

Use broadcast receiver VOLUME_CHANGED_ACTION then use AudioManager to obtain current volume.

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

ok , for now , what i do is to listen to the volume buttons using onKeyDown (and check for KEYCODE_VOLUME_DOWN,KEYCODE_VOLUME_MUTE,KEYCODE_VOLUME_UP ) , and using a handler i've posted a new runnable that checks the volume level .

also , since some devices have a volume dialog , i've added a listener to when it is being disappeared , according to this link.

0
votes

You can use : registerMediaButtonEventReceiver (ComponentName eventReceiver) which registers a component to be the sole receiver of MEDIA_BUTTON intents.

//  in your activity.
MediaButtonReceiver receiver = new MediaButtonReceiver();

// in onCreate put
registerMediaButtonEventReceiver(receiver); 

class MediaButtonReceiver implements BroadcastReceiver {
     void onReceive(Intent intent) {
          KeyEvent ke = (KeyEvent)intent.getExtra(Intent.EXTRA_KEY_EVENT); 
          if (ke .getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
            //action when volume goes down
          }
           if (ke .getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) {
              //action when volume goes up
          }
     } 
}

   //In both onStop and onPause put :
   unregisterMediaButtonEventReceiver(receiver);

what we are doing here is defining a BroadcastReceiver that deals with ACTION_MEDIA_BUTTON. and use EXTRA_KEY_EVENT which is containing the key event that caused the broadcast to get what was pressed and act upon that.