Android MediaPlayer problems - android

I am triggering a MediaPlayer to play a sound on a button click. Sometimes, the player will play the whole sound, sometimes it will not. It always cuts off on the end. I read a few threads on here where people were having the same problem, but none of the suggestions worked. For example, someone said that adding a mediaPlayer.onCompletionListener() would fix the issue, but it has not.
Here is the code with the MediaPlayer:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.vocab_row, parent, false);
ImageView playIcon = (ImageView) row
.findViewById(R.id.blueplay_icon);
TextView vocabWord = (TextView) row
.findViewById(R.id.vocab_text_word);
TextView vocabMeaning = (TextView) row
.findViewById(R.id.vocab_text_meaning);
vocabWord.setText(data.get(position).getKey());
vocabMeaning.setText(data.get(position).getDefinition());
final String fileName = "audio/" + data.get(position).getAudio();
// set the click listener for the play button
playIcon.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final MediaPlayer player = new MediaPlayer();
AssetManager manager = SingleLesson.this.getAssets();
final AssetFileDescriptor descriptor;
try {
descriptor = manager.openFd(fileName);
long start = descriptor.getStartOffset();
long end = descriptor.getLength();
//reset player
if (player != null) {
player.reset();
}
player.setDataSource(descriptor.getFileDescriptor(),
start, end);
} catch (IOException e) {
Log.e("IO EXCEPTION: ", "while getting mp3 assets.");
e.printStackTrace();
}
// set volume
player.setVolume(100, 100);
try {
player.prepare();
} catch (IllegalStateException e) {
Log.e("ERROR: ", "media player, illegal state");
e.printStackTrace();
} catch (IOException e) {
Log.e("ERROR: ", "media player, IO exception");
e.printStackTrace();
}
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer inPlayer) {
player.start();
}
});
// called when the file is finished playing
player.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer player) {
player.stop();
player.release();
}
});
}
This problem is happening on the emulator but not my htc incredible. It also doesn't happen on my girlfriend's moto droid2, but the sounds do have "clicks" in them on the moto droid2.

How old is the emulator? I have seen issues with emulators files getting corrupt after some time. If it is not a new one, try creating a one.

I have couple suggestions for you. It might or might not work. MediaPlayer.prepare() is a synchronous method, that means it will complete before any other code down the line runs, so you don't need onPreparedListener to start the playback. you can just type MediaPlayer.start() below the prepare method. Other suggestion is since you wanna play the sound again and again you prolly dont wanna release the mediaplayer. Try putting the MediaPlayer.reset() method instead in the onCompletionListener. Hope it solves the problem. You can also try adding MediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); before the setDataSource method.
Thanks.

Related

Playing audio files from device internal storage. It keeps throwing IOException on void prepare()

I want to play audio files which are stored on internal storage of my application from a user device: here below are the full code of extracting and showing list of those audio files=
//variables of retrieving audio file from internal storage
ListView listView_phone_calls;
ArrayList<File> phone_call_list;
ArrayAdapter<File> adapter;
//variables of playing an audio file
MediaPlayer player;
listView_phone_calls=(ListView)findViewById(R.id.listView_phone_calls);
phone_call_list=new ArrayList<>();
File[] file=getApplicationContext().getFilesDir().listFiles();
for (int i=0;i<file.length;i++){
phone_call_list.add(file[i]);
}
adapter=new ArrayAdapter<>(PhoneCall_Player.this,android.R.layout.simple_list_item_activated_1,phone_call_list);
listView_phone_calls.setAdapter(adapter);
listView_phone_calls.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//This is what should happen when a user clicks on a one item
player=new MediaPlayer();
File call_rec=(File) listView_phone_calls.getItemAtPosition(position);
try {
player.setDataSource(String.valueOf(call_rec));
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(PhoneCall_Player.this,"Sorry! File not found! "+e.getMessage(),Toast.LENGTH_SHORT).show();
}catch (IllegalArgumentException e){
e.printStackTrace();
Toast.makeText(PhoneCall_Player.this,"Sorry! Something is wrong!, "+e.getMessage(),Toast.LENGTH_SHORT).show();
}
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
player.prepare();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(PhoneCall_Player.this,"Player couldn't be prepared to play! "+e.getMessage(),Toast.LENGTH_SHORT).show();
}
player.start();
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
player.release();
player=null;
}
});
}
});
Whenever I click on an item, the toast of player couldn't be prepared to play keeps appearing; I think there is no problem with setDataSource(); so what is wrong with my codes. Is there any error that I am putting that I don't see? Or I am not calling MediaPlayer well?
prefix your path with file:// so that your path becomes file:///data/user/0/com.example.mypackagename/files/audio00001.mp3

