2015-01-15 20 views
4

我有興趣能夠「預緩衝」VideoView A而VideoView B正在播放。這可能嗎?如何預覽VideoView A而另一個VideoView B正在播放 - Android

  • 我有兩個VideoView的實例。
  • 在給定時間只顯示一個VideoView,佔用手機的整個屏幕。
  • 其目的是在從VideoView A和VideoView B切換時減少「黑屏」。
  • 該應用程序逐個播放視頻列表。

添加下面的代碼在2015年1月19日

下面的代碼抓住每個球員的MediaPlayer的一個參考。當MediaPlayer A開始渲染時,MediaPlayer B將調用stop(),release(),setDataSource(url),prepareAsync()。當MediaPlayer A完成時,媒體播放器B將調用start()。

public class PrebufferingActivity extends Activity { 
    private VideoView player1; 
    private VideoView player2; 
    private MediaPlayer mediaPlayer1; 
    private MediaPlayer mediaPlayer2; 
    public static final String URL_1 = "sample1.mp4"; 
    public static final String URL_2 = "sample2.mp4"; 

    public boolean FIRST_TIME = true; 

    @SuppressLint("NewApi") 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_prebuffering); 

     player1 = (VideoView) findViewById(R.id.videoPlayer1); 
     player2 = (VideoView) findViewById(R.id.videoPlayer2); 

     player1.setOnTouchListener(new OnTouchListener(){ 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       // TODO Auto-generated method stub 
       return false; 
      } 

     }); 

     player2.setOnTouchListener(new OnTouchListener(){ 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       // TODO Auto-generated method stub 
       return false; 
      } 
     }); 
     player1.setOnCompletionListener(new OnCompletionListener(){ 
      @Override 
      public void onCompletion(MediaPlayer mp)   { 
       mediaPlayer2.start(); 

       // Toggle visibility. Player1 is completed. Hide Player1. Show Player2. 
       player2.setVisibility(View.VISIBLE); 
       player1.setVisibility(View.INVISIBLE); 
      } 
     }); 

     player1.setOnInfoListener(new OnInfoListener(){ 
      @Override 
      public boolean onInfo(MediaPlayer mp, int what, int extra) 
      { 
       if(what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) 
       { 
        mediaPlayer2.stop(); 
        mediaPlayer2.release(); 

        try { 
         mediaPlayer2.setDataSource(URL_2); 
         mediaPlayer2.prepareAsync(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
       return false; 
      } 
     }); 

     player1.setOnPreparedListener(new OnPreparedListener(){ 
      @Override 
      public void onPrepared(MediaPlayer mp)   { 
       mediaPlayer1 = mp; 

       if(FIRST_TIME == true) { 
        mediaPlayer1.start(); 
        player1.requestFocus(); 
        FIRST_TIME = false; 
       } 
      } 
     }); 

     player2.setOnCompletionListener(new OnCompletionListener(){ 

      @Override 
      public void onCompletion(MediaPlayer mp)   { 
       mediaPlayer1.start(); 
       player1.requestFocus(); 

       // Toggle visibility. Player2 is completed. Hide Player2. Show Player1. 
       player1.setVisibility(View.VISIBLE); 
       player2.setVisibility(View.INVISIBLE); 
      } 
     }); 

     player2.setOnInfoListener(new OnInfoListener(){ 
      @Override 
      public boolean onInfo(MediaPlayer mp, int what, int extra) 
      { 
       if(what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) 
       { 
        // Prepare Player 2 
        mediaPlayer1.stop(); 
        mediaPlayer1.release(); 
        try { 
         mediaPlayer1.setDataSource(PrebufferingActivity.URL_1); 
         mediaPlayer1.prepareAsync(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 

       return false; 
      } 
     }); 

     player2.setOnPreparedListener(new OnPreparedListener(){ 
      @Override 
      public void onPrepared(MediaPlayer mp) { 
       mediaPlayer2 = mp; 
      } 
     }); 

     // Player 1 
     player1.setMediaController(new MediaController(this)); 
     player1.setVideoURI(Uri.parse(URL_1)); 

     // Player 2 
     player2.setMediaController(new MediaController(this)); 
     player2.setVideoURI(Uri.parse(URL_2)); 
    } 

回答

3

假設你正在使用MediaPlayer處理您VideoView內您的視頻播放,您可以使用prepareAsync()方法來實現這一目標。 prepareAsync()方法實質上執行與prepare()相同的功能,該功能用於緩衝和準備視頻,但可以在後臺異步完成。

編輯

我做類似的東西,但我實際使用SurfaceView。要處理另一個流,只需創建另一個MediaPlayer實例。以下示例將創建MediaPlayer的兩個實例並緩衝第一個視頻。第一個視頻準備好後,第二個視頻將被異步緩存。然後將第一個MediaPlayer綁定到SurfaceView,並啓動第一個視頻。當第一個視頻播放結束後,相應的MediaPlayer實例被釋放,輔助實例被連接,第二個視頻自動啓動。以下示例代碼已經過測試並且工作正常:

public class StreamingActivity extends Activity implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener 
{ 

    MediaPlayer  mediaPlayerPrimary; 
    MediaPlayer  mediaPlayerSecondary; 
    SurfaceHolder surfaceHolder; 
    SurfaceView  surfaceView; 
    String   videoSourcePrimary = "videoSourcePrimaryURL"; 
    String   videoSourceSecondary = "videoSourceSecondaryURL"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.streaming_activity_layout); 
     /** Create SurfaceView */ 
     surfaceView = (SurfaceView) findViewById(R.id.surface_view); 
     surfaceHolder = surfaceView.getHolder(); 
     surfaceHolder.addCallback(this); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder arg0) 
    { 
     try 
     { 
      /** Create MediaPlayer(s) */ 
      mediaPlayerPrimary = new MediaPlayer(); 
      mediaPlayerSecondary = new MediaPlayer(); 
      /** Attach primary MediaPlayer to SurfaceView */ 
      mediaPlayerPrimary.setDisplay(surfaceHolder); 
      /** Set sources */ 
      mediaPlayerPrimary.setDataSource(videoSourcePrimary); 
      mediaPlayerSecondary.setDataSource(videoSourceSecondary); 
      /** Prepare MediaPlayer(s) */ 
      mediaPlayerPrimary.prepare(); 
      mediaPlayerSecondary.prepareAsync(); 
      /** Set listeners */ 
      mediaPlayerPrimary.setOnPreparedListener(this); 
      mediaPlayerPrimary.setOnCompletionListener(this); 
      mediaPlayerSecondary.setOnPreparedListener(this); 
      mediaPlayerSecondary.setOnCompletionListener(this); 
      /** Set audio stream type */ 
      mediaPlayerPrimary.setAudioStreamType(AudioManager.STREAM_MUSIC); 
      mediaPlayerSecondary.setAudioStreamType(AudioManager.STREAM_MUSIC); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 
    { 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) 
    { 
    } 

    @Override 
    public void onPrepared(MediaPlayer mp) 
    { 
     if (mp == mediaPlayerPrimary) 
     { 
      /** First video ready, start playback */ 
      mediaPlayerPrimary.start(); 
     } 
     else if (mp == mediaPlayerSecondary) 
     { 
      /** Second video is ready */ 
     } 
    } 

    @Override 
    public void onCompletion(MediaPlayer mp) 
    { 
     /** First video is completed, start second video */ 
     mediaPlayerPrimary.release(); 
     mediaPlayerSecondary.setDisplay(surfaceHolder); 
     mediaPlayerSecondary.start(); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.streaming_activity_menu, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) 
    { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) 
     { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 
+0

謝謝Willis。無論如何,你知道如何從VideoView對象獲取MediaPlayer對象嗎?似乎無法找到像getMediaPlayer()... – codeshark

+0

此外,可以說我想調用其MediaPlayer對象prepareAsync()之前,將URL更改爲VideoView A.我應該做以下事情:videoViewA.stopPlayback(); videoViewA.setVideoURI(Uri.parse(URL)); 。videoViewA.getMediaPlayer()prepareAsync(); – codeshark

+0

查看已更新的答案... – Willis