MediaPlayer onCompletionListener called while paused - android

My media player for some reason completes while it is paused. Now i have seen another post that said about it being async and 300ms difference and that I understand. But my main problem is that i have 20 seconds left on the video and while paused it finishes after the 20 seconds run out.
here is the relevant code that I might have messed up on:
private void initPlayer()
{
try {
if(videoFile != null)
{
afd = getAssets().openFd(videoFile);
instructionVideoPlayer = new MediaPlayer();
instructionVideoPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
instructionVideoPlayer.setDisplay(holder);
instructionVideoPlayer.prepare();
Log.i("Instruction Video", "videoPrepared");
instructionVideoPlayer.setOnCompletionListener(instructionVideoComplete);
instructionVideoPlayer.setOnPreparedListener(this);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
Log.i(this.toString(), "IOEXception");
e.printStackTrace();
//initPlayer();
} catch (Exception e)
{
Log.i("InitPlayer", e.getClass().toString());
e.printStackTrace();
}
restoreOverlayState();
}
The listeners:
MediaPlayer.OnCompletionListener instructionVideoComplete = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
Log.i("onCompletion", "called");
if(!videoFile.contentEquals(LangSelect.INSTRUCTION_05))
{
Intent returnIntent = new Intent();
returnIntent.putExtra(LangSelect.ACTION, LangSelect.GO_VIDEO_NEXT);
setResult(RESULT_OK, returnIntent);
continuePlaying = true;
toFinish();
}
else
toFinish();
}
};
public void onPrepared(MediaPlayer mediaPlayer)
{
playVideo();
}
the play and pause functions
private void playVideo()
{
instructionVideoPlayer.seekTo(pausedAt);
instructionVideoPlayer.start();
restoreOverlayState();
}
private void pauseVideo()
{
pausedAt = instructionVideoPlayer.getCurrentPosition();
instructionVideoPlayer.pause();
}
private void restoreOverlayState()
{
prefs = getSharedPreferences(SAVE_PREFS, Context.MODE_PRIVATE);
if(prefs.getBoolean(IS_PAUSED, false))
{
pauseOverlay.setVisibility(View.VISIBLE);
pauseVideo();
}
else
{
pauseOverlay.setVisibility(View.GONE);
}
}
Edit: this only happens on the Nexus S (2.3.3) one of the phones I am testing on. The other Galaxy S(Froyo) does not have this error.

I figured out what I was doing Wrong. the OnCompletionListener was being called. The problem was I was running 2 media players and setting the same onCompletionlistener to them accidentally as I was calling initPlayer twice. Once in surfaceCreated and again at the end of onResume(). Either the Galaxy S is messed up or it has weird error checking becasue this problem didnt show up there.

Related

Android MediaPlayer: Multiple sounds playing at the same time. My code is

