• 10.2.2 网络视频播放


        Android支持采用第9章讨论的3种视频播放方法来播放HTTP和RTSP视频。无须改变原来的源代码,就可以通过意图触发内置的媒体播放器活动或者使用VideoView类来播放任何形式的网络视频。只需要将HTTP或RTSP URL作为视频Uri,那么只要是支持的格式,它就可以工作。

        1.VideoView网络视频播放器

        下面是来自第9章的ViewTheVideo活动示例,其使用一个VideoView及一个指向YouTube移动站点视频的RTSP URL。唯一的变化是构造videoUri所传入的字符串。

     1 package com.nthm.androidtestActivity;
     2 
     3 import com.nthm.androidtest.R;
     4 import android.app.Activity;
     5 import android.net.Uri;
     6 import android.os.Bundle;
     7 import android.widget.MediaController;
     8 import android.widget.VideoView;
     9 
    10 public class ViewTheVideo extends Activity {
    11     private VideoView vv;
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.viewthevideo);
    16         vv=(VideoView) findViewById(R.id.VedioView);
    17         vv.setMediaController(new MediaController(ViewTheVideo.this));
    18         Uri videoUri=Uri.parse("");//此处的路径下的视频必须是能够渐进式累进式的视频
    19         vv.setVideoURI(videoUri);
    20         vv.start();
    21     }
    22 }

        2.MediaPlayer网络视频播放器

        将MediaPlayer用于网络视频播放类似于在第9章中讨论过的MediaPlayer和MediaController代码。在下面的示例中会突出显示专门与网络播放相关的部分。关于MediaPlayer和MediaController的完整解释,请参阅第9章中的示例。

     1 package com.nthm.androidtestActivity;
     2 
     3 import java.io.IOException;
     4 import com.nthm.androidtest.R;
     5 import android.app.Activity;
     6 import android.media.MediaPlayer;
     7 import android.media.MediaPlayer.OnBufferingUpdateListener;
     8 import android.media.MediaPlayer.OnCompletionListener;
     9 import android.media.MediaPlayer.OnErrorListener;
    10 import android.media.MediaPlayer.OnInfoListener;
    11 import android.media.MediaPlayer.OnPreparedListener;
    12 import android.media.MediaPlayer.OnSeekCompleteListener;
    13 import android.media.MediaPlayer.OnVideoSizeChangedListener;
    14 import android.os.Bundle;
    15 import android.view.Display;
    16 import android.view.MotionEvent;
    17 import android.view.SurfaceHolder;
    18 import android.view.SurfaceHolder.Callback;
    19 import android.view.SurfaceView;
    20 import android.view.View;
    21 import android.view.View.OnTouchListener;
    22 import android.widget.LinearLayout;
    23 import android.widget.MediaController;
    24 import android.widget.MediaController.MediaPlayerControl;
    25 import android.widget.TextView;

        StreamingVideoPlayer活动实现了许多可用的监听以及源自MediaPlayer、SurfaceHolderMediaController的回调抽象类。OnBufferingUpdateListener在处理网络传输的媒体时特别的有用。这个类指定了一个onBufferingUpdate方法,当缓冲媒体时重复调用该方法,从而能够跟踪缓冲区的填充程度。

     1 public class StreamingVideoPlayer extends Activity implements
     2         OnCompletionListener, OnErrorListener, OnInfoListener,
     3         OnBufferingUpdateListener, OnPreparedListener, OnSeekCompleteListener,
     4         OnVideoSizeChangedListener, Callback, MediaPlayerControl,OnTouchListener {
     5     private MediaController controller;
     6     private Display currentDisplay;
     7     private SurfaceView surfaceView;
     8     private SurfaceHolder surfaceHolder;
     9     private MediaPlayer mediaPlayer;
    10     private View mainView;

        在当前版本中将使用一个称为statusView的TextView对象,以将状态消息显示给用户。之所以这么做,是因为通过Internet加载待播放的视频会花费相当长的时间,如果没有一些状态消息,那么用户可能会认为应用程序已经挂起。

     1     private TextView statusView;
     2     private int videoWidth=0;
     3     private int videoHeight=0;
     4     private boolean readyToPlay=false;
     5     @Override
     6     protected void onCreate(Bundle savedInstanceState) {
     7         super.onCreate(savedInstanceState);
     8         setContentView(R.layout.streamimgvideoplayer);
     9         mainView=findViewById(R.id.MainView);
    10         statusView=(TextView) findViewById(R.id.StatusTextView);
    11         
    12         surfaceView=(SurfaceView) findViewById(R.id.SurfaceView);
    13         surfaceHolder=surfaceView.getHolder();
    14         surfaceHolder.addCallback(this);
    15         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    16         
    17         mediaPlayer=new MediaPlayer();
    18         statusView.setText("MediaPlayer Created");
    19         mediaPlayer.setOnCompletionListener(this);
    20         mediaPlayer.setOnErrorListener(this);
    21         mediaPlayer.setOnInfoListener(this);
    22         mediaPlayer.setOnPreparedListener(this);
    23         mediaPlayer.setOnSeekCompleteListener(this);
    24         mediaPlayer.setOnVideoSizeChangedListener(this);

        在MediaPlayer事件监听器的列表中,活动实现并注册为OnBufferingUpdateListener。

    1         mediaPlayer.setOnBufferingUpdateListener(this);

        与播放SD卡上的文件不同,现在将播放一个来自RTSP服务器的文件。在字符串filePath中指定该文件的URL。然后,使用MediaPlayer的setDataSource方法,并传入filePath字符串。由于MediaPlayer知道如何处理从一个RTSP服务器加载并播放数据,因此不必做其他的改动来处理它。

     1         String filePath="";//可用于渐进式加载的视频路径
     2         try {
     3             mediaPlayer.setDataSource(filePath);
     4         } catch (IllegalArgumentException e) {
     5             e.printStackTrace();
     6         } catch (SecurityException e) {
     7             e.printStackTrace();
     8         } catch (IllegalStateException e) {
     9             e.printStackTrace();
    10         } catch (IOException e) {
    11             e.printStackTrace();
    12         }
    13         statusView.setText("MediaPlayer setDataSource Set");
    14         currentDisplay=getWindowManager().getDefaultDisplay();
    15         controller=new MediaController(this);
    16     }
    17 
    18 
    19     @Override
    20     public void surfaceCreated(SurfaceHolder holder) {
    21        mediaPlayer.setDisplay(holder);
    22        statusView.setText("MediaPlayer Display surface Set");

        我们将使用MediaPlayer的prepareAsync方法而不是prepare方法。prepareAsync方法在后台中一个单独的线程上做准备工作,从而使得用户界面不会被挂起。因此,这将允许用户执行其他操作,或者允许开发人员显示一个加载动画或类似的内容。

    1        try{
    2        mediaPlayer.prepareAsync();
    3        }catch(Exception e){
    4           finish(); 
    5        }

        因此,通过更新由statusView显示的状态信息,用户将知道在运行prepareAsync时发生了什么。

     1        statusView.setText("MediaPlayer preparing");
     2     }
     3     @Override
     4     public void surfaceChanged(SurfaceHolder holder, int format, int width,
     5             int height) {
     6 
     7     }
     8     @Override
     9     public void surfaceDestroyed(SurfaceHolder holder) {
    10 
    11     }
    12     @Override
    13     public void onCompletion(MediaPlayer mp) {
    14         statusView.setText("MediaPlayer Playback Completed");
    15     }
    16     @Override
    17     public boolean onInfo(MediaPlayer mp, int what, int extra) {
    18         return false;
    19     }
    20 
    21     @Override
    22     public boolean onError(MediaPlayer mp, int what, int extra) {
    23         return false;
    24     }
    25     @Override
    26     public void onPrepared(MediaPlayer mp) {
    27         statusView.setText("MediaPlayer Prepared");
    28          videoWidth=mp.getVideoWidth();
    29          videoHeight=mp.getVideoHeight();
    30          
    31          if(videoWidth>currentDisplay.getWidth()||videoHeight>currentDisplay.getHeight()){
    32              float heightRatio=(float)videoHeight/(float)currentDisplay.getHeight();
    33              float widthRatio=(float)videoWidth/(float)currentDisplay.getWidth();
    34              if(heightRatio>1||widthRatio>1){
    35                  if(heightRatio>widthRatio){
    36                      videoHeight=(int)Math.ceil((float)videoHeight/(float)heightRatio);
    37                      videoWidth=(int)Math.ceil((float)videoWidth/(float)heightRatio);
    38                  }else{
    39                      videoHeight=(int)Math.ceil((float)videoHeight/(float)widthRatio);
    40                      videoWidth=(int)Math.ceil((float)videoWidth/(float)widthRatio);
    41                  }
    42              }
    43          }
    44          surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth,videoHeight));
    45          controller.setMediaPlayer(this);
    46          controller.setAnchorView(this.findViewById(R.id.MainView));
    47          controller.setEnabled(true);
    48          controller.show();
    49          mp.start();
    50          statusView.setText("MediaPlayer Started");
    51     }
    52     @Override
    53     public void onSeekComplete(MediaPlayer mp) {
    54 
    55     }
    56     @Override
    57     public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
    58          videoWidth=mp.getVideoWidth();
    59          videoHeight=mp.getVideoHeight();
    60          
    61          if(videoWidth>currentDisplay.getWidth()||videoHeight>currentDisplay.getHeight()){
    62              float heightRatio=(float)videoHeight/(float)currentDisplay.getHeight();
    63              float widthRatio=(float)videoWidth/(float)currentDisplay.getWidth();
    64              if(heightRatio>1||widthRatio>1){
    65                  if(heightRatio>widthRatio){
    66                      videoHeight=(int)Math.ceil((float)videoHeight/(float)heightRatio);
    67                      videoWidth=(int)Math.ceil((float)videoWidth/(float)heightRatio);
    68                  }else{
    69                      videoHeight=(int)Math.ceil((float)videoHeight/(float)widthRatio);
    70                      videoWidth=(int)Math.ceil((float)videoWidth/(float)widthRatio);
    71                  }
    72              }
    73          }
    74          surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth,videoHeight));
    75     }

        由于活动实现了OnBufferingUpdateListener,并注册为MediaPlayer的监听器,因此当下载缓冲媒体时,将定期调用以下方法。缓冲将发生在准备阶段(调用onPrepareAsync或onPrepare方法之后)。

     1     @Override
     2     public void onBufferingUpdate(MediaPlayer mp, int percent) {
     3         statusView.setText("MediaPlayer Buffering:"+percent+"%");
     4     }
     5 
     6     @Override
     7     public void start() {
     8         mediaPlayer.start();
     9     }
    10 
    11     @Override
    12     public void pause() {
    13        if(mediaPlayer.isPlaying()){
    14            mediaPlayer.pause();
    15        }
    16     }
    17 
    18     @Override
    19     public int getDuration() {
    20         return mediaPlayer.getDuration();
    21     }
    22 
    23     @Override
    24     public int getCurrentPosition() {
    25         return mediaPlayer.getCurrentPosition();
    26     }
    27 
    28     @Override
    29     public void seekTo(int pos) {
    30         mediaPlayer.seekTo(pos);
    31     }
    32 
    33     @Override
    34     public boolean isPlaying() {
    35         return mediaPlayer.isPlaying();
    36     }
    37 
    38     @Override
    39     public int getBufferPercentage() {
    40         return 0;
    41     }
    42 
    43     @Override
    44     public boolean canPause() {
    45         return false;
    46     }
    47 
    48     @Override
    49     public boolean canSeekBackward() {
    50         return false;
    51     }
    52 
    53     @Override
    54     public boolean canSeekForward() {
    55         return false;
    56     }
    57 
    58     @Override
    59     public int getAudioSessionId() {
    60         return 0;
    61     }
    62     @Override
    63     public boolean onTouch(View v, MotionEvent event) {
    64         if(controller.isShowing()){
    65             controller.hide();
    66         }else{
    67             controller.show();    
    68         }
    69         return false;
    70     }
    71 }
  • 相关阅读:
    数据库分页
    SpringBoot 集成 MQTT
    mybatis的级联查询-懒加载遇到的序列化问题
    springboot学习:第二天
    SpringSecurity学习
    大日志文件查看方式
    logger(七)、springBoot的日志源码查看(LogBack + slf4j)——配置的实际工作类Action
    logger(六)、springBoot的日志源码查看(LogBack + slf4j)—— ContextInitializer
    logger(五)、springBoot的日志源码查看(LogBack + slf4j)——Appender
    logger(四)、springBoot的日志源码查看(LogBack + slf4j)——记录日志
  • 原文地址:https://www.cnblogs.com/ZSS-Android/p/3957246.html
Copyright © 2020-2023  润新知