Volume change listener?
Asked Answered
S

2

14

Is there any way to listen for volume changes with an Android service and react to that?

Btw: How does the Google music app allow the user to control the media volume even when the music is playing in the background?

Scrubland answered 20/8, 2011 at 7:32 Comment(0)
S
12

Check out registerMediaButtonEventReceiver(ComponentName broadcastReceiver);

Define a BroadcastReceiver that handles ACTION_MEDIA_BUTTON. The recieved intent includes a single extra field, EXTRA_KEY_EVENT, containing the key event that caused the broadcast. You can use this key event to get which key was pressed.


EDIT:
This is just a sample code. syntax errors may be there.

// in onCreate of activity
registerMediaButtonEventReceiver(mediaReceiver ); 

// later somewhere in activity.
MediaButton_Receiver mediaReceiver = new MediaButton_Receiver();

class MediaButton_Receiver implements BroadcastReceiver {
     void onReceive(Intent intent) {

          KeyEvent ke = (KeyEvent)intent.getExtra(Intent.EXTRA_KEY_EVENT); 
          if (ke .getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {

          }
          // Similarly other key codes .......
     } 
}

Unregister the receiver in onPause() or onStop()

Shout answered 20/8, 2011 at 8:34 Comment(5)
Can you give an example of that please?Scrubland
I have added the sample code. But there are syntax errors in it. Also should check action key down or key up. For start this is good, add it later.Shout
Also do not forget to unregister the receiver otherwise other applications using the media button event may get affected.Shout
@userSeven7s I don't get any intents when changing the volume using the volume rocker but I do get for the button on my headset. Should it work for the volume rocker as well?Tyrr
// should be put in onResume I think registerMediaButtonEventReceiver(mediaReceiver );Panel
N
0

For those using kotlin flows, you can use the following approach to listen to volume changes for a specific stream:

val Context.musicVolumeFlow
    get() = callbackFlow {
        val receiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                when (intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_TYPE", 0)) {
                    AudioManager.STREAM_MUSIC -> trySend(
                        intent.getIntExtra(
                            "android.media.EXTRA_VOLUME_STREAM_VALUE",
                            0
                        )
                    )
                }
            }
        }

        registerReceiver(receiver, IntentFilter("android.media.VOLUME_CHANGED_ACTION"))
        awaitClose { unregisterReceiver(receiver) }
    }

You can then collect it as follows from a Service (LifecycleService in this case but you can use your own coroutine scope):

lifecycleScope.launch {
    musicVolumeFlow.collect { Log.d("AppLog", "stream volume: $it") }
}

Notice this example is only interested in AudioManager.STREAM_MUSIC. Make sure to target the audio streams relevant to your application.

Nidia answered 14/4 at 22:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.