I am using Media player to play a sound file. It is working well on 2.2 and 2.3 but not working for ICS 4.0.3, I have checked that mobile is not on silent mode. my code is:
private MediaPlayer mediaPlayer;
private void playSound(int soundType) {
try {
mediaPlayer = MediaPlayer.create(this, R.raw.beep);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
Sound in ICS is played like this :
(i copied it from a previous post, so if theres any weird stuff in there i apologize)
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
int mSoundID = mSoundPool.load(this, R.raw.sound1, 1);
float lActualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float lMaxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float lVolume = lActualVolume / lMaxVolume;
// Is the sound loaded already?
if (mSoundIsLoaded) {
mSoundPool.play(mSoundID, lVolume, lVolume, 1, 0, 1f);
}
You will have to put the sound file in your assets/raw directory.
edit: I forgot to mention where the mSoundIsLoaded parameter came from. I set it when my sound has been loaded. I do this in my onCreate method. when the sound is loaded I set the boolean field called mSoundIsLoaded. I do this to prevent NullPointerExceptions when playing the sound the loading of the sound looks like this:
mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
mSoundIsLoaded = true;
}
});
mSoundID = mSoundPool.load(this, R.raw.sound1, 1);
This is the code i use in my app.. It is working fine in ICS
public void playWelcomeAudio() {
Thread t = new Thread()
{
#Override
public void run() {
AssetFileDescriptor afd = getApplicationContext().getResources().openRawResourceFd(R.raw.welcome);
try {
if(afd!=null)
{
UtilLog.d(TAG, "INIT MEDIA PLAYER");
welcomeAudio = new MediaPlayer();
welcomeAudio.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
welcomeAudio.prepare();
welcomeAudio.start();
}
} catch (Exception e) {
UtilLog.e(TAG, "Audio error", e);
}
}
};
t.start();
}
You can remove the thread. It is not necessory.
Related
I'm using MediaPlayer to play audio via an AsyncTask, and using AudioManager to set the stream. On a specific button press, I call AudioManager's setSpeakerPhoneOn() to toggle, but it doesn't switch to ear speaker. My audio always blasts through the main speaker.
I tried these solutions (as is apparent in the code below), but none worked:
Switching between earpiece and speakerphone on button
press
Audiomanager Speaker not
working
Here's my code for initializing the AudioManager in onViewCreated:
try {
audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(loudOn);
// loudOn is defined globally, and initialized to false
}
This is the audio playing function which uses AsyncTask:
static private void playCall(final Context context, final String[] contactParts)
{
final MediaPlayer mediaPlayer = new MediaPlayer();
new AsyncTask<Void,Void,Boolean>() {
#Override
protected Boolean doInBackground(Void... voids) {
try {
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.reset();
mp.release();
}
});
int audioFile_R_id = //get audio file id
try {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(audioFile_R_id);
if (afd == null) return false;
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build());
} else {
//deprecated in API 26
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
mediaPlayer.prepare();
return true;
}
catch (Resources.NotFoundException rnf)
{
rnf.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
#Override
protected void onPostExecute(Boolean prepared) {
if (prepared) {
mediaPlayer.start();
}
}
}.execute();
}
And this is the button code that attempts to toggle:
loudFAB.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
loudOn = !loudOn;
audioManager.setSpeakerphoneOn(loudOn);
}
});
Change the AudioManager
try {
audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(loudOn);
// loudOn is defined globally, and initialized to false
}
I have a piano app working with this method:
public void play(String note) {
score++;
score();
try {
mp = MediaPlayer.create(this, getResources().getIdentifier(note, "raw", getPackageName()));
mp.start();
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer media) {
media.release();
}
});
} catch (Exception e) {
Log.e("Error", "error playing file : " + note + "\n" + e);
}
}
The issue is that if I press the keys too fast and several times i get errors like this:
E/MediaPlayer: error (1, -19)
These errors occur as I go on playing. But when I uninstall the app, something seems to reset, and I get less errors...Why is this happening and is there a solution for it?
As your code implies you are playing notes and not long MP3s, I suggest you use SoundPool instead of MediaPlayer. It is better suited for this kind of application as it pre-loads all the resources in advance.
An example of this kind of implementation:
private SoundPool soundPool;
private HashMap<String, Integer> soundNameToSoundIdMap;
private void initSoundMap() {
soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
soundNameToSoundIdMap = new HashMap<String, Integer>();
soundNameToSoundIdMap.put("note_a", loadSound(getContext(), R.raw.note_a));
soundNameToSoundIdMap.put("note_b", loadSound(getContext(), R.raw.note_b));
}
private int loadSound(Context context, int resId) {
return soundPool.load(context, resId, 1);
}
public void play(String note) {
score++;
score();
Integer soundId = soundNameToSoundIdMap.get(note);
if (soundId != null){
soundPool.play(soundId.intValue(), 100, 100, 1, 0, 0);
}
}
I need to play multiple (correct :2 ) mp3 files loaded from my assets when a button is clicked. If the button is again clicked 2 new songs should be played and the old ones should be stopped immidiatelly.The process is on going...
At the moment I have achieved this by stupidly creating 2 mediaPlayer instances in 2 separate methods that basically have the same body .
The caller is an onTouch method and ,within it, first I call method 1 ,then sleep for 2 secs ,then call method 2. I m sure there must be a way for this to be more elegant code? For example I have implemented some listeners that are just sitting there (Actually tried to make this work but totally screwed up with Illegal States all over the place ). Ideally I would like to use 1 MediaPlayer and one method for playing every sound in my app.
int carouzelIndex = 0
#Override
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
...
if (e.getAction() == MotionEvent.ACTION_UP) {
carouzelIndex++;
Assets.playMusic1("music1.ogg",false);
Thread thread = new Thread(){
public void run(){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Assets.playMusic2("music2.ogg",false);
}
}
}
}
Now my player methods 1 and 2 (playMusic1() and playMusic2() )are the same. Both are instansiating different MediaPlayers and for the shake of simplicity I write just one copy in the post
Public class Assets
MediaPlayer mediaPlayer;
public static void playMusic(String filename, boolean looping) {
AssetFileDescriptor afd = null;
Log.d("Assets", "playing music");
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(looping);
}
try {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(looping);
}
afd = GameMainActivity.assets.openFd(filename);
mediaPlayer.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
afd.close();
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!mp.isPlaying())
mp.start();
}
});
mediaPlayer.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayerIsFinished = true;
mp.reset();
}
});
mediaPlayer.setOnInfoListener(new OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
return false;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
For immediate playback you need two MediaPlayer set up and chained together via OnCompletionListener
You can do it like this:
Note that I also deleted some unnecessary overrides, you might add them again if you need them.
Public class Assets{
MediaPlayer mediaPlayer;
MediaPlayer mediaPlayer2;
boolean mediaplayer2prepared = false;
boolean mediaplayer1finished = false;
public static void playMusic(String filename, boolean looping, String filename2, boolean looping2) {
AssetFileDescriptor afd = null;
Log.d("Assets", "playing music");
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(looping);
mediaplayer1finished = false;
}
if (mediaPlayer2 == null) {
mediaPlayer2 = new MediaPlayer();
mediaPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer2.setLooping(looping);
mediaplayer2prepared = false;
}
try {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(looping);
mediaplayer1finished = false;
}
if (mediaPlayer2 != null) {
mediaPlayer2.stop();
mediaPlayer2.release();
mediaPlayer2 = new MediaPlayer();
mediaplayer2prepared = false;
mediaPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer2.setLooping(looping);
}
afd = GameMainActivity.assets.openFd(filename);
mediaPlayer.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
afd.close();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!mp.isPlaying())
mp.start();
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayerIsFinished = true;
mp.reset();
if(mediaplayer2prepared)
mediaplayer2.start();
mediaplayer1finished = true;
}
});
mediaPlayer.prepareAsync();
afd2 = GameMainActivity.assets.openFd(filename2);
mediaPlayer2.setDataSource(afd2.getFileDescriptor(),
afd2.getStartOffset(), afd2.getLength());
afd2.close();
mediaPlayer2.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayerIsFinished = true;
mp.reset();
mediaplayer2prepared = true;
if(mediaplayer1finished && !mp.isPlaying()){
mp.start();
}
}
});
mediaPlayer2.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayerIsFinished = true;
mp.reset();
}
});
mediaPlayer2.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
}
To start both mediaplayers in succession simply do Assets.playMusic("music1.ogg",false, "music2.ogg",false);
You can try something like this. Use a single mediaplayer in a single thread. It is an asynchronous operation so it will go on also if the thread is paused. I think it would work.
private Thread t = null;
private MediaPlayer mediaPlayer;
...
Button b=findViewById(R.id.yourButtonId);
b.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//if button had previously clicked stop audio reproduction
if(mediaPlayer.isPlaying()) mediaPlayer.stop();
if(t.isAlive()) t.stop();
String[] files;
//Here you have to set your filenames in the array
...
...
//Now play that audio
playMusic(files, false);
}
});
...
protected static void playMusic(String[] files, boolean looping){
AssetFileDescriptor afd = null;
Log.e("Assets", "Playing music");
t=new Thread(){
#Override
public void run(){
//Initialize mediaPlayer
for(String filename:files){
mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(looping);
afd = GameMainAcivity.assets.openFd(filename);
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),afd.getLength());
afd.close();
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer mp){
if(!mp.isPlaying()) mp.start();
}
});
//while audio is playing wait in this position
while(mediaPlayer.isPlaying()){
this.wait(100);
}
//now loop can restart with the other filename that has
//to be reproduced
}
}
};
t.start();
}
I have done an android project on NFC and I want to add a warning tone after receiving NFC date succeed ,how can I do it?
Use SoundPool class. Place your audio files in /res/raw/ and first init loading them (for example in OnCreate Method) and then request to play selected audio file. here is code example:
private SoundPool soundPool;
private boolean tiltSoundsLoaded = false;
private int tiltSoundID;
private int tiltFailureSoundID;
public void initTiltSounds(Context context) {
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
tiltSoundsLoaded = true;
}
});
tiltSoundID = soundPool.load(context, R.raw.swosh_sound_effect, 1);
tiltFailureSoundID = soundPool.load(context, R.raw.fail_metallic, 1);
}
public void playTiltSound(AudioManager audioManager, boolean success) {
try{
int soundToPlay;
if(success)
soundToPlay = tiltSoundID;
else
soundToPlay = tiltFailureSoundID;
float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (tiltSoundsLoaded)
soundPool.play(soundToPlay, actualVolume, actualVolume, 1, 0, 1f);
else
Log.e(LOG_TAG, "Tilt Sound not loaded");
}catch(Exception e){
Log.e(LOG_TAG, "Could not play tilt sound");
}
}
I try to play a device ringtone one time with the MediaPlayer class (I have to use MediaPlayer as I use the ringtones together with other audio sources in my app) So i try the following to play a random ringtone yet I cant stop it looping, it keeps playing. Is it possible to play a ringtone only one time with MediaPlayer.
Thanks
try {
RingtoneManager mRing = new RingtoneManager(RingtoneActivity.this);
int mNumberOfRingtones = mRing.getCursor().getCount();
Uri mRingToneUri = mRing.getRingtoneUri((int) (Math.random() * mNumberOfRingtones));
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(RingtoneActivity.this, mRingToneUri);
mMediaPlayer.prepare();
mMediaPlayer.setLooping(false);
mMediaPlayer.start();
} catch (Exception ignore) {
}
UPDATE:
I just have posted a new question related to this one as I was able to find the specific cause of the trouble in my case.
I found simple solution with use events - confirm answer since it solves your problem :)
mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
mediaPlayer.stop();
}
});
http://developer.android.com/reference/android/media/MediaPlayer.html
Remember about release().
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
Full code it your want to use need set ring tone to something what you would like.
AudioManager audioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
int volume = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(view.getContext());
Uri notificationSoundUri = Uri.parse(prefs.getString("notification_sound", "DEFAULT_SOUND"));
MediaPlayer mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(view.getContext(), notificationSoundUri);
} catch (Exception e1) {
e1.printStackTrace();
mediaPlayer.release();
return;
}
mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
try {
mediaPlayer.prepare();
} catch (Exception e1) {
e1.printStackTrace();
mediaPlayer.release();
return;
}
mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
// TODO Auto-generated method stub
mediaPlayer.stop();
mediaPlayer.start();
}
});
mediaPlayer.setVolume(volume, volume);
mediaPlayer.start();
use Notifications
NotificationManager nManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notifBuilder =
new NotificationCompat.Builder(context);
notifBuilder.setSound(sound);
notification = notifBuilder.build();
nManager.notify(SOME_INT_CONSTANT, notification);