Android提高第二十一篇之MediaPlayer播放网络视频

本文介绍如何使用Android的MediaPlayer播放网络视频,并实现进度条更新、数据缓冲等功能。文章提供了详细的代码示例,包括如何处理SurfaceHolder的生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android提高第二十一篇之MediaPlayer播放网络视频

上次讲解了MediaPlayer播放网络音频,介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法,这次再讲解MediaPlayer播放网络视频。播放网络视频比播放网络音频多需要一个SurfaceView而已,已经熟悉MediaPlayer播放网络音频之后,相信大家对播放网络视频也能很快地掌握。先来看看本文程序运行截图:

本文程序的视频来自http://daily3gp.com,大家可以替换程序中的视频链接,试试其他影片。

main.xml的源码如下:


  1. <framelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.         android:layout_height="fill_parent" android:layout_width="fill_parent">
  3.         <surfaceview android:id="@+id/surfaceView1" 
  4.                 android:layout_height="fill_parent" android:layout_width="fill_parent">
  5.         <linearlayout android:layout_height="wrap_content" 
  6.                 android:layout_width="fill_parent" android:layout_gravity="bottom"
  7.                 android:orientation="vertical">
  8.                 <linearlayout android:orientation="horizontal" 
  9.                         android:layout_gravity="center_horizontal" android:layout_marginTop="4.0dip"
  10.                         android:layout_height="wrap_content" android:layout_width="wrap_content">
  11.                         <button android:layout_width="wrap_content" 
  12.                                 android:layout_height="wrap_content" android:id="@+id/btnPlayUrl"
  13.                                 android:text="播放网络视频">
  14.                         <button android:layout_height="wrap_content" android:id="@+id/btnPause" 
  15.                                 android:text="暂停" android:layout_width="80dip">
  16.                         <button android:layout_height="wrap_content" 
  17.                                 android:layout_width="80dip" android:text="停止" android:id="@+id/btnStop">
  18.                 
  19.                 <linearlayout android:orientation="horizontal" 
  20.                         android:layout_width="fill_parent" android:layout_height="wrap_content"
  21.                         android:layout_marginBottom="20dip">
  22.                         <seekbar android:paddingright="10dip" android:layout_gravity="center_vertical" 
  23.                                 android:paddingLeft="10dip" android:layout_weight="1.0"
  24.                                 android:layout_height="wrap_content" android:layout_width="wrap_content"
  25.                                 android:id="@+id/skbProgress" android:max="100">
  26.                 
  27.         
复制代码
Player.java是本文的核心,Player.java实现了“进度条更新”、“数据缓冲”、“SurfaceHolder生命周期”等功能,其中“SurfaceHolder生命周期”是视频与音频播放的最大区别,通过surfaceCreated()、surfaceDestroyed()、surfaceChanged()可以创建/释放某些资源。下面这个地方需要注意一下:

  1. videoWidth = mediaPlayer.getVideoWidth();
  2.                 videoHeight = mediaPlayer.getVideoHeight();
  3.                 if (videoHeight != 0 && videoWidth != 0) {
  4.                         arg0.start();
  5.                 }
