I have a audio player app, where there is a Main activity that shows 3 audio sample urls. On click on one, it goes to a Details Activity, which has a play and pause button, to start and pause the audio.
My problem is that, when I start the Main activity, and say click on audio 1, I hit play on Details activity. This starts the MediaPlayer and the audio starts to play. When I go back to the Main activity, the audio is still playing, which is what I want. Now, when I click on audio 1 again, and go to Details Activity and hit play again, there seems to be a new MediaPlayer starting the audio. So I have 2 tracks playing together!
Is there a way I can have only one MediaPlayer instance at any given time?
Thanks
Chris
You should consider the Singleton pattern. Make a class MyPlayer that has a static method getMediaPlayer() that returns the same instance of MediaPlayer each time called.
Singleton Class
public final class MySingleton extends Application {
static MediaPlayer instance;
public static MediaPlayer getInstance() {
if (instance == null)
{
instance = new MediaPlayer();
}
return instance;
}
}
Adapter Where your List
Initialize Your Singleton Class One time in Constructor
private static MediaPlayer mMediaPlayer = MySingleton.getInstance();
if (mMediaPlayer.isPlaying()) {
try {
mMediaPlayer.reset();
mMediaPlayer.stop();
mMediaPlayer.setDataSource(mainActivity, Uri.parse(songsarraylist.get(position).getPath()));
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (Exception e) {
Toast.makeText(mainActivity, "Catching", Toast.LENGTH_SHORT).show();
}
} else {
try {
mMediaPlayer.setDataSource(mainActivity, Uri.parse(songsarraylist.get(position).getPath()));
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
Related
I am developing a music player on android and the app has two activities (MainActivity and PlayActivity). In the MainActivity I have a listview with a list of songs and in the PlayActivity I have a button to listen and pause the music. The problem is that when go back to MainActivity and I select a new song from the listview, the first one keeps playing on background while the second one also starts playing. How can I stop the first song when I select a new one?
(I don't want to stop mediaplayer onBackPressed, I just want to stop the music when another song it's selected from listview and play a fresh song in PlayActivity)
EDIT: I'm using AsyncTask to start mediaplayer on PlayActivity: mp.prepareAsync();
You could try to stop MediaPlayer when onBackPressed()
MediaPlayer mp ; // mp is your MediaPlayer
#Override
public void onBackPressed() {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
super.onBackPressed();
}
private void playMusic() {
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
mp.release();
MediaPlayer copyMp = new MediaPlayer();
try {
copyMp.setDataSource("/path");
mp = copyMp;
mp.prepare();
mp.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
From here
MediaPlayer is not thread-safe. Creation of and all access to player
instances should be on the same thread.
That means you have to maintain one media player instance throughout your whole application(As per your requirement). I don't know how you implemented the media player(Service/AsyncTask etc.). When you select a new song, you need to access that instance and replace the existing song with the selected one.
I have problems with my app because multimedia sound is heard when the app is in background
I have defined my Media player like this;
private void playLocalAudio(int R1)throws Exception
{
MediaPlayer mediaPlayer = MediaPlayer.create(this,R1);
mediaPlayer.start();
}
For calling PlayLocalAudio I do:
try{
playLocalAudio(R.raw.fartw1);
}
catch (Exception e) {
e.printStackTrace();
}
}});
But I am not able to call correctly MediaPlayer.Stop()
I am trying:
public void onPause()
{
super.onPause();
mediaplayer.stop();
}
But it doesn't work. Could you help me?
I'm guessing that your code has a class variable mediaPlayer that's not visible in your example. In that case you have variable shadowing, because you're instantiating a new mediaPlayer in playLocalAudio and that instance is not visible inside the pause method. So stop is never called. Remove the MediaPlayer class name from the declaration in playLocalAudio.
In my onCreate method i check to see whether a media player is playing and if it is a shut it down
if(mediaplayer.isPlaying()==false)
try {
playAudio(path);
} catch (Exception e) {
e.printStackTrace();
}else{
mediaplayer.stop();
mediaplayer.reset();
}
primarySeekBarProgressUpdater();
}
my play audio method is
private void playAudio(String url) throws Exception{
mediaplayer.setDataSource(url);
mediaplayer.prepare();
mediaplayer.start();
}
i also initialize my media player before the onCreate method. The problem is my media player won't shut down instead when a user clicks on a new song in the list view class it creates this class and plays both media players at the same time the old one continues playing.
Ok, so I assume you have a ListActivity with full of songs, and users click to any of those, it will move to a new Activity to play the song, in which the song information is passed through the Intent.
First of all, you need to read and remember Activity Lifecycle: http://developer.android.com/reference/android/app/Activity.html
Secondly, to your problem, according to the lifecycle, everytime users click to a song on the list, then it will create a new Activity to play the song, that means it creates a new MediaPlayer object as well. Hence, you can see many songs playing as much as you select the songs from the list.
What you need to do is to handle the MediaPlayer object when you close the music-playing screen to return to your song list.
MediaPlayer mPlayer = null;;
public void onCreate() {
// init mediaplayer here
mPlayer = ...
}
public void onDestroy() {
// release object
if( mPlayer != null ) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
}
I have created a list of songs on click on the song i am able to play the song using MedaiPlayer. While one song is playing if the user clicks another song then i am stopping the media player and starting the player again. But I am getting illegalstateexception in reset(). Here is the code where I am getting the exception. How to stop a player properly? also why am i getting this exception. How to avoid it?
public void stopPlayer() {
try {
if (player != null) {
// Log.e("Trying to Stop "," Player ");
player.stop();
player.release();
player.reset();// causes IllegalstateException
player = null;
}
} catch (Exception e) {
player = null;
playerStatus = false;
e.printStackTrace();
}
}
try this :
player.reset();
player.release();
and also have a look at media player state diagram.
If you want to play again ,then use player.reset(),
player.release() means that it releases the player object so you have to re-intialise the player. So first you use reset() and then release(). release() is used when your player object no longer working. When your activity destroys release() method to be used for good practice.
Whenever you want to stop it:
if(player!=null)
{
if(player.isPlaying())
player.stop();
player.reset();//It requires again setDataSource for player object.
}
Whenever your player no longer to be needed:
if(player!=null)
{
if(player.isPlaying())
player.stop();
player.reset();//It requires again setDataSource for player object.
player.release();
player=null; // fixed typo.
}
Though the accepted answer works, This is a better way to achieve the task
private void stopSong() {
if(mediaPlayer!=null) {
if(mediaPlayer.isPlaying()) {
mediaPlayer.reset();// It requires again setDataSource for player object.
mediaPlayer.stop();// Stop it
mediaPlayer.release();// Release it
mediaPlayer = null; // Initialize it to null so it can be used later
}
}
}
Are you planning on reusing the player again, or are you done with the player? If you're done with the player, call release() and not reset(). If you plan on reusing the player, call reset() and not release().
reset() resets the player to its uninitialized state.
release() frees all resources associated with the player.
The Media Player State Diagram shows, and also states:
Calling stop() stops playback and causes a MediaPlayer in the Started, Paused, Prepared or PlaybackCompleted state to enter the Stopped state.
Once in the Stopped state, playback cannot be started until prepare() or prepareAsync() are called to set the MediaPlayer object to the Prepared state again.
That means, that after calling stop(), we should call prepare() on the same audio file if we wish to play it again. Otherwise calling start() again won't do anything.
As prepare() might throw exception, we should wrap it in a try-catch block, like this:
public void stopAudio(View view) {
mplayer.stop();
try {
mplayer.prepare();
} catch (IOException e) {
Log.e("stopAudio", "Unable to prepare() mplayer after stop()", e);
}
}
I have a media player and everytime that this activity is called if there is a media player playing i want it to stop and the new media player start playing ... This is my audio player method
private void playAudio(String url) throws Exception{
mediaplayer.release();
mediaplayer.setDataSource(url);
mediaplayer.prepare();
mediaplayer.start();
}
I initialize the media player at the beginning of the class
private MediaPlayer mediaplayer = new MediaPlayer();
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.songplaying);
// Getting Our Extras From Intent
Bundle names = getIntent().getExtras();
// Getting Specific Data
path = names.getString("pathkeyword");
//Start Player
try {
playAudio(path);
} catch (Exception e) {
e.printStackTrace();
}
Everytime this is class is created it creates a new media player doesn't stop the other one and just plays both at the same time.
You may wish to look into onPause and kill the media player then. The problem is that there is no reference to the media player once it has been made a 2nd time. As a result, you start up your activity, play the music, but when you exit (e.g. press the HOME button) the media player has not been told to stop (it runs as a separate thread). When you reopen it, it will start a new media player on a new thread, producing two sounds.
To fix this, kill the media player properly when you exit. This will properly kill the media player when you quit the activity:
#Override
protected void onPause(){
super.onPause();
if(mediaplayer.isPlaying()){
try{
mediaplayer.stop();
}
catch(IllegalStateException){
Log.d("mediaplayer","Media player was stopped in an illegal state.");
}
}
}
If you wish to continue the music whilst the activity is not in the foreground, you need to use a Service.