Как воспроизводить звук непрерывно при изменении ориентации на Android?

Я новичок в Android, и мне нужно создать MediaPlayer для воспроизведения аудио-музыки. Когда начнется игра, начнется игра. Но когда я меняю ориентацию на экране своего эмулятора, MediaPlayer повторно инициализируется, и начинает воспроизводиться другой звук. Как я могу избежать этого?

Вот мой код:

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();


        }
    } 

}

И я сделал некоторые изменения в файле Manifest.xml.

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

и создайте папку макета.

Почему музыка воспроизводится дважды?

Ответ 1

Когда мы объявляем mediaplayer как статическую переменную, тогда будет существовать только один экземпляр mp. Предположим, что наша ориентация активности меняется сейчас. Все будет воссоздано при изменении ориентации, но переменная Mp не будет воссоздана из-за статического свойства. Таким образом, мы просто делаем условие

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

в нашем методе onCreate(), это будет проверять, играет ли музыка или нет, если ее воспроизведение тогда, если условие не позволит программе снова запустить музыкальный проигрыватель. и если музыка не воспроизводится, то условие разрешит приложению перезапустить музыку.


Вот ваш код обновления:

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();


        }
    } 

}

Ответ 2

Самый простой ответ на этот вопрос.

@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);
}

Ответ 3

Для таких задач вы должны использовать Service, поскольку он не будет повторно инициализирован при изменении ориентации.

Ответ 4

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();



}

Ответ 5

Медиаплеер также должен воспроизводить музыку, если активность не находится сверху. Поэтому вам лучше использовать сервис, который затем не зависит от ориентации экрана и других вещей:

Начните внимательно читать http://developer.android.com/guide/components/services.html. Особенно START_STICKY важна для службы медиаплеера.

Ответ 6

Поэтому я долгое время боролся с этим, но я, наконец, понял это. То, что вы хотите сделать, это сделать ваш Mediaplayer статической переменной-членом класса, подобной верхнему ответу здесь. Тем не менее, ловушку, которую вы хотите избежать, использует "удобный" метод create(). Это фактически создает новый экземпляр медиаплеера каждый раз, когда он вызывается, даже если он статичен. Вместо этого вы хотите сделать следующее:

static MediaPlayer m = new MediaPlayer();

Теперь, где бы вы ни находились в своем коде, вы хотите создать плеер:

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();

Дело в том, что create(), хотя и удобен, действительно приятен, когда вы не меняете ориентацию когда-либо, потому что он будет продолжать создавать новые экземпляры и быстро использовать память. Создание одного статического члена и повторное использование его каждый раз, когда вызывается onCreate(), намного чище и проще. Reset() помещает игрока в правильное состояние для повторного использования.

Ответ 7

При изменении ориентации активность уничтожается и воссоздается.

Вы можете сохранить фактический ход видео в onSaveInstanceState() и получить сохраненные данные в onRestoreInstanceState() из Bundle, после чего вы можете начать игру с либо данными прогресса, либо с самого начала, если не было сохраненные данные.

Ответ 8

Помимо использования "Сервиса", еще одним решением было бы реализовать метод onOrientationChange в вашей деятельности. То же самое нужно применять для манифеста файла активности как 'android: configChanges = "orientation | keyboardHidden" '; которые вы уже сделали.

В методе onOrientationChange. получить текущую позицию воспроизведения и передать это объекту медиаплеера и снова воспроизвести.

Таким образом, он не будет создавать новый объект медиаплеера и будет использовать его с текущей позицией.

Ответ 9

Потому что я много раз боролся с этой проблемой, я решил создать POC для использования в качестве ссылки. В этом примере используется флаг configChanges и обрабатывается изменение размера вручную. Это хорошо работает IMHO

https://github.com/caspercba/POCMediaPlayerRotation

Ответ 10

Вы уверены, что положили

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

в нужном месте? вы должны ставить его в действие своего игрока не на какую-либо другую деятельность или вне своей деятельности. В качестве примера я использовал это в своем манифесте:

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

и он работает.. надеюсь, что это поможет..

Ответ 11

Вам нужно использовать этот код, и не забудьте android:configChanges="orientation|screenSize" добавить его в свою манифестную деятельность

@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);  
    }
}