Android - How to change sound output while playing sound? - android

I have an app that plays a list of soundtracks. It works great, however changing the sound output to internal speakers or vice versa, has no effect. It stops the current one, and then plays the next on the new mode.
I've read in android documentation of MediaPlayer that I can't change the sound output using setAudioStreamType() method. So this is the problem, but can't find a solution!
Here's the code for the toggle when the track is playing:
if (this.audioManager.isSpeakerphoneOn() || this.getCurrent() == 1) {
this.audioManager.setMode(AudioManager.MODE_IN_CALL);
this.audioManager.setSpeakerphoneOn(false);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
} else if (this.getCurrent() != 0) {
this.audioManager.setMode(AudioManager.MODE_NORMAL);
this.audioManager.setSpeakerphoneOn(true);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
Thanks in advance!

Related

Android interrupt media player with ringtone manager

I have used ringtonemanager previously in android studio and it seemed to lower the volume of any music that was playing in a different app to play the alert i was trying to play, then once my alert had completed the background music would then come back to normal volume (as the default alarm/notification would do) But now a year or so later im trying to implement this again but my alert cannot be heard over the music playing in Google Play Music.
Is this a change that now requires additional parameters to function as it used to?
Im using:
Uri notification =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
myRM = RingtoneManager.getRingtone(this.getContext(), notification);
myRM.play();
Many Thanks
Handling Changes in Audio Output seems what fits your need.
In short, you need to request audio focus before starting playing.
...
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(null, mStreamType, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
mRingtone.play();
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to
last a short amount of time, and where it is acceptable for other
audio applications to keep playing after having lowered their output
level (also referred to as "ducking").
Remember to release audio focus when finishing..
if (mRingtone != null && mRingtone.isPlaying()) {
mRingtone.stop();
}
mRingtone = null;
if (mAudioManager != null) {
mAudioManager.abandonAudioFocus(null);
}

Adding a delay to android sound output

So I wrote this piece for an Android App. The idea is simple:
Detect whether sound is playing and if yes open the BluethoothSCO Channel so the audio gets played there.
I want to use it to "route" the navigation direction infos to my car speaker. It works nearly like expected.
There is a 'huge' delay of around 1 second between the audio recognition and the bluethoothsco connection being ready. This results in a loss of nearly half the navigation information.
My Idea was to add a delay or pause the playback for a second.
NOW: Sound is detected -> BluethootSCO opening (sound keeps playing here) -> sound over car speaker
IDEA: Sound is detected -> pause/delay for 1 sec ->BluethootSCO opening -> resume playback -> sound over car speaker
I thought about recording it and playing it afterwards but that would be to late for some informations like "turn left NOW".
A short delay would be ok, but I have no idea on to implement this :(
Since the app is only for myself using root would be ok.
Maybe there is an possibility direct at the AudioFlinger?
public void checkSound() {
AudioManager localAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
Visualizer localVisualizer = new Visualizer(0);
localVisualizer.setEnabled(true);
Visualizer.MeasurementPeakRms localPeak = new Visualizer.MeasurementPeakRms();
boolean wasPlayingBefore=false;
while (keeprunning) //Loop to detect changes on the Media Audio Stream
{
localVisualizer.getMeasurementPeakRms(localPeak);
if(localPeak.mPeak > -8500 && !wasPlayingBefore)
{
//There is some audio output
wasPlayingBefore=true;
localAudioManager.setBluetoothScoOn(true);
localAudioManager.startBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
android.os.SystemClock.sleep(5000); //Route to BT Headset will exist min. 5 seconds ...
}
if(localPeak.mPeak <= -8500 && wasPlayingBefore)
{
//output (temporary) gone
android.os.SystemClock.sleep(2000);//... plus this 2 seconds
//check again
localVisualizer.getMeasurementPeakRms(localPeak);
}
if(localPeak.mPeak <= -8500 && wasPlayingBefore)
{
//Audio didn't get back in last 2 seconds...
wasPlayingBefore=false;
localAudioManager.setBluetoothScoOn(false);
localAudioManager.stopBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_NORMAL);
}
android.os.SystemClock.sleep(100); //Slow down the loop
Log.d("Peak", String.valueOf(localPeak.mPeak));//Debug info - Audio peak -9600 = Silent, 0 = MAX Output
}
localVisualizer.release();
}

How to remove background Noise in Audio Track?

I am developing VOIP kind of application. Sending the voice is perfect but when i receive the same voice from the webserver, i am playing back that using AudioTrack API.
I am calling at.play() and at.write in a Thread so that i should get all the voice which is recorded and sent from the other device.
But, now the problem here i m facing is, if there is no voice than its still playing like some bullet sound, i mean there is a continuos background sound when i try to play .
I m using this following function in a Thread:
if (at != null) {
if (at.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
at.play();
} else {
if (playing == true) {
System.out.println("BEFORE WRITE");
at.write(playShortData, 0,
playShortData.length);
System.out.println("AFTER WRITE");
at.flush();
playing = false;
}
}
}
How can i remove the background noise if there no voice is send from other device.
I think its playing Junk value when none of them is speaking on other sides, its just sending junk values ..

Media Player crash after use

I am working on a small application that plays back eight different .5 second midi files. I have an ontouch action that gets called everytime a specified object gets touched and within that I have an if/else if statement that plays the specified midi file depending on the object touched. When I run this, It works fine for the first several touches but after a while the playback stops, and then the app eventually crashes. What is going wrong here?
Basic Structure:
public ontouch(){
if (something >= 3){
mediaplayer s = mediaplayer.create(somethingmidi2);
s.start();
}else if (something < 3){
mediaplayer s = mediaplayer.create(somethingmidi);
s.start();
}
} `
Just a guess, but you probably aren't calling the release() method of the media player, nor reset() when you are reinitializing it.

How to shut off the sound MediaRecorder plays when the state changes

My Android application uses MediaRecorder on a SurfaceHolder to show a live preview of what the camera is capturing. Every time the user presses the REC button on the app, the app starts to record.
Every time the state of the MediaRecorder switches to/from 'start', Android automatically (?) fires off a beep. This beep sounds different from phone to phone, which makes me think that this beep is natively attached to the state change of MediaRecorder.
The beep is not played if the volume of the phone is set to silent.
I google it and did some research but I couldn't find a way to turn this beep off. Is it possible? If so, how?
The app was tested on: Nexus One 2.3.4, Desire HD 2.3.3
Ok the accepted answer did not work for me. On a Galaxy Nexus Running 4.2.1 (Jelly Bean) when recording via MediaRecorder I needed to use AudioManager.STREAM_RING because AudiManager.STREAM_SYSTEM did not work. It would always play a "chime" sound at beginning of each recording.
Here is my solution using "STREAM_RING" and others.
// disable sound when recording.
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_ALARM,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_DTMF,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_MUSIC,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_RING,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_VOICE_CALL,true);
// re-enable sound after recording.
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_ALARM,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_DTMF,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_MUSIC,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_RING,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_VOICE_CALL,false);
Also as the documentation states be sure to re-enable audio in the onPause() method.
I hope this helps someone tearing their hair out over this problem. This disables all sound streams. You can go through and work out which ones you specifically need. I found that different versions of android use different streams for the chime when mediarecorder runs. ie, STREAM_RING works for android 4.2.1 but for ICS it doesn't work.
Edit: As my comment below mentions, I can't get the sound disabled for Android OS 2.3.3 on a Samsung Galaxy S1. Anyone have luck with this?
Darrenp's solution helps to tidy up code but in a recent update to my phone (galaxy nexus android 4.3) the volume / recording beep started up again! The solution by user1944526 definitely helps. In an effort to make it easier to understand...
Use something like ,
// class variables.
Integer oldStreamVolume;
AudioManager audioMgr;
enableSound() {
setMuteAll(false);
if (audioMgr != null && oldStreamVolume != null) {
audioMgr.setStreamVolume(AudioManager.STREAM_RING, oldStreamVolume, 0);
}
}
disableSound() {
audioMgr = (AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
oldStreamVolume = audioMgr.getStreamVolume(AudioManager.STREAM_RING);
audioMgr.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
}
For completeness each of those functions you could also call either darrenp's solution in a function or include all of the above STREAM_ lines. but for me now, these combined are working. Hope this helps someone...
try
((AudioManager)context.getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,true);
That mute all sounds.
Following on from #wired00's answer, the code can be simplified as follows:
private void setMuteAll(boolean mute) {
AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int[] streams = new int[] { AudioManager.STREAM_ALARM,
AudioManager.STREAM_DTMF, AudioManager.STREAM_MUSIC,
AudioManager.STREAM_RING, AudioManager.STREAM_SYSTEM,
AudioManager.STREAM_VOICE_CALL };
for (int stream : streams)
manager.setStreamMute(stream, mute);
}
This works fine for now but if more streams are introduced in the future, this method may need updating. A more robust approach (though perhaps overkill) is to use reflection to get all the STREAM_* static fields:
List<Integer> streams = new ArrayList<Integer>();
Field[] fields = AudioManager.class.getFields();
for (Field field : fields) {
if (field.getName().startsWith("STREAM_")
&& Modifier.isStatic(field.getModifiers())
&& field.getType() == int.class) {
try {
Integer stream = (Integer) field.get(null);
streams.add(stream);
} catch (IllegalArgumentException e) {
// do nothing
} catch (IllegalAccessException e) {
// do nothing
}
}
}
Interestingly, there seem to be some streams that are not documented, namely STREAM_BLUETOOTH_SCO, STREAM_SYSTEM_ENFORCED and STREAM_TTS. I'm guessing/hoping there's no harm in muting these too!
I just had this problem on a Lenovo K900 running Android 4.2.1.
setStreamMute doesn't seem to do anything for me, but setStreamVolume works...
AudioManager audioMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
int oldStreamVolume = audioMgr.getStreamVolume(AudioManager.STREAM_RING);
audioMgr.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
... do recording ...
audioMgr.setStreamVolume(AudioManager.STREAM_RING, oldStreamVolume, 0);
Add this code before the start:
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC,true);
And add this code after the stop:
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC,false);
There are countries/firmwares that use STREAM_SYSTEM and others using STREAM_MUSIC. There are also countries where this is illegal but use a different channel.

Categories

Resources