Davim
Davim

Reputation: 221

How can I detect if the volume is set to mute?

When I am developing an Android application, how can I detect if volume is set to mute?

How can my application get notified if the volume changes to mute or gets unmuted?

Upvotes: 10

Views: 9980

Answers (2)

argenkiwi
argenkiwi

Reputation: 2427

You can do the following to observe if a specific stream (music in this case) is muted:

val Context.musicMutedFlow
    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.getBooleanExtra(
                            "android.media.EXTRA_STREAM_VOLUME_MUTED",
                            false
                        )
                    )
                }
            }
        }

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

Then, from a ContextWrapper (e.g., Activity, Service), you can collect the flow as follows:

lifecycleScope.launch {
    musicMutedFlow.collect { Log.d("Some tag", "Music stream muted: $it") }
}

If, like in the accepted answer, you want to specifically know if the Ring and notification volume is muted, you may instead want to do the following:

val Context.ringAndNotificationMutedFlow
    get() = callbackFlow {
        val receiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val ringerMode = intent.getIntExtra(
                    AudioManager.EXTRA_RINGER_MODE,
                    AudioManager.RINGER_MODE_NORMAL
                )

                trySend(ringerMode != AudioManager.RINGER_MODE_NORMAL)
            }
        }

        registerReceiver(receiver, IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION))
        awaitClose { unregisterReceiver(receiver) }
    }

The advantage is that the AudioManager constants used are public and Google would have to mark them for deprecation if they were to change them or remove them.

Upvotes: 0

Ajay S
Ajay S

Reputation: 48602

You can use AudioManager to check volume is mute or not mute.

AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
switch( audio.getRingerMode() ){
case AudioManager.RINGER_MODE_NORMAL:
   break;
case AudioManager.RINGER_MODE_SILENT:
   break;
case AudioManager.RINGER_MODE_VIBRATE:
   break;
}

and for Volume change there is BroadcastReceiver for that.

public class VolumeKeyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
       //Implement Logic
    }
}

Register the BroadcastReceiver

VolumeKeyReceiver keyReceiver = new VolumeKeyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.media.VOLUME_CHANGED_ACTION");
registerReceiver(keyReceiver, intentFilter);

Upvotes: 34

Related Questions