【问题标题】:How to play audio continuously while orientation changes in Android?如何在Android中方向改变时连续播放音频?
【发布时间】:2013-07-29 07:12:04
【问题描述】:

我是 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" >

并创建 layout-land 文件夹。

为什么音乐播放两次?

【问题讨论】:

    标签: android audio android-mediaplayer


    【解决方案1】:

    这个问题的最简单答案。

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

    【讨论】:

      【解决方案2】:

      当我们将 mediaplayer 声明为静态变量时,只会存在一个 mp 实例。假设我们的 Activity 方向现在改变了,一切都将在方向改变时重新创建,但 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();
      
      
              }
          } 
      
      }
      

      【讨论】:

      • 找不到它的类异常,请检查src文件夹中Audio_Activity的拼写是否正确。并检查它 manifest.xml。
      • 还要检查包名。请确认您的包名与您在 manifest.xml 中定义的名称相似
      • 请在此处发布您的 menifest.xml 文件。谢谢,
      • 是的,这是正确的,现在请检查您的包名。您的包名称应为“com.tutorialmediaplayer”,在此包中放置此活动“Audio_Activity”。
      • 你应该创建一个新项目。在创建新项目时。设置活动名称“Audio_Activity”,将您的布局放入布局文件中。只需将我的代码放入 Audio_Activity.java。
      【解决方案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】:

          所以我为此苦苦挣扎了很长时间,但我终于弄明白了。您要做的是使您的 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() 将播放器置于正确的状态,以便重新使用。

          【讨论】:

            【解决方案6】:

            如果活动不在顶部,媒体播放器也应该播放音乐。所以你最好使用一个服务,它独立于屏幕方向和其他东西:

            开始仔细阅读http://developer.android.com/guide/components/services.html。 特别是START_STICKY 对于媒体播放器服务很重要。

            【讨论】:

              【解决方案7】:

              你确定你放了

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

              在正确的地方? 你必须把它放在你的玩家的活动中,而不是任何其他活动或活动之外.. 作为一个例子,我在清单中这样使用它:

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

              它有效..希望它有所帮助..

              【讨论】:

                【解决方案8】:

                当你改变方向时,Activity 被销毁并重新创建。

                您可以在 onSaveInstanceState() 中保存视频的实际进度,并从 Bundle 中获取 onRestoreInstanceState() 中保存的数据,之后您可以使用进度数据开始播放,如果没有则从头开始播放数据已保存。

                【讨论】:

                • 我怎么知道在纵向模式下我是否必须播放视频...因为如果用户在横向暂停视频,那么它应该保持暂停,而如果视频正在播放,那么它应该播放.. ..
                【解决方案9】:

                除了使用“服务”之外,另一种解决方案是在您的活动中实现“onOrientationChange”方法。同样必须应用于活动的清单文件 ' android:configChanges="orientation|keyboardHidden" ';你已经完成了。

                在“onOrientationChange”方法中。获取当前播放位置并将其提供给媒体播放器对象并再次播放。

                通过这样做,它不会创建媒体播放器的新对象并使用与当前位置相同的对象。

                【讨论】:

                  【解决方案10】:

                  因为我也多次为这个问题苦苦挣扎,所以我决定创建一个 POC 作为参考。此示例使用 configChanges 标志并手动处理大小调整。恕我直言,效果很好

                  https://github.com/caspercba/POCMediaPlayerRotation

                  【讨论】:

                    【解决方案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);  
                        }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-06-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-02-14
                      • 1970-01-01
                      相关资源
                      最近更新 更多