I have searched and researched stackoverflow and google but can't find any answer to MY question. I've found other question and answers but that were related to sounds saved in the app but I'm creating an app which gets data from Parse server, so it gets mp3 files and display these in listview and than when an item is clicked it plays that track. But here comes the problem: When you play a sound and click on another one, the first just doesn't stop and the second starts to play.
I have tried with the following code but it's just not working.
Here's my code:
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final MediaPlayer mediaPlayer = new MediaPlayer();
final MediaPlayer scndmediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
scndmediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if (mediaPlayer.isPlaying()) {
Toast.makeText(getContext(), "First is playing", Toast.LENGTH_SHORT).show();
try {
mediaPlayer.stop();
scndmediaPlayer.setDataSource(audioFileURL);
scndmediaPlayer.prepare();
scndmediaPlayer.start();
//soundtoolbar.setTitle(name);
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IllegalStateException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
if (scndmediaPlayer.isPlaying()){
scndmediaPlayer.stop();
}
Toast.makeText(getContext(), "First is starting", Toast.LENGTH_SHORT).show();
mediaPlayer.setDataSource(audioFileURL);
mediaPlayer.prepare();
mediaPlayer.start();
soundtoolbar.setTitle(name);
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IllegalStateException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
playPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying() || scndmediaPlayer.isPlaying()) {
mediaPlayer.pause();
scndmediaPlayer.pause();
playPause.setBackground(getContext().getDrawable(R.drawable.ic_play_arrow_white_24dp));
} else {
mediaPlayer.start();
scndmediaPlayer.start();
playPause.setBackground(getContext().getDrawable(R.drawable.ic_pause_white_24dp));
}
}
});
}
});
I've created 2 mediaplayers with the code above and when user clicks the play button it first checks if any of the player is running.
I'm trying to achieve the following: When user clicks the play button it checks if the (1st) mediaPlayer is running or not. If it's running, it has just to stop it and launch (2nd) scndmediaPlayer or viceversa... if second is playing it stops that and launch first one. so it will create a loop: 1st is playing? User clicks another button stop first. Launch second. User clicks another button. First is playing? No. Second is playing? Yes. Stop the second and launch the first.
But can't find where is the problem in my code.
Please help me with this. I'm trying to resolve it from 2 days but I'm unable...
Thanks :)
EDIT: I tried using one MediaPlayer and do the following: Check if mediaplayer is playing! No it isn't playing. Start it. User clicks the button again and it stops the mediaplayer and start it with new audioFileUrl. BUT. MediaPlayer is forgetting that it's playing. Seems like it just starts the track and than forget and to check if it's true i set a Toast: when mediaplayer isn't playing the toast shows and it's showing every time I click a track in the list which means it forget that it has a track which is playing...
EDIT 2: I managed to do the following: It plays the track. User clicks another track. It stops the mediaplayer but doesn't play the new track. User click once again. It plays the new track. User clicks the new track and the app crashes...
EDIT 3: Posting my entire class:
public class MyAdapter extends ParseQueryAdapter<ParseObject> {
public Button playPause, next, previous;
public Toolbar soundtoolbar;
boolean isPlaying = false;
public MyAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("MyClass");
query.orderByDescending("createdAt");
return query;
}
});
}
#Override
public View getItemView(final ParseObject object, View v, final ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.activity_audio_files_item, null);
}
super.getItemView(object, v, parent);
final Button play = (Button) v.findViewById(R.id.play);
playPause = TabFragment1.playPause;
next = TabFragment1.next;
previous = TabFragment1.previous;
soundtoolbar = TabFragment1.soundtoolbar;
final ParseFile descr = object.getParseFile("audiofile");
final String name = object.getString("name");
final String audioFileURL = descr.getUrl();
final SlidingUpPanelLayout slidingUpPanelLayout = TabFragment1.spanel;
play.setText(name);
final MediaPlayer mediaPlayer = new MediaPlayer();
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isPlaying != true) {
Toast.makeText(getContext(), name+" is playing", Toast.LENGTH_SHORT).show();
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(audioFileURL);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
soundtoolbar.setTitle(name);
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
mediaPlayer.start();
isPlaying = true;
}
});
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (SecurityException e2) {
e2.printStackTrace();
} catch (IllegalStateException e3) {
e3.printStackTrace();
} catch (IOException e4) {
e4.printStackTrace();
} catch (NullPointerException e5) {
e5.printStackTrace();
}
} else {
mediaPlayer.stop();
Toast.makeText(getContext(), "Starting "+name, Toast.LENGTH_SHORT).show();
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync();
mediaPlayer.setDataSource(audioFileURL);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
soundtoolbar.setTitle(name);
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
mediaPlayer.start();
}
});
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (SecurityException e2) {
e2.printStackTrace();
} catch (IllegalStateException e3) {
e3.printStackTrace();
} catch (IOException e4) {
e4.printStackTrace();
} catch (NullPointerException e5){
e5.printStackTrace();
}
}
playPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
playPause.setBackground(getContext().getDrawable(R.drawable.ic_play_arrow_white_24dp));
} else {
mediaPlayer.start();
playPause.setBackground(getContext().getDrawable(R.drawable.ic_pause_white_24dp));
}
}
});
}
});
return v;
}
}
Somebody please help...
i suggest you to checkout SoundPool . İt ll helps you. And one more , may be you ll put media urls to array or something like this.And use one mediaPlayer By the way, you ll avoid from two mediaPlayer and avoid from memory leak.
http://developer.android.com/reference/android/media/SoundPool.html

Adding delay while Mediaplayer loops

Playing .wav file using MediaPlayer class. As I need to loop the Audio I've set .setLooping(true); . So obviously, the doubt is how do I add a delay each time the audio plays, say I want a delay of 5000 .
The answers to similar questions here doesn't work in my case. Any help would be appreciated. Here is my code:
Button Sample = (Button)findViewById(R.id.samplex);
Sample.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String filePath = Environment.getExternalStorageDirectory()+"/myAppCache/wakeUp.wav";
try {
mp.setDataSource(filePath);
mp.prepare();
mp.setLooping(true);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
}
});
You need to register 2 listeners (on completion and on error) and then you would need to delay next play in on completion callback. Reason for the error listener is to return true to avoid calling on completion event whenever there is an error - explanation here
private final Runnable loopingRunnable = new Runnable() {
#Override
public void run() {
if (mp != null) {
if (mp.isPlaying() {
mp.stop();
}
mp.start();
}
}
}
mp.setDataSource(filePath);
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
button.postDelayed(loopingRunnable, 5000);
}
});
mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {
...
return true;
});
mp.prepare();
// no need to loop it since on completion event takes care of this
// mp.setLooping(true);
Whenever your destruction method is (Activity.onDestroyed(), Fragment.onDestroy(), View.onDetachedFromWindow()), ensure you are removing the runnable callbacks, e.g.
#Override
protected void onDestroy() {
super.onDestroy();
...
button.removeCallbacks(loopingRunnable);
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
}
mp.release();
mp = null;
}
}

MediaController with MediaPlayer in Service getDuration error

