tazeenmulani
tazeenmulani

Reputation: 592

How to play audio continuously while orientation changes in Android?

I'm new to Android and I have to create MediaPlayer for playing the audio music. When start my activity song starts playing. But when I change the orientation on my emulator screen MediaPlayer is reinitialized and another audio starts playing. How can I avoid it?

Here is my code:

public class Audio_Activity extends Activity {


MediaPlayer mp = null;


    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        if(isLaunched)
        {
            setContentView(R.layout.audio);
        }

        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        length = settings.getInt("TheOffset", 0);
        init();
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);
        playMusic();


        mp.setOnCompletionListener(new OnCompletionListener() 
        {

            @Override
            public void onCompletion(MediaPlayer arg0) 
            {
                // TODO Auto-generated method stub

            }
        });


    }

    private void playMusic() 
    {
        httpGetAsynchTask httpGetAsyncTask = new httpGetAsynchTask();
        httpGetAsyncTask.execute();
    }



    class httpGetAsynchTask extends AsyncTask<String,Integer, Void>
    {

        protected void onPreExdcute()
        {

        }

        @Override
        protected Void doInBackground(String... arg0)
        {
            // TODO Auto-generated method stub

            final SharedPreferences.Editor prefsEdit = prefs.edit();

            Log.e("Song is playing", "in  Mediya Player ");

            mp.setLooping(false);
            mp.start();
            int millisecond=mp.getDuration();
            Log.e("Song is playing", "in  Mediya Player " + millisecond);

            prefsEdit.putBoolean("mediaplaying", true);
            prefsEdit.commit();
            //btnChapter.setEnabled(false);

            return null;

        }

        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);
            btnChapter.setEnabled(false);
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Configuration config=getResources().getConfiguration();
        if(config.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            setContentView(R.layout.audio);
        }
        else if(config.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            setContentView(R.layout.audio);
        }
    }

    @Override
    public void onPause() {
        super.onPause();


        SharedPreferences.Editor prefsEdit = prefs.edit();
        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying)
        {
            mp.pause();
            int position = mp.getCurrentPosition();
            Log.e("Current ", "Position -> " + position);
            prefsEdit.putInt("mediaPosition", position);
            prefsEdit.commit();
        }
    }

    @Override
    protected void onResume() {

        super.onResume();

        mp.start();

        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying) {
            int position = prefs.getInt("mediaPosition", 0);
            mp.seekTo(position);
            // mp.start();


        }
    } 

}

And I have done some changes in Manifest.xml file.

< android:configChanges="orientation|screenSize|keyboard" >

and create layout-land folder .

Why is the music playing twice?

Upvotes: 16

Views: 14462

Answers (11)

Herry patel
Herry patel

Reputation: 39

You need to use this code an dont forget to android:configChanges="orientation|screenSize"add this in your manifest activity

@Override
public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(
   if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
     //if you are using mediaplayer than u need to mp.getCurrentPosition();
       int currentPosition = vv.getCurrentPosition();
       vv.seekTo(currentPosition);
   }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        int currentPosition = vv.getCurrentPosition();
        vv.seekTo(currentPosition);  
    }
}

Upvotes: 1

eric k atwood
eric k atwood

Reputation: 121

So I wrestled with this for quite a time, but I finally figured it out. What you want to do is make your Mediaplayer a static member variable of the class, similar to the top answer here. However, the pitfall you want to avoid is using the "convenient" create() method. This actually creates a new instance of the mediaplayer every time it is called, even if it is static. What you want to do instead is something like this:

static MediaPlayer m = new MediaPlayer();

Now wherever in your code you want to create the player, do something like this:

m.reset();

try{
        m.setDataSource(getApplicationContext(),Uri.parse("android.resource://com.example.app/" + R.raw.soundId));
        m.prepare();

}catch(java.io.IOException e){ }

m.seekTo(pos);
m.start();

The point of this is that create(), while convenient, is really only nice when you are not changing orientation ever, because it will keep creating new instances and quickly use up memory. Creating one static member and re-using it each time onCreate() is called is much cleaner and simpler. Reset() puts the player in the correct state for it to be re-used.

Upvotes: 3

Burcak Kam
Burcak Kam

Reputation: 261

Are you sure that you put

< android:configChanges="orientation|screenSize|keyboard" >

at the right place? you have to put it in the activity of your player not any other activity or outside the activity.. As an example I used it like this in my manifest:

<activity android:name=".PlayerActivity" android:label="@string/title_activity_player" android:noHistory="true" android:configChanges="orientation|screenSize"> </activity>

and it works.. hope it helps..

Upvotes: 1

anfd
anfd

Reputation: 121

public void onSaveInstanceState(Bundle savedInstanceState) {

    super.onSaveInstanceState(savedInstanceState);

    savedInstanceState.putInt("Position", mediaPlayer.getCurrentPosition());
    savedInstanceState.putBoolean("isplaying", mediaPlayer.isPlaying());

     if (mediaPlayer.isPlaying())
          mediaPlayer.pause();

}


@Override

