Reputation: 592
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
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
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
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
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
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
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
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
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
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
Reputation: 1038
For tasks like this you should use a Service since it won't be re-initialized when the orientation changes.
Upvotes: 3
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