I am using VideoView to play an mp4 video. I would like to give the user the option of watching this video with sound or mute the sound if he/she chooses. I do not use the mediaController allowing the user to stop and play, I have "touch" events controlling this.
UPDATE: I have a menu that I have added a "mute" icon to. Now I am trying to figure out how to add the mute to this button. I am reading some info on from the Android AudioManager, in particular the setStreamMute. Here is what the API's say:
public void setStreamMute (int streamType, boolean state)
Since: API Level 1
Mute or unmute an audio stream.
The mute command is protected against client process death: if a process with an active mute request on a stream dies, this stream will be unmuted automatically.
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.
For a better user experience, applications MUST unmute a muted stream in onPause() and mute is again in onResume() if appropriate.
This method should only be used by applications that replace the platform-wide management of audio settings or the main telephony application.
Parameters
streamType The stream to be muted/unmuted.
state The required mute state: true for mute ON, false for mute OFF
Use the AudioManager service to mute and unmute just the stream related to your video. From the method(s) you have declared to respond to the user touch events, call methods like:
public void mute() {
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setStreamMute(AudioManager.STREAM_MUSIC, true);
}
public void unmute() {
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setStreamMute(AudioManager.STREAM_MUSIC, false);
}
This will leave the other streams (notification, alarm, etc.) active so you aren't silencing the whole device just to mute the video.
Also, if you need to suggest to your Activity which stream it should be pushing the audio through you can call Activity.setVolumeControlStream(AudioManager.STREAM_MUSIC) to tie your Activity's window to that stream.
I was able to implement my desire to have a mute button contained in a menu button. Each time the user interacts with the button, the video either mutes or unmutes. Here is the code:
private AudioManager mAm;
private boolean mIsMute;
// Audio mgr
mAm = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mIsMute = false;
public void isMute() {
if(mIsMute){
mAm.setStreamMute(AudioManager.STREAM_MUSIC, false);
mIsMute = false;
}else{
mAm.setStreamMute(AudioManager.STREAM_MUSIC, true);
mIsMute = true;
}
}
And then inside my case:
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
// Mute
case R.id.main_menu_mute:
isMute();
break;
.........
}
return super.onOptionsItemSelected(item);
}
Related
How to mute mic in android my code is working but in some device mic is not muted please give solution my code is:
private void setMicMuted(boolean state){
AudioManager myAudioManager = (AudioManager)con.getSystemService(Context.AUDIO_SERVICE);
// get the working mode and keep it
int workingAudioMode = myAudioManager.getMode();
myAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// change mic state only if needed
if (myAudioManager.isMicrophoneMute() != state) {
myAudioManager.setMicrophoneMute(state);
}
// set back the original working mode
myAudioManager.setMode(workingAudioMode); }
If you are using MediaRecorder just use it without calling setAudio on it, this way it will only record video without audio.
I am working on a push to talk App, where the receiver will get a live-streamed audio message from a sender if he is connected to the internet. Now everything's working all fine except one issue that is: whenever any other applications like google music or youtube are playing audios, that time if I am getting an audio notification or message through the application, both the audios are playing in a parallel manner. I am using VoiceLayer library for the app and to play a message audio, they use VoiceLayerMessagePlayer. Is there any way I can pause the other media players when I am getting a notification or voice message in my Application? I looked through the internet and found out that OnAudioFocusChangeListener might be helpful but didn't get a proper example regarding its implementation. Please do let me know if you need any more information. Thanks in advance.
You should use AudioManager service to receive notification whether you receive/lost audio focus (Managing audio focus). I've done similar thing in a project where when my app starts playing, Google Play pause and vice versa. Use the following code where you are controlling your media playback like (activity or service)
Stop MediaPlayer when an other app play music
Please check below code it's working fine.
AudioManager am = null;
// Request focus for music stream and pass
AudioManager.OnAudioFocusChangeListener
// implementation reference
int result = am.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if(result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
{
// Play
}
// Implements AudioManager.OnAudioFocusChangeListener
#Override
public void onAudioFocusChange(int focusChange)
{
if(focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)
{
// Pause
}
else if(focusChange == AudioManager.AUDIOFOCUS_GAIN)
{
// Resume
}
else if(focusChange == AudioManager.AUDIOFOCUS_LOSS)
{
// Stop or pause depending on your need
}
}
Hope this helps you and solved your problem.
please try this code. it work with me
val audioManager = requireActivity().getSystemService(Context.AUDIO_SERVICE) as AudioManager
val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_GAME)
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
setOnAudioFocusChangeListener({ }, object : Handler() {})
build()
})
setAcceptsDelayedFocusGain(true)
build()
}
audioManager.requestAudioFocus(focusRequest)
When I play 'Soundcloud' or 'Saavn' music playing app and I start my own app, the music in Saavn or Soundcloud is still playing in background. Need a way to stop it using code. How to do it ?
I tried this -
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
String SERVICECMD = "com.android.music.musicservicecommand";
String CMDNAME = "command";
String CMDSTOP = "stop";
if(mAudioManager.isMusicActive()) {
Intent i = new Intent(SERVICECMD);
i.putExtra(CMDNAME , CMDSTOP );
HomeActivity.this.sendBroadcast(i);
}
but it is only useful in stopping the music if Android's default music player is playing in background and not 3rd party apps like Saavn and Soundcloud.
One possible solution I found on this is using the AudioManager.requestAudioFocus(...) function
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
Code example:
int result = am.requestAudioFocus(focusChangeListener, //Request audio focus for playback
AudioManager.STREAM_MUSIC, //Use the music stream.
AudioManager.AUDIOFOCUS_GAIN); //Request permanent focus.
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// other app had stopped playing song now , so u can do u stuff now .
}
Audio focus is assigned in turn to each application that requests it. This means that if another application requests audio focus, your's will lose it.
The app is notified when there is a change on the AudioFocus, through the onAudioFocusChange event listener. This listener is the first parameter in the requestAudioFocus function.
This listener should look something like:
private OnAudioFocusChangeListener focusChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
AudioManager am =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (focusChange) {
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK):
//Lower the volume while ducking (not sure what ducking means really)
break;
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
//TODO: pause audio
break;
case (AudioManager.AUDIOFOCUS_LOSS) :
//TODO: pause audio
break;
case (AudioManager.AUDIOFOCUS_GAIN):
//TODO: Return the volume to normal and resume if paused.
break;
default: break; //empty on default
}
}
};
I think it is not possible to stop a service of another app as you may not know the processid, You can stop the service of your app only if you know the Pid of the app using
android.os.Process.killProcess(processIdKillService)
How do applications like Soundcloud stop another app's MediaPlayer? For example, when I am playing a song through Google Music and I open SoundCloud, the song from Google Music stops playing as soon as the Soundcloud song starts. I might be missing something obvious but I have always wondered how this is achieved.
Thanks,
Justin
Use Audio Focus. See Request the Audio Focus
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}
Adding on to #TCA's answer:
There is only one AudioManager. So, Audio focus is assigned to each application that requests it one by one. This means that if another application requests audio focus, your application will lose it. You will be notified of the loss of audio focus through the onAudioFocusChange handler of the Audio Focus Change Listener (afChangeListener in TCA's answer) you registered when requesting the audio focus.
private OnAudioFocusChangeListener focusChangeListener =
new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
AudioManager am =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (focusChange) {
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
//Transient audio loss
break;
case (AudioManager.AUDIOFOCUS_LOSS) :
//Audio focus loss. Stop playback.
break;
case (AudioManager.AUDIOFOCUS_GAIN) :
//Audio focus gain. Start playback.
break;
default: break;
}
}
};
I've built a small app that mutes/unmute the music stream using the class AudioManager.
In fact, it works until I close the application. i.e. I've muted the sream, I close the app, I restart the app and the button doesn't unmute the stream any more. I've searched in the net but no one seems to have met this problem.
Here's my code:
public class ControlloVolume extends Activity {
ToggleButton tb_mute;
Button btn_mute;
AudioManager mAudioManager;
boolean mute;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controllo_volume);
tb_mute = (ToggleButton) findViewById(R.id.tb_mute);
btn_mute = (Button) findViewById(R.id.btn_mute);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)==0){
mute = true;
tb_mute.setChecked(mute);
}else{
mute = false;
tb_mute.setChecked(mute);
}
}
public void onButtonClicked(View view){
if(!mute){
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
tb_mute.setChecked(true);
mute = true;
}else{
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
tb_mute.setChecked(false);
mute = false;
}
}
First, beware it's not recommended
For a better user experience, applications MUST unmute a muted stream
in onPause() and mute it again in onResume() if appropriate.
But I assume you know what you're doing, so here we go.
Note this line from the docs on setStreamMute
The mute command is protected against client process death: if a
process with an active mute request on a stream dies, this stream will
be unmuted automatically.
I've checked on my device and indeed, when I just exit my activity, stream stays muted. But as soon as I kill the process, mute goes away.
Take a look at activity lifecycle.
As your current approach will not work reliably, you could write a foreground service which will trigger the mute - start that service from your activity.
Also you would likely need to setStreamSolo.
Two important things.
Volume==0 and muted are NOT the same thing. I.e. stream can have volume==0 but be not muted. Though if stream is muted, volume will always be 0
mute requests are cumulative. I.e. if you've set mute twice, you must unmute twice as well - your code doesn't handle that
As a side note, for such app you would probably want to use widget instead of activity.
Off topic. It seems surprisingly lot of people don't quite get how booleans work.
And as I see code such as yours regulary, here is a bit streamlined rewrite.
#Override
public void onCreate(Bundle savedInstanceState) {
// ... setup just like you did
// boolean is just like any other type. You can assign not only
// constants, but expressions too
mute = (mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)==0);
tb_mute.setChecked(mute);
}
public void onButtonClicked(View view){
mute = !mute; // invert value
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, mute);
tb_mute.setChecked(mute);
}