复制代码
有些视频是android播放器不能播放的,不能播放时videoHeight=0,videoWidth=0,以此来判断是否播放视频。Player.java源码如下:
  1. package com.videoplayer;


  2. import java.io.IOException;
  3. import java.util.Timer;
  4. import java.util.TimerTask;
  5. import android.media.AudioManager;
  6. import android.media.MediaPlayer;
  7. import android.media.MediaPlayer.OnBufferingUpdateListener;
  8. import android.media.MediaPlayer.OnCompletionListener;
  9. import android.os.Handler;
  10. import android.os.Message;
  11. import android.util.Log;
  12. import android.view.SurfaceHolder;
  13. import android.view.SurfaceView;
  14. import android.widget.SeekBar;

  15. public class Player implements OnBufferingUpdateListener,
  16.                 OnCompletionListener, MediaPlayer.OnPreparedListener,
  17.                 SurfaceHolder.Callback {
  18.         private int videoWidth;
  19.         private int videoHeight;
  20.         public MediaPlayer mediaPlayer;
  21.         private SurfaceHolder surfaceHolder;
  22.         private SeekBar skbProgress;
  23.         private Timer mTimer=new Timer();
  24.         public Player(SurfaceView surfaceView,SeekBar skbProgress)
  25.         {
  26.                 this.skbProgress=skbProgress;
  27.                 surfaceHolder=surfaceView.getHolder();
  28.                 surfaceHolder.addCallback(this);
  29.                 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  30.                 mTimer.schedule(mTimerTask, 0, 1000);
  31.         }
  32.         
  33.         /*******************************************************
  34.          * 通过定时器和Handler来更新进度条
  35.          ******************************************************/
  36.         TimerTask mTimerTask = new TimerTask() {
  37.                 @Override
  38.                 public void run() {
  39.                         if(mediaPlayer==null)
  40.                                 return;
  41.                         if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {
  42.                                 handleProgress.sendEmptyMessage(0);
  43.                         }
  44.                 }
  45.         };
  46.         
  47.         Handler handleProgress = new Handler() {
  48.                 public void handleMessage(Message msg) {

  49.                         int position = mediaPlayer.getCurrentPosition();
  50.                         int duration = mediaPlayer.getDuration();
  51.                         
  52.                         if (duration > 0) {
  53.                                 long pos = skbProgress.getMax() * position / duration;
  54.                                 skbProgress.setProgress((int) pos);
  55.                         }
  56.                 };
  57.         };
  58.         //*****************************************************
  59.         
  60.         public void play()
  61.         {
  62.                 mediaPlayer.start();
  63.         }
  64.         
  65.         public void playUrl(String videoUrl)
  66.         {
  67.                 try {
  68.                         mediaPlayer.reset();
  69.                         mediaPlayer.setDataSource(videoUrl);
  70.                         mediaPlayer.prepare();//prepare之后自动播放
  71.                         //mediaPlayer.start();
  72.                 } catch (IllegalArgumentException e) {
  73.                         // TODO Auto-generated catch block
  74.                         e.printStackTrace();
  75.                 } catch (IllegalStateException e) {
  76.                         // TODO Auto-generated catch block
  77.                         e.printStackTrace();
  78.                 } catch (IOException e) {
  79.                         // TODO Auto-generated catch block
  80.                         e.printStackTrace();
  81.                 }
  82.         }

  83.         
  84.         public void pause()
  85.         {
  86.                 mediaPlayer.pause();
  87.         }
  88.         
  89.         public void stop()
  90.         {
  91.                 if (mediaPlayer != null) { 
  92.                         mediaPlayer.stop();
  93.             mediaPlayer.release(); 
  94.             mediaPlayer = null; 
  95.         } 
  96.         }
  97.         
  98.         @Override
  99.         public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
  100.                 Log.e("mediaPlayer", "surface changed");
  101.         }

  102.         @Override
  103.         public void surfaceCreated(SurfaceHolder arg0) {
  104.                 try {
  105.                         mediaPlayer = new MediaPlayer();
  106.                         mediaPlayer.setDisplay(surfaceHolder);
  107.                         mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  108.                         mediaPlayer.setOnBufferingUpdateListener(this);
  109.                         mediaPlayer.setOnPreparedListener(this);
  110.                 } catch (Exception e) {
  111.                         Log.e("mediaPlayer", "error", e);
  112.                 }
  113.                 Log.e("mediaPlayer", "surface created");
  114.         }

  115.         @Override
  116.         public void surfaceDestroyed(SurfaceHolder arg0) {
  117.                 Log.e("mediaPlayer", "surface destroyed");
  118.         }

  119.         
  120.         @Override
  121.         /**
  122.          * 通过onPrepared播放
  123.          */
  124.         public void onPrepared(MediaPlayer arg0) {
  125.                 videoWidth = mediaPlayer.getVideoWidth();
  126.                 videoHeight = mediaPlayer.getVideoHeight();
  127.                 if (videoHeight != 0 && videoWidth != 0) {
  128.                         arg0.start();
  129.                 }
  130.                 Log.e("mediaPlayer", "onPrepared");
  131.         }

  132.         @Override
  133.         public void onCompletion(MediaPlayer arg0) {
  134.                 // TODO Auto-generated method stub
  135.                 
  136.         }

  137.         @Override
  138.         public void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress) {
  139.                 skbProgress.setSecondaryProgress(bufferingProgress);
  140.                 int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();
  141.                 Log.e(currentProgress+"% play", bufferingProgress + "% buffer");
  142.                 
  143.         }

  144. }