public void onRestoreInstanceState(Bundle savedInstanceState) {

    super.onRestoreInstanceState(savedInstanceState);

    position = savedInstanceState.getInt("Position");
    mediaPlayer.seekTo(position);
     if (savedInstanceState.getBoolean("isplaying"))
         mediaPlayer.start();



}

Upvotes: 2

Gaspar de Elias
Gaspar de Elias

Reputation: 244

Because I've also struggled with this problem many times, I've decided to create a POC to be used as a reference. This example uses configChanges flag and handles the resizing manually. It works quite well IMHO

https://github.com/caspercba/POCMediaPlayerRotation

Upvotes: 0

Shabbir Dhangot
Shabbir Dhangot

Reputation: 9131

Simplest Answer for this question.

@Override
protected void onSaveInstanceState(Bundle outState) 
{
    outState.putInt("possition", mpbg.getCurrentPosition());
    mpbg.pause();
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) 
{
    int pos = savedInstanceState.getInt("possition");
    mpbg.seekTo(pos);
    super.onRestoreInstanceState(savedInstanceState);
}

Upvotes: 9

Ahmad Raza
Ahmad Raza

Reputation: 2850

When we declare mediaplayer as a static variable then only one instance of mp will exist. Suppose our Activity orientation changes now, Everything will be recreated on orientation change but Mp variable will not be recreated because of static property. In this way we just make a condition

if(mp!=null && !mp.isPlaying()){ 
    mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);
    playMusic(); 
} 

in our onCreate() method, this will check whether music is already playing or not, if its playing then if condition will not allow application to start music player again. and if Music is not playing then if condition will allow the application to restart the music.


Here is your update code:

public class Audio_Activity extends Activity {


static MediaPlayer mp = null;


    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        if(isLaunched)
        {
            setContentView(R.layout.audio);
        }

        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        length = settings.getInt("TheOffset", 0);
        init();
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        if(mp == null) 
        {
            initializeMP();
        }
        if(!mp.isPlaying())
        {
             playMusic();
        }

        mp.setOnCompletionListener(new OnCompletionListener() 
        {

            @Override
            public void onCompletion(MediaPlayer arg0) 
            {
                // TODO Auto-generated method stub

            }
        });


    }

    private void playMusic() 
    {
        httpGetAsynchTask httpGetAsyncTask = new httpGetAsynchTask();
        httpGetAsyncTask.execute();
    }

    public void initializeMP()
    {
          mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);

    }

    class httpGetAsynchTask extends AsyncTask<String,Integer, Void>
    {

        protected void onPreExdcute()
        {

        }

        @Override
        protected Void doInBackground(String... arg0)
        {
            // TODO Auto-generated method stub

            final SharedPreferences.Editor prefsEdit = prefs.edit();

            Log.e("Song is playing", "in  Mediya Player ");

            if(mp == null)
            {
                initializeMP()
            }
            mp.setLooping(false);
            mp.start();
            int millisecond=mp.getDuration();
            Log.e("Song is playing", "in  Mediya Player " + millisecond);

            prefsEdit.putBoolean("mediaplaying", true);
            prefsEdit.commit();
            //btnChapter.setEnabled(false);

            return null;

        }

        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);
            btnChapter.setEnabled(false);
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Configuration config=getResources().getConfiguration();
        if(config.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            setContentView(R.layout.audio);
        }
        else if(config.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            setContentView(R.layout.audio);
        }
    }

    @Override
    public void onPause() {
        super.onPause();


        SharedPreferences.Editor prefsEdit = prefs.edit();
        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying)
        {
            if(mp!=null)
            {
                 mp.pause();
            }
            int position = mp.getCurrentPosition();
            Log.e("Current ", "Position -> " + position);
            prefsEdit.putInt("mediaPosition", position);
            prefsEdit.commit();
        }
    }

    @Override
    protected void onResume() {

        super.onResume();
        if(mp == null)
        {
            initializeMP();
        }
        mp.start();

        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying) {
            int position = prefs.getInt("mediaPosition", 0);
            mp.seekTo(position);
            // mp.start();


        }
    } 

}

Upvotes: 4

Jayesh Elamgodil
Jayesh Elamgodil

Reputation: 1477

Besides using 'Service', one more solution would be to implement the 'onOrientationChange' method in your activity. Same has to be applied to manifest file of the activity as ' android:configChanges="orientation|keyboardHidden" '; which you have already done.

In 'onOrientationChange' method. get the current playing position and give that to media player object and play again.

By doing this, it will not create new object of media player and uses the same with current position.

Upvotes: 0

Philipp
Philipp

Reputation: 11833

A media player also should play music if the activity is not on top. So you better a use a service, which is then independent from screen orientation and other things:

Start reading http://developer.android.com/guide/components/services.html carefully. Especially START_STICKY is important for a media player service.

Upvotes: 1

Aballano
Aballano

Reputation: 1038

For tasks like this you should use a Service since it won't be re-initialized when the orientation changes.

Upvotes: 3

Mark McK
Mark McK

Reputation: 84

When you change orientation activity is destroyed and recreated.

You can save the actual progress of the video in onSaveInstanceState() and get the saved data in onRestoreInstanceState() from the Bundle, after that you can start the playing with either the progress data, or from the beginning if there was no data saved.

Upvotes: 0

Related Questions