• Android提高之MediaPlayer播放网络视频


    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!

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

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

    main.xml的源码如下:

    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" android:layout_width="fill_parent">  
    4.     <SurfaceView android:id="@+id/surfaceView1"  
    5.         android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>  
    6.     <LinearLayout android:layout_height="wrap_content"  
    7.         android:layout_width="fill_parent" android:layout_gravity="bottom"  
    8.         android:orientation="vertical">  
    9.         <LinearLayout android:orientation="horizontal"  
    10.             android:layout_gravity="center_horizontal" android:layout_marginTop="4.0dip"  
    11.             android:layout_height="wrap_content" android:layout_width="wrap_content">  
    12.             <Button android:layout_width="wrap_content"  
    13.                 android:layout_height="wrap_content" android:id="@+id/btnPlayUrl"  
    14.                 android:text="播放网络视频"></Button>  
    15.             <Button android:layout_height="wrap_content" android:id="@+id/btnPause"  
    16.                 android:text="暂停" android:layout_width="80dip"></Button>  
    17.             <Button android:layout_height="wrap_content"  
    18.                 android:layout_width="80dip" android:text="停止" android:id="@+id/btnStop"></Button>  
    19.         </LinearLayout>  
    20.         <LinearLayout android:orientation="horizontal"  
    21.             android:layout_width="fill_parent" android:layout_height="wrap_content"  
    22.             android:layout_marginBottom="20dip">  
    23.             <SeekBar android:paddingRight="10dip" android:layout_gravity="center_vertical"  
    24.                 android:paddingLeft="10dip" android:layout_weight="1.0"  
    25.                 android:layout_height="wrap_content" android:layout_width="wrap_content"  
    26.                 android:id="@+id/skbProgress" android:max="100"></SeekBar>  
    27.         </LinearLayout>  
    28.     </LinearLayout>  
    29. </FrameLayout>  

    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.   
    3.   
    4. import java.io.IOException;  
    5. import java.util.Timer;  
    6. import java.util.TimerTask;  
    7. import android.media.AudioManager;  
    8. import android.media.MediaPlayer;  
    9. import android.media.MediaPlayer.OnBufferingUpdateListener;  
    10. import android.media.MediaPlayer.OnCompletionListener;  
    11. import android.os.Handler;  
    12. import android.os.Message;  
    13. import android.util.Log;  
    14. import android.view.SurfaceHolder;  
    15. import android.view.SurfaceView;  
    16. import android.widget.SeekBar;  
    17.   
    18. public class Player implements OnBufferingUpdateListener,  
    19.         OnCompletionListener, MediaPlayer.OnPreparedListener,  
    20.         SurfaceHolder.Callback {  
    21.     private int videoWidth;  
    22.     private int videoHeight;  
    23.     public MediaPlayer mediaPlayer;  
    24.     private SurfaceHolder surfaceHolder;  
    25.     private SeekBar skbProgress;  
    26.     private Timer mTimer=new Timer();  
    27.     public Player(SurfaceView surfaceView,SeekBar skbProgress)  
    28.     {  
    29.         this.skbProgress=skbProgress;  
    30.         surfaceHolder=surfaceView.getHolder();  
    31.         surfaceHolder.addCallback(this);  
    32.         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
    33.         mTimer.schedule(mTimerTask, 01000);  
    34.     }  
    35.       
    36.     /******************************************************* 
    37.      * 通过定时器和Handler来更新进度条 
    38.      ******************************************************/  
    39.     TimerTask mTimerTask = new TimerTask() {  
    40.         @Override  
    41.         public void run() {  
    42.             if(mediaPlayer==null)  
    43.                 return;  
    44.             if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {  
    45.                 handleProgress.sendEmptyMessage(0);  
    46.             }  
    47.         }  
    48.     };  
    49.       
    50.     Handler handleProgress = new Handler() {  
    51.         public void handleMessage(Message msg) {  
    52.   
    53.             int position = mediaPlayer.getCurrentPosition();  
    54.             int duration = mediaPlayer.getDuration();  
    55.               
    56.             if (duration > 0) {  
    57.                 long pos = skbProgress.getMax() * position / duration;  
    58.                 skbProgress.setProgress((int) pos);  
    59.             }  
    60.         };  
    61.     };  
    62.     //*****************************************************  
    63.       
    64.     public void play()  
    65.     {  
    66.         mediaPlayer.start();  
    67.     }  
    68.       
    69.     public void playUrl(String videoUrl)  
    70.     {  
    71.         try {  
    72.             mediaPlayer.reset();  
    73.             mediaPlayer.setDataSource(videoUrl);  
    74.             mediaPlayer.prepare();//prepare之后自动播放  
    75.             //mediaPlayer.start();  
    76.         } catch (IllegalArgumentException e) {  
    77.             // TODO Auto-generated catch block  
    78.             e.printStackTrace();  
    79.         } catch (IllegalStateException e) {  
    80.             // TODO Auto-generated catch block  
    81.             e.printStackTrace();  
    82.         } catch (IOException e) {  
    83.             // TODO Auto-generated catch block  
    84.             e.printStackTrace();  
    85.         }  
    86.     }  
    87.   
    88.       
    89.     public void pause()  
    90.     {  
    91.         mediaPlayer.pause();  
    92.     }  
    93.       
    94.     public void stop()  
    95.     {  
    96.         if (mediaPlayer != null) {   
    97.             mediaPlayer.stop();  
    98.             mediaPlayer.release();   
    99.             mediaPlayer = null;   
    100.         }   
    101.     }  
    102.       
    103.     @Override  
    104.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  
    105.         Log.e("mediaPlayer""surface changed");  
    106.     }  
    107.   
    108.     @Override  
    109.     public void surfaceCreated(SurfaceHolder arg0) {  
    110.         try {  
    111.             mediaPlayer = new MediaPlayer();  
    112.             mediaPlayer.setDisplay(surfaceHolder);  
    113.             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
    114.             mediaPlayer.setOnBufferingUpdateListener(this);  
    115.             mediaPlayer.setOnPreparedListener(this);  
    116.         } catch (Exception e) {  
    117.             Log.e("mediaPlayer""error", e);  
    118.         }  
    119.         Log.e("mediaPlayer""surface created");  
    120.     }  
    121.   
    122.     @Override  
    123.     public void surfaceDestroyed(SurfaceHolder arg0) {  
    124.         Log.e("mediaPlayer""surface destroyed");  
    125.     }  
    126.   
    127.       
    128.     @Override  
    129.     /**  
    130.      * 通过onPrepared播放  
    131.      */  
    132.     public void onPrepared(MediaPlayer arg0) {  
    133.         videoWidth = mediaPlayer.getVideoWidth();  
    134.         videoHeight = mediaPlayer.getVideoHeight();  
    135.         if (videoHeight != 0 && videoWidth != 0) {  
    136.             arg0.start();  
    137.         }  
    138.         Log.e("mediaPlayer""onPrepared");  
    139.     }  
    140.   
    141.     @Override  
    142.     public void onCompletion(MediaPlayer arg0) {  
    143.         // TODO Auto-generated method stub  
    144.           
    145.     }  
    146.   
    147.     @Override  
    148.     public void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress) {  
    149.         skbProgress.setSecondaryProgress(bufferingProgress);  
    150.         int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();  
    151.         Log.e(currentProgress+"% play", bufferingProgress + "% buffer");  
    152.           
    153.     }  
    154.   
    155. }  

     

    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.   
    3. import android.app.Activity;  
    4. import android.content.pm.ActivityInfo;  
    5. import android.net.Uri;  
    6. import android.os.Bundle;  
    7. import android.util.Log;  
    8. import android.view.SurfaceView;  
    9. import android.view.View;  
    10. import android.view.View.OnClickListener;  
    11. import android.widget.Button;  
    12. import android.widget.SeekBar;  
    13.   
    14. public class test_videoplayer extends Activity {  
    15.     private SurfaceView surfaceView;  
    16.     private Button btnPause, btnPlayUrl, btnStop;  
    17.     private SeekBar skbProgress;  
    18.     private Player player;  
    19.   
    20.     /** Called when the activity is first created. */  
    21.     @Override  
    22.     public void onCreate(Bundle savedInstanceState) {  
    23.         super.onCreate(savedInstanceState);  
    24.         setContentView(R.layout.main);  
    25.         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
    26.         surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView1);  
    27.   
    28.         btnPlayUrl = (Button) this.findViewById(R.id.btnPlayUrl);  
    29.         btnPlayUrl.setOnClickListener(new ClickEvent());  
    30.   
    31.         btnPause = (Button) this.findViewById(R.id.btnPause);  
    32.         btnPause.setOnClickListener(new ClickEvent());  
    33.   
    34.         btnStop = (Button) this.findViewById(R.id.btnStop);  
    35.         btnStop.setOnClickListener(new ClickEvent());  
    36.   
    37.         skbProgress = (SeekBar) this.findViewById(R.id.skbProgress);  
    38.         skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());  
    39.         player = new Player(surfaceView, skbProgress);  
    40.   
    41.     }  
    42.   
    43.     class ClickEvent implements OnClickListener {  
    44.   
    45.         @Override  
    46.         public void onClick(View arg0) {  
    47.             if (arg0 == btnPause) {  
    48.                 player.pause();  
    49.             } else if (arg0 == btnPlayUrl) {  
    50.                 String url="http://daily3gp.com/vids/family_guy_penis_car.3gp";  
    51.                 player.playUrl(url);  
    52.             } else if (arg0 == btnStop) {  
    53.                 player.stop();  
    54.             }  
    55.   
    56.         }  
    57.     }  
    58.   
    59.     class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {  
    60.         int progress;  
    61.   
    62.         @Override  
    63.         public void onProgressChanged(SeekBar seekBar, int progress,  
    64.                 boolean fromUser) {  
    65.             // 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()  
    66.             this.progress = progress * player.mediaPlayer.getDuration()  
    67.                     / seekBar.getMax();  
    68.         }  
    69.   
    70.         @Override  
    71.         public void onStartTrackingTouch(SeekBar seekBar) {  
    72.   
    73.         }  
    74.   
    75.         @Override  
    76.         public void onStopTrackingTouch(SeekBar seekBar) {  
    77.             // seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字  
    78.             player.mediaPlayer.seekTo(progress);  
    79.         }  
    80.     }  
    81.   
    82. }  
  • 相关阅读:
    16.10.16学到的JAVA知识
    参数类型转换求和(JAVA)
    大道至简第一篇读后感之愚公移山(伪代码)
    First
    18.10.22 luoguP3374 【模板】树状数组 1
    18.10.16 luoguP3372 线段树模板-区间更新值&求和(POJ3468 A Simple Problem with Integers)
    18.10.16 POJ 2528 Mayor's posters(线段树+离散化)
    18.10.15 POJ 2182 Lost Cows(线段树)
    18.10.10 数算作业-字符串
    18.10.9 不好做的最长上升子序列(nlogn树状数组解LIS)
  • 原文地址:https://www.cnblogs.com/huanjianlin/p/3547601.html
Copyright © 2020-2023  润新知