Media file is played and overlay when i selected item

I have a application in which when i select any item then it will play that media file but when i select other item then the old media is playing continue and the current media file is overlay(current file is also playing) so i am listen both media files.
I have written below code:
ImageView songView;
Gallery songGallery;
MediaPlayer mp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song_test);
songView = (ImageView) findViewById(R.id.songView);
songGallery = (Gallery) findViewById(R.id.songGallery);
songGallery.setAdapter(new MyGalleryAdapter(getApplicationContext()));
songGallery.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View arg1,
int arg2, long id) {
// TODO Auto-generated method stub
songView.setImageResource(symbolIds[arg2]);
String imageName = getResources().getResourceEntryName(
symbolIds[arg2]);
Uri audio = Uri.parse("android.resource://" + getPackageName()
+ "/raw/" + imageName + "");
mp = MediaPlayer.create(getApplicationContext(), audio);
try {
if (mp.isPlaying()) {
mp.reset();
}
mp.start();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"Error", Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), e.toString(),
Toast.LENGTH_LONG).show();
}
....
....
}
}
So my question is - When i select the item the song is playing very well but when i select other item then the old song is also playing with the current.
so i want to stop the old song...
I want to play only current selected item song.
The issue is that MediaPlayer is being recreated instead of being reset. Rather than using the #create() factory call, you can use the constructor instead. In the following code, if the mp is already created it is reset and then a datasource is prepared and started.
if (mp != null) {
mp.reset();
} else {
mp = new MediaPlayer();
}
// Now set the datasource
mp.setDataSource(context, audio);
mp...
mp.prepare();
mp.start();
Ideally though you should call prepareAsync and have a callback onPrepare() call the actual mediaPlayer.start so that prepare does not block the main thread.
mp.setOnPreparedListener(this);
mp.setDataSource(..)
mp.prepareAsync();
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
Make the MediaPlayer mp global variable private static. Better yet use Singleton instead of global
You could review the state diagram here
then review an implementation of that logic for recycle media player in the
media sample you can find in your SDK installation:
$SDK/.../src/com/android/sample/apis/media/MediaPlayerDemo_Video.java
and follow how the sample resets the player state before using it again

Can't play MediaPlayer onCreate

I have an app where I want, as soon as it starts, a little background music (opa gangam style!) to be played (from the sd card). I use the code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MediaPlayer mp = new MediaPlayer();
String filePath = Environment.getExternalStorageDirectory().getPath() + "/mymusic/gangamstyle.mp3";
try {
mp.setDataSource(filePath);
} catch (IOException e) {
e.printStackTrace();
}
try {
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
But when I test it, no music is played. I see everything is ok however. What could I do wrong? Thanks a lot
You have to use setOnPreparedListener in order to know when the media player is ready to play:
MediaPlayer player = new MediaPlayer();
player.setDataSource(filePath);
player.setVolume(100, 100);
player.setLooping(false);
player.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
mp.start();
}
});
player.prepare();
There is some problem in your file path. Media player gives this kind of error when the file path is not correct. So, Please check your file path and then try it.

Wait for a sound to end playing. Is this correct?

