现在的位置: 首页 > 综合 > 正文

Android 一个实例网络视频

2013年08月24日 ⁄ 综合 ⁄ 共 7547字 ⁄ 字号 评论关闭

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

效果图:

main.xml的源码如下:

java代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_height="fill_parent"
  4. android:layout_width="fill_parent">
  5. <SurfaceView
  6. android:id="@+id/surfaceView1"
  7. android:layout_height="fill_parent"
  8. android:layout_width="fill_parent">
  9. </SurfaceView>
  10. <LinearLayout
  11. android:layout_height="wrap_content"
  12. android:layout_width="fill_parent"
  13. android:layout_gravity="bottom"
  14. android:orientation="vertical">
  15. <LinearLayout
  16. android:orientation="horizontal"
  17. android:layout_gravity="center_horizontal"
  18. android:layout_marginTop="4.0dip"
  19. android:layout_height="wrap_content"
  20. android:layout_width="wrap_content">
  21. <Button
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:id="@+id/btnPlayUrl"
  25. android:text="播放网络视频">
  26. </Button>
  27. <Button android:layout_height="wrap_content"
  28. android:id="@+id/btnPause"
  29. android:text="暂停"
  30. android:layout_width="80dip">
  31. </Button>
  32. <Button
  33. android:layout_height="wrap_content"
  34. android:layout_width="80dip"
  35. android:text="停止"
  36. android:id="@+id/btnStop"></Button>
  37. </LinearLayout>
  38. <LinearLayout android:orientation="horizontal"
  39. android:layout_width="fill_parent"
  40. android:layout_height="wrap_content"
  41. android:layout_marginBottom="20dip">
  42. <SeekBar
  43. android:paddingRight="10dip"
  44. android:layout_gravity="center_vertical"
  45. android:paddingLeft="10dip"
  46. android:layout_weight="1.0"
  47. android:layout_height="wrap_content"
  48. android:layout_width="wrap_content"
  49. android:id="@+id/skbProgress"
  50. android:max="100"></SeekBar>
  51. </LinearLayout>
  52. </LinearLayout>
  53. </FrameLayout>

复制代码

       Player.java是本文的核心,Player.java实现了“进度条更新”、“数据缓冲”、“SurfaceHolder生命周期”等功能,其中“SurfaceHolder生命周期”是视频与音频播放的最大区别,通过surfaceCreated()、surfaceDestroyed()、surfaceChanged()可以创建\释放某些资源。下面这个地方需要注意一下:

java代码:

  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源码如下:

java代码:

  1. package eoe.demo;
  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. this.skbProgress=skbProgress;
  26. surfaceHolder=surfaceView.getHolder();
  27. surfaceHolder.addCallback(this);
  28. surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  29. mTimer.schedule(mTimerTask, 0, 1000);
  30. }
  31. /*通过定时器和Handler来更新进度条 */
  32. TimerTask mTimerTask = new TimerTask() {
  33. @Override
  34. public void run() {
  35. if(mediaPlayer==null)
  36. return;
  37. if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {
  38. handleProgress.sendEmptyMessage(0);
  39. }
  40. }
  41. };
  42. Handler handleProgress = new Handler() {
  43. public void handleMessage(Message msg) {
  44. int position = mediaPlayer.getCurrentPosition();
  45. int duration = mediaPlayer.getDuration();
  46. if (duration > 0) {
  47. long pos = skbProgress.getMax() * position / duration;
  48. skbProgress.setProgress((int) pos);
  49. }
  50. };
  51. };
  52. public void play() {
  53. mediaPlayer.start();
  54. }
  55. public void playUrl(String videoUrl) {
  56. try {
  57. mediaPlayer.reset();
  58. mediaPlayer.setDataSource(videoUrl);
  59. mediaPlayer.prepare();//prepare之后自动播放
  60. //mediaPlayer.start();
  61. } catch (IllegalArgumentException e) {
  62. // TODO Auto-generated catch block
  63. e.printStackTrace();
  64. } catch (IllegalStateException e) {
  65. // TODO Auto-generated catch block
  66. e.printStackTrace();
  67. } catch (IOException e) {
  68. // TODO Auto-generated catch block
  69. e.printStackTrace();
  70. }
  71. }
  72. public void pause() {
  73. mediaPlayer.pause();
  74. }
  75. public void stop() {
  76. if (mediaPlayer != null) {
  77. mediaPlayer.stop();
  78. mediaPlayer.release();
  79. mediaPlayer = null;
  80. }
  81. }
  82. @Override
  83. public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
  84. Log.e("mediaPlayer", "surface changed");
  85. }
  86. @Override
  87. public void surfaceCreated(SurfaceHolder arg0) {
  88. try {
  89. mediaPlayer = new MediaPlayer();
  90. mediaPlayer.setDisplay(surfaceHolder);
  91. mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  92. mediaPlayer.setOnBufferingUpdateListener(this);
  93. mediaPlayer.setOnPreparedListener(this);
  94. } catch (Exception e) {
  95. Log.e("mediaPlayer", "error", e);
  96. }
  97. Log.e("mediaPlayer", "surface created");
  98. }
  99. @Override
  100. public void surfaceDestroyed(SurfaceHolder arg0) {
  101. Log.e("mediaPlayer", "surface destroyed");
  102. }
  103. @Override
  104. /**
  105. * 通过onPrepared播放
  106. */
  107. public void onPrepared(MediaPlayer arg0) {
  108. videoWidth = mediaPlayer.getVideoWidth();
  109. videoHeight = mediaPlayer.getVideoHeight();
  110. if (videoHeight != 0 && videoWidth != 0) {
  111. arg0.start();
  112. }
  113. Log.e("mediaPlayer", "onPrepared");
  114. }
  115. @Override
  116. public void onCompletion(MediaPlayer arg0) {
  117. // TODO Auto-generated method stub
  118. }
  119. @Override
  120. public void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress) {
  121. skbProgress.setSecondaryProgress(bufferingProgress);
  122. int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();
  123. Log.e(currentProgress+"% play", bufferingProgress + "% buffer");
  124. }
  125. }

复制代码

       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源码如下:

java代码:

  1. package eoe.demo;
  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. }

复制代码

抱歉!评论已关闭.