2013-07-29 86 views
14

Tôi mới sử dụng Android và tôi phải tạo MediaPlayer để phát nhạc âm thanh. Khi bắt đầu bài hát hoạt động của tôi bắt đầu phát. Nhưng khi tôi thay đổi hướng trên màn hình giả lập MediaPlayer được khởi động lại và một âm thanh khác bắt đầu phát. Làm thế nào tôi có thể tránh nó?Cách phát âm thanh liên tục trong khi các thay đổi định hướng trong Android?

Đây là mã của tôi:

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


     } 
    } 

} 

Và tôi đã thực hiện một số thay đổi trong tập tin manifest.xml.

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

và tạo thư mục bố cục.

Tại sao nhạc phát lại hai lần?

Trả lời

5

Khi chúng tôi khai báo phương tiện truyền thông dưới dạng biến tĩnh thì chỉ có một phiên bản của mp sẽ tồn tại. Giả sử định hướng Hoạt động của chúng ta thay đổi ngay bây giờ, Mọi thứ sẽ được tái tạo trên sự thay đổi định hướng nhưng biến Mp sẽ không được tạo lại vì thuộc tính tĩnh. Bằng cách này, chúng ta chỉ cần thực hiện một điều kiện

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

trong phương pháp của chúng tôi onCreate(), điều này sẽ kiểm tra xem âm nhạc đã được chơi hay không, nếu chơi của nó sau đó nếu điều kiện sẽ không cho phép ứng dụng để bắt đầu nghe nhạc một lần nữa. và nếu Nhạc không phát thì điều kiện sẽ cho phép ứng dụng khởi động lại nhạc.


Đây là mã cập nhật của bạn:

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

tôi biết về nó hoạt động. Cảm ơn, –

+0

Ứng dụng của tôi bị lỗi. – tazeenmulani

+1

mô tả lỗi ???? –

0

Khi bạn thay đổi hoạt động định hướng bị hủy và được tạo lại.

Bạn có thể lưu tiến trình thực tế của video trong onSaveInstanceState() và nhận dữ liệu đã lưu trong onRestoreInstanceState() từ Bundle, sau đó bạn có thể bắt đầu phát với dữ liệu tiến trình hoặc từ đầu nếu có không có dữ liệu nào được lưu.

+0

làm thế nào tôi có thể biết ở chế độ portriat hoặc là tôi phải phát video hay không ... bcause nếu người dùng tạm dừng video ở chế độ ngang thì nó sẽ tạm dừng khi video đang phát thì sẽ phát .... – Erum

3

Đối với các tác vụ như thế này, bạn nên sử dụng Service vì nó sẽ không được khởi tạo lại khi định hướng thay đổi.

1

Trình phát đa phương tiện cũng sẽ phát nhạc nếu hoạt động không ở trên cùng. Vì vậy, bạn nên sử dụng một dịch vụ tốt hơn, sau đó độc lập với hướng màn hình và những thứ khác:

Bắt đầu đọc http://developer.android.com/guide/components/services.html cẩn thận. Đặc biệt là START_STICKY rất quan trọng đối với dịch vụ trình phát đa phương tiện.

0

Ngoài việc sử dụng 'Dịch vụ', một giải pháp khác sẽ là triển khai phương pháp 'onOrientationChange' trong hoạt động của bạn. Tương tự phải được áp dụng cho tệp kê khai của hoạt động dưới dạng 'android: configChanges = "orientation | keyboardHidden"'; mà bạn đã làm.

Trong phương thức 'onOrientationChange'. có được vị trí chơi hiện tại và đưa nó cho đối tượng trình phát media và phát lại.

Bằng cách này, nó sẽ không tạo đối tượng mới của trình phát phương tiện và sử dụng cùng với vị trí hiện tại.

7

đơn giản trả lời cho câu hỏi này.

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

Vì tôi cũng đã vật lộn với vấn đề này nhiều lần, tôi đã quyết định tạo POC để tham chiếu. Ví dụ này sử dụng cờ configChanges và xử lý thay đổi kích thước theo cách thủ công. Nó hoạt động khá tốt IMHO

https://github.com/caspercba/POCMediaPlayerRotation

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



} 
0

Bạn có chắc chắn rằng bạn đặt

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

ở đúng nơi? bạn cần phải đặt nó trong hoạt động của máy nghe nhạc của bạn không bất kỳ hoạt động nào khác hoặc bên ngoài hoạt động .. Như một ví dụ tôi sử dụng nó như thế này trong manifest của tôi:

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

và nó hoạt động .. hy vọng nó giúp ..

1

Vì vậy, tôi vật lộn với điều này trong một thời gian, nhưng cuối cùng tôi đã tìm ra. Những gì bạn muốn làm là làm cho Mediaplayer của bạn trở thành một biến thành viên tĩnh của lớp, tương tự như câu trả lời hàng đầu ở đây. Tuy nhiên, điểm yếu mà bạn muốn tránh là sử dụng phương thức create() "thuận tiện". Điều này thực sự tạo ra một thể hiện mới của mediaplayer mỗi khi nó được gọi, ngay cả khi nó là tĩnh. Những gì bạn muốn làm thay vào đó là một cái gì đó như thế này:

static MediaPlayer m = new MediaPlayer(); 

Bây giờ bất cứ nơi nào trong mã của bạn, bạn muốn tạo ra các máy nghe nhạc, làm một cái gì đó như thế này:

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

Điểm của việc này là tạo (), trong khi thuận tiện, thực sự là chỉ tốt đẹp khi bạn không thay đổi định hướng bao giờ, bởi vì nó sẽ tiếp tục tạo ra các trường hợp mới và nhanh chóng sử dụng bộ nhớ. Tạo một thành viên tĩnh và tái sử dụng nó mỗi khi onCreate() được gọi là sạch hơn và đơn giản hơn nhiều. Reset() đặt người chơi ở trạng thái chính xác để nó được sử dụng lại.

Các vấn đề liên quan