In my application I need to play a sound in different moments and wait for it to end before doing anything else. Right now I have this code for playing sound:
private MediaPlayer mPlayer = null;
private boolean playSound(){
mPlayer = new MediaPlayer();
try{
mPlayer.setDataSource(openFileInput(fileName).getFD());
mPlayer.prepare();
mPlayer.start();
} catch (Exception e){
e.printStackTrace();
Log.e("player", "error playing sound: "+fileName);
return false;
}
while(mPlayer.isPlaying());
mPlayer.release();
mPlayer = null;
return true;
}
It's not working as I expected: when changing an image before playing the sound the change happens after the sound is played (I suppose it's for the thread queue or something like this)
I don't know if this is a bad solution or if there is any better solution for my case:
the sound playing must start after all previous work is finished.
the app must not do any other work while playing the sound.
the code to execute after the sound playing is not always the same.
You should implement a completion listener:
public class myclass extends .... implements OnCompletionListener, ... {
private int nextAction; // not the smatest solution, but good enough :)
...
private boolean playSound(next){
nextAction = next;
mPlayer = new MediaPlayer();
try{
mPlayer.setDataSource(openFileInput(fileName).getFD());
mPlayer.prepare();
mPlayer.setOnCompletionListener(this);
mPlayer.start();
} catch (Exception e){
e.printStackTrace();
Log.e("player", "error playing sound: "+fileName);
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
// do your stuff, destroy the mplayer, if needed
switch(nextAction){
case ACTION1: ...; break;
case ACTION2: ...; break; //..and so on
}
}

Play a sound from res/raw

I m making an app which is supposed to play a few sounds with the mediaPlayer.
This is the code i use :
String[] name = {"sonar_slow","sonar_medium","sonar_fast"};
String link = "/res/raw/" + name[state-1] + ".mp3";
try {
player.setDataSource(link);
player.prepare();
player.start();
} catch(Exception e) {
e.printStackTrace();
}
I also tried this :
if(state==1){
player.create(this, R.raw.sonar_slow);
}else if(state==2){
player.create(this, R.raw.sonar_medium);
}else if(state==3){
player.create(this, R.raw.sonar_fast);
}
player.start();
But none of the above is working. My app is not crashing but the sound is not playing.
Any ideas ?
There are two problems.
Problem 1
You cannot reference resources inside your projects /res/raw directory in this fashion. The file "/res/raw/sonar_slow.mp3" in your project directory is not stored in "/res/raw/sonar_slow.mp3" in your apk. Instead of the following:
MediaPlayer mp = MediaPlayer.create(this);
mp.setSource("sonar_slow");
You need to use
MediaPlayer mp = MediaPlayer.create(this, R.raw.sonar_slow);
Problem 2
The following is wrong: it calls a static method that does not modify the player.
player.create(this, R.raw.sonar_slow);
You should instead call
player = MediaPlayer.create(this, R.raw.sonar_slow);
Full solution
Below is a reusable AudioPlayer class that encapsulates MediaPlayer. This is slightly modified from "Android Programming: The Big Nerd Ranch Guide". It makes sure to remember to clean up resources
package com.example.hellomoon;
import android.content.Context;
import android.media.MediaPlayer;
public class AudioPlayer {
private MediaPlayer mMediaPlayer;
public void stop() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
public void play(Context c, int rid) {
stop();
mMediaPlayer = MediaPlayer.create(c, rid);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
stop();
}
});
mMediaPlayer.start();
}
}
How to play a file with MediaPlayer:
MediaPlayer mp = MediaPlayer.create(this, R.raw.mysound); // sound is inside res/raw/mysound
mp.start();
This is a simple example of how to play a sound with the Android MediaPlayer.
You have two buttons hat each play a different sound. The selecting of the sound and actually playing it is done in the manageSound() method. The sounds "hello", "goodbye" and "what" are in the res/raw directory:
MediaPlayer mp = null;
String hello = "Hello!";
String goodbye = "GoodBye!";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button buttonHello = (Button) findViewById(R.id.idHello);
buttonHello.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
managerOfSound(hello);
} // END onClick()
}); // END buttonHello
final Button buttonGoodBye = (Button) findViewById(R.id.idGoodBye);
buttonGoodBye.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
managerOfSound(goodbye);
} // END onClick()
}); // END buttonGoodBye
} // END onCreate()
protected void manageSound(String theText) {
if (mp != null) {
mp.reset();
mp.release();
}
if (theText.equals(hello))
mp = MediaPlayer.create(this, R.raw.hello);
else if (theText.equals(goodbye))
mp = MediaPlayer.create(this, R.raw.goodbye);
else
mp = MediaPlayer.create(this, R.raw.what);
mp.start();
}
Taken from here: http://www.badprog.com/android-mediaplayer-example-of-playing-sounds
Furthermore, I would strongly recommend using SoundPool instead of MediaPlayer, for better Performance and usability.
http://developer.android.com/reference/android/media/SoundPool.html
Please also check if your sound is muted - I know this sounds stupid, but it happens to the best of us ;)
You need to do it like this :
try{
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
Make sure your only playing when the file has finished preparing.

Categories

Resources