In my app, I use the following code to play a short notification sound using MediaPlayer with STREAM_NOTIFICATION. The issue is that, when the app plays the notification sound and at the same time music is played at background by music player app, the notification sound will interrupt (pause) the music playing. How can I make my app's notification sound to be played simultaneously with the background music playback? Thanks.
AssetFileDescriptor afd =
mResources.openRawResourceFd(resId);
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
mediaPlayer.prepare();
mediaPlayer.start();
The behaviour described in the question seems to be specific for Android 5.x and below. For Android 6.x and above AudioManager behavior has changed and AudioSystem.STREAM_NOTIFICATION flag doesn't interrupt music playback anymore.
As workaround I would recommend to replace
mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
by
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
P.S. Not sure what exactly changed in Android platform but according to
https://android.googlesource.com/platform/frameworks/base/+/android-5.1.1_r37/media/java/android/media/AudioAttributes.java and https://android.googlesource.com/platform/frameworks/base/+/android-6.0.0_r26/media/java/android/media/AudioAttributes.java they treat AudioSystem.STREAM_NOTIFICATION as AudioSystem.STREAM_SYSTEM for both Android 5.x & 6.x:
public Builder setInternalLegacyStreamType(int streamType) {
switch(streamType) {
/*...*/
case AudioSystem.STREAM_SYSTEM:
mContentType = CONTENT_TYPE_SONIFICATION;
break;
/*...*/
case AudioSystem.STREAM_NOTIFICATION:
mContentType = CONTENT_TYPE_SONIFICATION;
break;
/*...*/
default:
Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
}
mUsage = usageForLegacyStreamType(streamType);
return this;
}
Related
Basically I'm using android voice recogniser and google cloud speech api, both in my app.
For android speech recogniser there is default tones playing when start recognising and stop recognising.
I want to play same tone when I use google cloud speech api.
I tried to play sound via media player but unable to access the URI of that particular sounds. can some one help me to play that sounds.
I tried this :
private void playSound(){
Uri defaultRingtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
MediaPlayer mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(getContext(), defaultRingtoneUri);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM);
mediaPlayer.prepare();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp)
{
mp.reset();
}
});
if (mediaPlayer.isPlaying()){
mediaPlayer.reset();
}
mediaPlayer.start();
} catch (IllegalArgumentException | SecurityException
| IllegalStateException | IOException e) {
e.printStackTrace();
}
}
I am brand new (47 minutes) into Android development and have a problem that I have is likely to be a simple one.
Anyway, here it is.
I would like to use a web service which, given a url, spits back an Mp3 (browser instantly starts downloading it).
MediaPlayer player = new MediaPlayer();
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
String url = "http://www.gimme-an-mp3.com/xyz";
try {
player.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
player.prepareAsync();
player.start();
For some reason, the media player does not play my Mp3 file. Why? Do I have to first download it and then pass it to the media player?
you have to call player.start() only after player has been prepared.
before that, the player is still preparing.
player.prepareAsync();
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
more details can be found here http://developer.android.com/reference/android/media/MediaPlayer.html
and here Android: correct usage of PrepareAsync() in media player activity
I'm trying to play an alarm sound exactly once:
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
final MediaPlayer mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(ctx, notification);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.setLooping(false);
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer arg0) {
mMediaPlayer.seekTo(0);
mMediaPlayer.start();
}
});
But the sound plays endlessly, although 'setLooping' is set to false.
What else can I do to make the sound not loop?
The call:
mMediaPlayer.prepare();
Is a blocking call for files so you dont really need the listener, you can just call:
mMediaPlayer.start();
Right after it.
Also it start from time 0 so you dont need:
mMediaPlayer.seekTo(0);
As to the endless playing, you can find the explanation and solution here:
android mediaplayer loops forever on ICS
My app runs as a service in background and can give notifications based on some events. Currently, to play notification files, I use MediaPlayer in my app :
MediaPlayer mPlay = MediaPlayer.create(this, R.raw.sound);
mPlay.start();
But, if a song is already playing on the device (Music player, radio etc), and my notification plays when receiving the event, both the sounds (Music audio & notification audio) is heard in parallel.
So, is there a way that I can suppress the system audio volume so that my notification is heard clearly and once notification audio is over, the system audio can playback again?
Thanks for any help
I got the answer to this question in the following link:
http://developer.android.com/training/managing-audio/audio-focus.html
We need to request for audio focus (transient/permanent) and then can play the app audio:
AudioManager am = (AudioManager) 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_TRANSIENT);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// Start playback.
Log.i(TAG, "...audiofocus granted....");
MediaPlayer mPlay = MediaPlayer.create(this, R.raw.sound);
mPlay.start();
}
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
Log.i(TAG, "....audiofocus loss transient in listener......");
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
Log.i(TAG, "....audiofocus gain in listener......");
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
Log.i(TAG, "....audiofocus loss in listener......");
//am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
};
Hope it helps someone.
I've tried settings the audio stream of the media player in my application using the following code but when I do this I hear no sound in the emulator. If I don't set the stream for the player then the audio plays fine. I'm sure I'm using this wrong but cannot workout how, any help?
MediaPlayer player = MediaPlayer.create(getApplicationContext(), R.raw.test_audio);
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.start();
Note: I've added the MODIFY_AUDIO_SETTINGS permission to my manifest already.
Thanks!
I don't know why this would happen, however the code below works. You should set the data source with setDataSource() instead of with create().
This code works:
MediaPlayer mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setDataSource(this,Uri.parse("android.resource://PACKAGE_NAME/"+R.raw.soundfile));
mp.prepare();
mp.start();
This code doesn't work:
MediaPlayer mp = MediaPlayer.create(this, R.raw.soundfile);
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.prepare();
mp.start();
The issue is you are using MediaPlayer.create() to create your MediaPlayer. Create function calls the prepare() function which finalize your media and does not allow you to change AudioStreamType.
The solution is using setDataSource instead of create:
MediaPlayer mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setLooping(true);
try {
mp.setDataSource(getApplicationContext(), yourAudioUri);
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
See this link for more information.
1.
setAudioStreamType(int streamtype)
Must call this method before prepare() ;
2.
MediaPlayer.create(Context context, int resid)
On success, prepare() will already have been called and must not be called again.
The solution here was deprecated in API 22
I opened my own thread to figure this out.
Here is an updated working solution.
mediaPlayerScan = new MediaPlayer();
try {
mediaPlayerScan.setDataSource(getContext(),
Uri.parse(getString(R.string.res_path) + R.raw.scan_beep));
if (Build.VERSION.SDK_INT >= 21) {
mediaPlayerScan.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
} else {
mediaPlayerScan.setAudioStreamType(AudioManager.STREAM_ALARM);
}
mediaPlayerScan.prepare();
} catch (IOException e) {
e.printStackTrace();
}
Try the following:
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.prepare();
player.start();
And why are you calling "audioManager.getStreamVolume(AudioManager.STREAM_ALARM);"? The value isn't stored in a variable, so it is rather useless ;)
I hope that helped