In my app I have an audio player Activity which simply shows the current song title and album cover art together with a MediaController. I also have a Service which implements MediaController.MediaPlayerControl and which uses a MediaPlayer for playback.
In general everything works fine - the Activity binds to the Service and sets the MediaController to control the MediaPlayer.
The problem comes when starting a new song but ONLY when the MediaController is shown on the screen. If it is hidden or even if I leave the Activity using BACK and return to the home screen, the 'playlist' is processed without a problem. If the MediaContoller is visible, however, the player dies silently and the seek / progress bar shows a start and end time of 466:36:07 and logcat shows...
attempt to call getDuration without a valid mediaplayer
I don't get an unhandled exception stacktrace in logcat - just that message and MediaPlayer simply stops playing. I've Googled for the error and get nearly 3000 hits (most of which are for questions here on SO) but I can't find a situation which matches mine.
Relevant Activity code...
public class AudioPlayerActivity extends Activity
implements OnKeyListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.audio_player);
// Find views here
controller = new MyMediaController(this);
controller.setAnchorView(ll);
controller.setOnKeyListener(this);
}
#Override
protected void onResume() {
super.onResume();
mBound = bindService(new Intent(this, MusicPlayerService.class), mConnection, Context.BIND_AUTO_CREATE);
try {
getCurrentItem();
mediaFilename = currentItem.getTrackName();
coverArtPath = currentItem.getMediaArtUrl();
updateTrackDetails();
Intent playerServiceIntent = new Intent(this, MusicPlayerService.class);
startService(playerServiceIntent);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public void showMediaController() {
// Called by onTouchEvent(...)` when the screen is touched
if (mBound) {
controller.setMediaPlayer(mService);
controller.setEnabled(true);
controller.show(0);
}
}
}
The Service has the following code...
public class NDroidTEMusicPlayerService extends Service
implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener,
MediaPlayer.OnErrorListener,
AudioManager.OnAudioFocusChangeListener,
MediaPlayerControl {
private void setupMediaPlayer() {
...
try {
mMediaPlayer.setDataSource(trackUrl);
mMediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCompletion(MediaPlayer mp) {
stop();
mp.reset();
currentItem = playList.getNextItem(isRepeating);
Intent i = new Intent(MYAPP.ACTION_MYAPP_UPDATE_PLAY_VIEW);
i.putExtra("current_item", currentItem);
sendBroadcast(i);
setupMediaPlayer();
}
#Override
public int getDuration() {
int duration = 0;
if (mMediaPlayer != null)
duration = mMediaPlayer.getDuration();
return duration;
}
}

Working with MP3 sound in Processing for Android ( need to stop )

I am developing an app for Android devices using Processing 2.0, now I have playMP3(); function but need to stop the sound using stopMP3();. I tried everything but what is the best way to load an mp3 and play/stop using processing?, snd.stop(); within the stopMP3 function does not work...
import android.media.*;
import android.content.res.*;
...
MediaPlayer snd;
...
void setup()
{
MediaPlayer snd = new MediaPlayer();
}
...
void playMP3()
{
try {
AssetManager assets = this.getAssets();
AssetFileDescriptor fd = assets.openFd("loop1.mp3");
snd.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
snd.prepare();
snd.start();
snd.setLooping(true);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
void stopMP3(){
????
}
this is a simple sample for media player
private MediaPlayer m_Player;
//Start Play Function
private void startPlaying() {
m_Player = new MediaPlayer();
m_Player.setOnCompletionListener(onComplete);
try {
if(m_Player.isPlaying())
stopPlaying();
m_Player.setDataSource(m_FileName);
m_Player.prepare();
m_Player.start();
} catch (IOException e) {
}
}
//Stop Play Function
private void stopPlaying() {
m_Player.stop();
m_Player.reset();
m_Player = null;
}
//and this is onComplete Listener
MediaPlayer.OnCompletionListener onComplete = new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
stopPlaying();
}
};
i hope it's helping you

default notification sound only once

I have an application that uses the Orientation Sensor, and I want to play the default notification sound when the 'y' value is upper than 170 degrees. The thing is that the first time it happens it makes the sound correctly but twice (I suppose this is because of the time it takes to stablish canSound to false) and also after the first time it happens, if 'y' value is again upper than 170,it doesn't sound as I expected to happen.So, the question is, what am I doing wrong with mediaPlayer?
Thanks in advance.
P.D.:This is the part of code I have inside public void onSensorChanged(SensorEvent event) related with my problem.
if(y>170&&canSound)
{
canSound=false;
Uri defaultRingtoneUri=RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mediaPlayer = new MediaPlayer();
try
{
mediaPlayer.setDataSource(context, defaultRingtoneUri);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mediaPlayer.prepare();
mediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
mp.release();
}
});
mediaPlayer.start();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
else
{
if(y<170&&!canSound)
{
mediaPlayer.stop();
mediaPlayer.reset();
canSound=true;
}

Categories

Resources