I have some trouble getting the Seekbar to work, The first song that loads will not let me use the SeekBar, but when I load a secondary or third song the SeekBar will work for them. I tried initializing the SeekBar after the song Uri dataSource was loaded, however it still exhibited the same behavior.
Any ideas on how to get the SeekBar to work on the first song?
Thanks
...
public class MainActivity extends AppCompatActivity {
final int REQUEST_OPEN_FILE = 1;
MediaPlayer mediaPlayer = new MediaPlayer();
Uri audioFileUri;
/*SeekBar seekBar;*/
/*TextView SongProgress = findViewById(R.id.SongProgress);*/
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OPEN_FILE) {
if (resultCode == RESULT_OK) {
audioFileUri = data.getData();
SeekBar seekBar;
seekBar = findViewById(R.id.seekbar);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
seekBar.setProgress(progress);
mediaPlayer.seekTo(progress);
/*int Minutes=((progress/1000)/60);
int Seconds=((progress/1000)%60);
int time = Minutes + Seconds;
SongProgress.setText(time);*/
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.reset();
mediaPlayer.setDataSource(this, audioFileUri);
mediaPlayer.prepare();
mediaPlayer.start();
Toast.makeText(this, "Was Playing", Toast.LENGTH_SHORT);
}
else{
mediaPlayer.setDataSource(this, audioFileUri);
mediaPlayer.prepare();
mediaPlayer.start();
Toast.makeText(this, "Was not playing", Toast.LENGTH_SHORT);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
...
...
}
Ok, I got the seekbar progress to update with the song so that the seekbar tracks along the audio file while it is playing. It was a simple runnable with a handler which I've posted in the code here. You have to have a runnable loop to track through the song as it is playing to update the seekbar. Then you have to write a handler to call that runnable loop. One important thing to note if you don't add the Boolean if(fromUser) in the seekbar onchanged listener the thread will cause it to play back choppy because it is also updating the progress in relation to the seekBar update progress function.
SeekBar seekBar;
Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
seekBar = (SeekBar) findViewById(R.id.seekbar);
...
}
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OPEN_FILE) {
if (resultCode == RESULT_OK) {
audioFileUri = data.getData();
try {
if (mediaPlayer.isPlaying()) {
seekBar.setProgress(0);
mediaPlayer.reset();
mediaPlayer.setDataSource(this, audioFileUri);
mediaPlayer.prepare();
mediaPlayer.start();
seekBar.setMax(mediaPlayer.getDuration()); // Set the Maximum range of the
Toast.makeText(this, "Was Playing", Toast.LENGTH_SHORT);
} else {
seekBar.setProgress(0);
mediaPlayer.setDataSource(this, audioFileUri);
mediaPlayer.prepare();
mediaPlayer.start();
seekBar.setMax(mediaPlayer.getDuration()); // Set the Maximum range of the
/*seekBar.getVisibility();
seekBar.setVisibility(View.INVISIBLE);*/
Toast.makeText(this, "Was not playing", Toast.LENGTH_SHORT);
}
} catch (Exception e) {
e.printStackTrace();
}
int mediaPos = mediaPlayer.getCurrentPosition();
int mediaMax = mediaPlayer.getDuration();
seekBar.setMax(mediaMax); // Set the Maximum range of the
seekBar.setProgress(mediaPos);// set current progress to song's
handler.removeCallbacks(moveSeekBarThread);
handler.postDelayed(moveSeekBarThread, 1000);
}
}
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser) {
seekBar.setProgress(progress);
mediaPlayer.seekTo(progress);
}
else{}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if(mediaPlayer.isPlaying()){
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); //Looping the thread after 0.1 second
// seconds
}else if(mediaPlayer.getCurrentPosition() == mediaPlayer.getDuration()){}
}
};
Related
My SeekBar can work but then it can't auto-run the SeekBar progress
when I clicked on the SeekBar I will auto move to the position with an overlay player. and the runnable thread does not on the SeekBar
the line below is the code of my SeekBar
positionBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser && progress != 100) {
player.getDuration();
player.seekTo(progress);
positionBar.setProgress(progress);
Toast.makeText(getApplicationContext(), "seekbar progress: " + progress, Toast.LENGTH_SHORT).show();
}else {
progress = 0;
positionBar.setProgress(progress);
Song nextSong = songCollection.getNextSong(songId);
if(nextSong != null){
songId = nextSong.getId();
title = nextSong.getTitle();
artist = nextSong.getArtist();
fileLink = nextSong.getFileLink();
coverArt = nextSong.getCoverArt();
url = BASE_URL + fileLink;
displaySong(title,artist,coverArt);
stopActivities();
}
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//
Toast.makeText(getApplicationContext(),"seekbar touch started!", Toast.LENGTH_SHORT).show();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// player.seekTo(musicPostion);
Toast.makeText(getApplicationContext(),"seekbar touch stop!", Toast.LENGTH_SHORT).show();
}
}
);
new Thread(new Runnable() {
#Override
public void run() {
while(player != null){
try{
Message msg = new Message();
msg.what = player.getCurrentPosition();
handler.sendMessage(msg);
positionBar.setProgress(player.getCurrentPosition());
Thread.sleep(1000);
}catch (InterruptedException e){
}
}
}
}).start();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
int currentPosition = msg.what;
positionBar.setProgress(currentPosition);
}
};`
Just like a view holder has the method getAdapterPosition(), I want to write my own setAdapterPosition() for the view holder(which doesn't exist).
What am I working on?
Currently, I am working on a project wherein I have to list 10 songs in the form of a recycler view and then play them, if any particular song is clicked. Each list item contains the song name, a seek bar and a play button
I have implemented this part, by adding all the media player contros inside the adapter class.
What do I want?
Currently, this model used mediaPlayer.setLooping(true) so that as soon as a song finished, it kept looping till some other song is clicked for playing.
Now I want to extend this model to an "autoplay" version so that as soon as a song is finished, the next song is played
What is the problem?
The seekBar progress and playButton image transition to a pauseButton image were happening with the call
viewHolder.seekBar.setProgress(...)
viewHolder.playButton.setImageDrawable(...)
Since this was happening on the
viewHolder.itemView.setOnClickListener(...)
as soon as a new song was clicked, the seekBar and playButton image were being updated.
Now, when the song is completed, I don't want the user to click on the next song to play it. I want it to be autoplayed, but I am unable to understand, how do I change myViewHolder position accordingly.
Suppose Song 0 has finished playing and Song 1 has started playing, viewHolder.getAdapterPosition() still returns 0 instead of 1. Hence the seekBar & playButton of song 0 is being updated and not of song 1.
I want to be able to do something like this
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
int nextSongPosition, currentSongPosition;
currentSongPosition = viewHolder.getAdapterPosition();
if(currentSongPosition==(songs.size()-1)){
nextSongPosition = 0;
//do some miracle so that viewHolder.getAdapterPosition() now shows 0 instead of currentSongPosition
}else{
nextSongPosition = currentSongPosition + 1;
//do some miracle so that viewHolder.getAdapterPosition() now shows nextSongPosition instead of the currentSongPosition;
}
}
});
As clear from the question statement, I want to implement something similar to a setAdapterPosition() which doesn't exist.
EDIT 1
onBindViewHolder Code:
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, int i) {
Song song = songs.get(i);
viewHolder.itemView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
audioManager = (AudioManager) Objects.requireNonNull(context).getSystemService(Context.AUDIO_SERVICE);
if(mediaPlayer.isPlaying()){
pauseMediaPlayer(viewHolder);
}else{
StorageReference storageRef = FirebaseStorage.getInstance().getReference("Songs");
StorageReference dateRef = storageRef.child(song.getStoredAs());
dateRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
try {
mediaPlayer.setDataSource(uri.toString());
mediaPlayer.prepare();
viewHolder.seekBar.setMax(mediaPlayer.getDuration() / 1000);
mSeekbarUpdateHandler = new Handler();
mUpdateSeekbar = new Runnable() {
#Override
public void run() {
if (viewHolder.seekBar != null && mediaPlayer != null) {
try{
viewHolder.seekBar.setProgress(mediaPlayer.getCurrentPosition() / 1000);
mSeekbarUpdateHandler.postDelayed(this, 50);
} catch(IllegalStateException e){
Log.i("Exception",e.toString());
}
}
}
};
viewHolder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser && mediaPlayer != null)
mediaPlayer.seekTo( progress * 1000);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
startMediaPlayer(viewHolder);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
Log.i("Song Loading Error", exception.toString());
}
});
}
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
int nextSongPosition, currentSongPosition;
currentSongPosition = viewHolder.getAdapterPosition();
if(currentSongPosition==(songs.size()-1)){
nextSongPosition = 0;
//do some miracle so that viewHolder.getAdapterPosition() now shows 0 instead of currentSongPosition
}else{
nextSongPosition = currentSongPosition + 1;
//do some miracle so that viewHolder.getAdapterPosition() now shows nextSongPosition instead of the currentSongPosition;
}
}
});
}
pauseMediaPlayer(..) & startMediaPlayer(..) Code:
private void pauseMediaPlayer(ViewHolder viewHolder) {
int result = audioManager.requestAudioFocus(this, AudioManager.USE_DEFAULT_STREAM_TYPE, AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
isSongPlaying = false;
viewHolder.playButton.setImageResource(R.drawable.play_button);
if (mediaPlayer != null) {
mediaPlayer.pause();
}
}
}
private void startMediaPlayer(ViewHolder viewHolder) {
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
isSongPlaying = true;
viewHolder.playButton.setImageResource(R.drawable.pause_button);
if (mediaPlayer != null) {
//mediaPlayer.setLooping(true);
mediaPlayer.start();
}
mSeekbarUpdateHandler.postDelayed(mUpdateSeekbar, 0);
}
}
I want to play 6 different sounds triggered by 6 different buttons in background, so that if the app is on background the sound keeps playing.
When one sound is already playing, pressing another button will stop it and play its own sound,
Tapping the same button 2K times it stops, 2K+1 times: starts again.. (K is a non-null integer)
All of the code is done and seems to be working correctly, except that the player stops after one and a half minute. (This is not because of low memory)
Can anyone please tell me what am I doing wrong?
public class PlayService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
int btnId = intent.getExtras().getInt("ID");
Toast.makeText(this, "onStart service" + btnId, Toast.LENGTH_SHORT).show();
selectResId(btnId);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show();
if (player != null) {
player.stop();
player.release();
}
player = null;
}
#Override
public void onLowMemory() {
super.onLowMemory();
Toast.makeText(this, "Low mem", Toast.LENGTH_SHORT).show();
}
private void selectResId(int resId){
switch (resId){
case 1: playMediaFromResource(R.raw.number_one);
case 2: playMediaFromResource(R.raw.number_two);
case 3: playMediaFromResource(R.raw.number_three);
case 4: playMediaFromResource(R.raw.number_four);
case 5: playMediaFromResource(R.raw.number_five);
case 6: playMediaFromResource(R.raw.number_six);
default: break;
}
}
private void playMediaFromResource(int resId) {
Uri mediaPath = Uri.parse("android.resource://" + getPackageName() + "/" + resId);
try {
player.setDataSource(getApplicationContext(), mediaPath);
player.setLooping(true);
player.prepare();
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And the MainActivity:
public class MainActivity extends AppCompatActivity {
private Button btnStart1;
private Button btnStart2;
private Button btnStart3;
private Button btnStart4;
private Button btnStart5;
private Button btnStart6;
private Intent intent;
private int previousID = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewsByIds();
setOnClickListeners();
}
private void findViewsByIds() {
btnStart1 = findViewById(R.id.btn_start_1);
btnStart2 = findViewById(R.id.btn_start_2);
btnStart3 = findViewById(R.id.btn_start_3);
btnStart4 = findViewById(R.id.btn_start_4);
btnStart5 = findViewById(R.id.btn_start_5);
btnStart6 = findViewById(R.id.btn_start_6);
}
private void setOnClickListeners() {
btnStart1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(1);
}
});
btnStart2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(2);
}
});
btnStart3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(3);
}
});
btnStart4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(4);
}
});
btnStart5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(5);
}
});
btnStart6.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(6);
}
});
}
private void checkIntentState(int ID) {
if (intent == null) {
createNewIntent(ID);
} else {
stopService(intent);
intent = null;
if (ID != previousID) {
createNewIntent(ID);
}
}
}
private void createNewIntent(int ID) {
intent = new Intent(MainActivity.this, PlayService.class);
intent.putExtra("ID", ID);
startService(intent);
previousID = ID;
}
}
I want to answer to my own question just in case anyone else runs into the problem.
It turns out, that Android added some new features (restricted access to background resources for battery life improvement purposes since Oreo(i.e. Android 8.0+ || API level 26)).
As the documentation says:
"Apps that are running in the background now have limits on how freely they can access background services."
So, in this case we will need to use foreground services.
I have been working on an audio stream app but I need clarity on a variety of issues. First of all, I am playing the audio file with a bound service and I have a play-pause button` that toggles player on and off.
These are the issues i have with my code:
Media player gets instantiated each time I press play button but that is not what because I also need to pause playback when needed.
Playback is very slow. It takes a lot of time for the mediaplayer to prepare and stream.
Sometimes media player gets initialized twice if the user vigorously toggles the playpause button.
Here the code:
Music Player Activity
btn_play_pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!playPause) {
btn_play_pause.setImageResource(R.drawable.pause_button);
if (initialStage) {
musicService.play();
Toast.makeText(MusicPlayerActivity.this, "Playing started", Toast.LENGTH_SHORT).show();
}
playPause = true;
} else {
btn_play_pause.setImageResource(R.drawable.play_button);
Toast.makeText(MusicPlayerActivity.this, "Playing paused", Toast.LENGTH_SHORT).show();
playPause = false;
musicService.pause();
}
}
});
}
Music Service
public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener{
private final IBinder mBinder = new MusicService.AudioBinder();
private MediaPlayer mediaPlayer;
private AudioManager audioManager;
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener;
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "Network Error", Toast.LENGTH_LONG).show();
mediaPlayer.reset();
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
try {
mp.setDataSource(stream_source);
mp.prepareAsync();
mp.start();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
mediaPlayer = mp;
}
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer = mp;
}
public class AudioBinder extends Binder {
public MusicService getService() {
//Return this instance of RadioBinder so clients can call public methods
return MusicService.this;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
switch (intent.getAction()) {
case Constants.ACTION_STOP_AUDIO_SERVICE:
hideNotification();
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("close_activity",true);
this.startActivity(i);
break;
case Constants.ACTION_STREAM_PLAY_PAUSE:
if (isPlaying()) {
pause();
showNotification();
stopForeground(false); // stop making it a foreground service but leave the notification there
} else {
play();
showNotification();
}
break;
default:
break;
}
}
return START_STICKY;
}
#Override
public void onCreate() {
setUpAudioManager();
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
}
public void play() {
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnErrorListener(this);
showNotification();
}
public void pause() {
if(mediaPlayer.isPlaying()) {
mediaPlayer.pause();
audioManager.abandonAudioFocus(audioFocusChangeListener);
}
showNotification();
}
public boolean isPlaying() {
return mediaPlayer != null && (mediaPlayer.isPlaying());
}
#Override
public boolean stopService(Intent name) {
if (mediaPlayer != null){
mediaPlayer.release();
mediaPlayer = null;
}
return super.stopService(name);
}
public void hideNotification() {
stopForeground(true);
}
#Override
public void onDestroy() {
if(mediaPlayer!= null){
mediaPlayer.release();
}
super.onDestroy();
}
public void releaseTrack(){
if(mediaPlayer!= null){
mediaPlayer.release();
}
}
}
My application contains one mediaplayer with one (play/pause) button in audio.xml , but the problem is that I am not able to find right code to stop MediaPlayer before the page gets destroyed and because of that the app crashes when i log in audio page (xml) and quit without running mediaplayer , here is the code i used:
public class audio extends Langue implements Runnable,
OnClickListener, OnSeekBarChangeListener {
private SeekBar seekBar;
private Button startMedia;
// private Button stopMedia;
private MediaPlayer mp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.audio);
seekBar = (SeekBar) findViewById(R.id.seekBar1);
startMedia = (Button) findViewById(R.id.button1);
//stopMedia = (Button) findViewById(R.id.button2);
startMedia.setOnClickListener(this);
//stopMedia.setOnClickListener(this);
seekBar.setOnSeekBarChangeListener(this);
seekBar.setEnabled(false);
}
public void run() {
int currentPosition = mp.getCurrentPosition();
int total = mp.getDuration();
while (mp != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekBar.setProgress(currentPosition);
}
}
public void onClick(View v) {
if (v.equals(startMedia)) {
if (mp == null) {
mp = MediaPlayer.create(getApplicationContext(), R.raw.espoir);
seekBar.setEnabled(true);
}
if (mp.isPlaying()) {
mp.pause();
startMedia.setText("Play");
} else {
mp.start();
startMedia.setText("Pause");
seekBar.setMax(mp.getDuration());
new Thread(this).start();
}
}
/* if (v.equals(stopMedia) && mp != null) {
if (mp.isPlaying() || mp.getDuration() > 0) {
mp.stop();
mp = null;
startMedia.setText("Play");
seekBar.setProgress(0);
}
}
*/
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
try {
if (mp.isPlaying() || mp != null) {
if (fromUser)
mp.seekTo(progress);
} else if (mp == null) {
Toast.makeText(getApplicationContext(), "Media is not running",
Toast.LENGTH_SHORT).show();
seekBar.setProgress(0);
}
} catch (Exception e) {
Log.e("seek bar", "" + e);
seekBar.setEnabled(false);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
// stop song
#Override
protected void onPause(){
super.onPause();
mp.stop();
finish();
}
}
Do something like this into the onPause() method for preventing crash
try{
mp.stop();
} catch(Exception e) {
}
finish();