12

AudioManger.setStreamMute is now deprecated with api 23 and it is preferred to use AudioManager.adjustStreamVolume with AudioManager.ADJUST_MUTE.

My problem is that this kind of flag is only supported with api 23 while my app is minimum api 16.

Is there an other way of muting the whole system?

If not, why would google deprecate this method?

Floern
  • 33,559
  • 24
  • 104
  • 119
dor00012
  • 362
  • 4
  • 17

2 Answers2

27

The way I would do it would be to use an if/else block to use the proper calls depending on the version of Android that the app is currently running under.

// Change the stream to your stream of choice. 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
   am.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0);
} else {
   am.setStreamMute(AudioManager.STREAM_MUSIC, true);
}
phxhawke
  • 2,581
  • 23
  • 17
  • but should'nt there be a better solution also for api less than 23? – dor00012 Oct 12 '15 at 17:06
  • That IS the solution. The else will execute if API is less than 23. About the only way I could make it any better would be to wrap it in a method. – phxhawke Oct 13 '15 at 13:55
  • By saying a better solution for api less than 23 i meant a method that is not deprecated - an alternative for 'setStreamMute'. I understand there probably isn't, thank you. – dor00012 Oct 14 '15 at 05:18
  • 2
    setStreamMute is not deprecated on previous versions. Only on API 23. It the application runs on a a phone that is using an API less than 23 it will work as expected. – phxhawke Oct 14 '15 at 16:55
  • I know what you mean, phxhawke. Soon code will be full of these `if Build.version >= Build.Android.X` – Someone Somewhere Dec 11 '15 at 15:17
  • 1
    `setStreamVolume` was not deprecated, so is there an advantage to adjust over set? Both support the same syntax. – Abandoned Cart May 03 '17 at 20:52
9

The accepted answer works fine in muting the system, but if you need to restore the state (e.g. when users pause / quit your app), please note that the semantics of the adjustStreamVolume and setStreamMute methods are different:

For setStreamMute, from the documentation:

The mute requests for a given stream are cumulative: the AudioManager can receive several mute requests from one or more clients and the stream will be unmuted only when the same number of unmute requests are received.

This does not seem to be the case for adjustStreamVolume with AudioManager.ADJUST_MUTE. In other words, if the status of the stream is already muted before you mute it with setStreamMute (stream, true), an immediate setStreamMute (stream, false) will leave it in muted state, while adjustStreamVolume with AudioManager.ADJUST_UNMUTE may unmute the stream.

Depending on the use case, to emulate the old semantics, one way is to check the mute state before muting, something like the following -

To mute:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!audioManager.isStreamMute(stream)) {
       savedStreamMuted = true;
       audioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
    }
} else {
    audioManager.setStreamMute(stream, true);
}

To unmute:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (savedStreamMuted) {
         audioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
         savedStreamMuted = false;
    }
} else {
    // Note that this must be the same instance of audioManager that mutes
    // http://stackoverflow.com/questions/7908962/setstreammute-never-unmutes?rq=1
    audioManager.setStreamMute(stream, false);
}

This assumes users are unlikely to invoke another app to mute the stream in-between and expect the stream to stay muted after your app unmutes (anyway there seems no way to check this).

Incidentally, the isStreamMute method was previously hidden, and was only unhidden in API 23, enabling its use for this purpose.

headuck
  • 2,763
  • 16
  • 19