复制代码
test_videoplayer.java是主程序,负责调用Player类,其中关键部分是SeekBarChangeEvent这个SeekBar拖动的事件:SeekBar的Progress是0~SeekBar.getMax()之内的数,而MediaPlayer.seekTo()的参数是0~MediaPlayer.getDuration()之内数,所以MediaPlayer.seekTo()的参数是(progress/seekBar.getMax())*MediaPlayer.getDuration()。test_videoplayer.java源码如下:
  1. package com.videoplayer;

  2. import android.app.Activity;
  3. import android.content.pm.ActivityInfo;
  4. import android.net.Uri;
  5. import android.os.Bundle;
  6. import android.util.Log;
  7. import android.view.SurfaceView;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.Button;
  11. import android.widget.SeekBar;

  12. public class test_videoplayer extends Activity {
  13.         private SurfaceView surfaceView;
  14.         private Button btnPause, btnPlayUrl, btnStop;
  15.         private SeekBar skbProgress;
  16.         private Player player;

  17.         /** Called when the activity is first created. */
  18.         @Override
  19.         public void onCreate(Bundle savedInstanceState) {
  20.                 super.onCreate(savedInstanceState);
  21.                 setContentView(R.layout.main);
  22.                 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  23.                 surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView1);

  24.                 btnPlayUrl = (Button) this.findViewById(R.id.btnPlayUrl);
  25.                 btnPlayUrl.setOnClickListener(new ClickEvent());

  26.                 btnPause = (Button) this.findViewById(R.id.btnPause);
  27.                 btnPause.setOnClickListener(new ClickEvent());

  28.                 btnStop = (Button) this.findViewById(R.id.btnStop);
  29.                 btnStop.setOnClickListener(new ClickEvent());

  30.                 skbProgress = (SeekBar) this.findViewById(R.id.skbProgress);
  31.                 skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());
  32.                 player = new Player(surfaceView, skbProgress);

  33.         }

  34.         class ClickEvent implements OnClickListener {

  35.                 @Override
  36.                 public void onClick(View arg0) {
  37.                         if (arg0 == btnPause) {
  38.                                 player.pause();
  39.                         } else if (arg0 == btnPlayUrl) {
  40.                                 String url="http://daily3gp.com/vids/family_guy_penis_car.3gp";
  41.                                 player.playUrl(url);
  42.                         } else if (arg0 == btnStop) {
  43.                                 player.stop();
  44.                         }

  45.                 }
  46.         }

  47.         class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {
  48.                 int progress;

  49.                 @Override
  50.                 public void onProgressChanged(SeekBar seekBar, int progress,
  51.                                 boolean fromUser) {
  52.                         // 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()
  53.                         this.progress = progress * player.mediaPlayer.getDuration()
  54.                                         / seekBar.getMax();
  55.                 }

  56.                 @Override
  57.                 public void onStartTrackingTouch(SeekBar seekBar) {

  58.                 }

  59.                 @Override
  60.                 public void onStopTrackingTouch(SeekBar seekBar) {
  61.                         // seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字
  62.                         player.mediaPlayer.seekTo(progress);
  63.                 }
  64.         }

  65. }
复制代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值