`
hxdawxyhxdawxy
  • 浏览: 125921 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

android 播放网络视频和音频

阅读更多
       本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!
       上次讲解了MediaPlayer播放网络音频,介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法,这次再讲解MediaPlayer播放网络视频。播放网络视频比播放网络音频多需要一个SurfaceView而已,已经熟悉MediaPlayer播放网络音频之后,相信大家对播放网络视频也能很快地掌握。先来看看本文程序运行截图:


本文程序的视频来自http://daily3gp.com,大家可以替换程序中的视频链接,试试其他影片。
main.xml的源码如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_height="fill_parent" android:layout_width="fill_parent">
	<SurfaceView android:id="@+id/surfaceView1"
		android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>
	<LinearLayout android:layout_height="wrap_content"
		android:layout_width="fill_parent" android:layout_gravity="bottom"
		android:orientation="vertical">
		<LinearLayout android:orientation="horizontal"
			android:layout_gravity="center_horizontal" android:layout_marginTop="4.0dip"
			android:layout_height="wrap_content" android:layout_width="wrap_content">
			<Button android:layout_width="wrap_content"
				android:layout_height="wrap_content" android:id="@+id/btnPlayUrl"
				android:text="播放网络视频"></Button>
			<Button android:layout_height="wrap_content" android:id="@+id/btnPause"
				android:text="暂停" android:layout_width="80dip"></Button>
			<Button android:layout_height="wrap_content"
				android:layout_width="80dip" android:text="停止" android:id="@+id/btnStop"></Button>
		</LinearLayout>
		<LinearLayout android:orientation="horizontal"
			android:layout_width="fill_parent" android:layout_height="wrap_content"
			android:layout_marginBottom="20dip">
			<SeekBar android:paddingRight="10dip" android:layout_gravity="center_vertical"
				android:paddingLeft="10dip" android:layout_weight="1.0"
				android:layout_height="wrap_content" android:layout_width="wrap_content"
				android:id="@+id/skbProgress" android:max="100"></SeekBar>
		</LinearLayout>
	</LinearLayout>
</FrameLayout>



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



有些视频是android播放器不能播放的,不能播放时videoHeight=0,videoWidth=0,以此来判断是否播放视频。
Player.java源码如下:
package com.videoplayer;


import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.SeekBar;

public class Player implements OnBufferingUpdateListener,
		OnCompletionListener, MediaPlayer.OnPreparedListener,
		SurfaceHolder.Callback {
	private int videoWidth;
	private int videoHeight;
	public MediaPlayer mediaPlayer;
	private SurfaceHolder surfaceHolder;
	private SeekBar skbProgress;
	private Timer mTimer=new Timer();
	public Player(SurfaceView surfaceView,SeekBar skbProgress)
	{
		this.skbProgress=skbProgress;
		surfaceHolder=surfaceView.getHolder();
		surfaceHolder.addCallback(this);
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		mTimer.schedule(mTimerTask, 0, 1000);
	}
	
	/*******************************************************
	 * 通过定时器和Handler来更新进度条
	 ******************************************************/
	TimerTask mTimerTask = new TimerTask() {
		@Override
		public void run() {
			if(mediaPlayer==null)
				return;
			if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {
				handleProgress.sendEmptyMessage(0);
			}
		}
	};
	
	Handler handleProgress = new Handler() {
		public void handleMessage(Message msg) {

			int position = mediaPlayer.getCurrentPosition();
			int duration = mediaPlayer.getDuration();
			
			if (duration > 0) {
				long pos = skbProgress.getMax() * position / duration;
				skbProgress.setProgress((int) pos);
			}
		};
	};
	//*****************************************************
	
	public void play()
	{
		mediaPlayer.start();
	}
	
	public void playUrl(String videoUrl)
	{
		try {
			mediaPlayer.reset();
			mediaPlayer.setDataSource(videoUrl);
			mediaPlayer.prepare();//prepare之后自动播放
			//mediaPlayer.start();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	public void pause()
	{
		mediaPlayer.pause();
	}
	
	public void stop()
	{
		if (mediaPlayer != null) { 
			mediaPlayer.stop();
            mediaPlayer.release(); 
            mediaPlayer = null; 
        } 
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		Log.e("mediaPlayer", "surface changed");
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		try {
			mediaPlayer = new MediaPlayer();
			mediaPlayer.setDisplay(surfaceHolder);
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setOnBufferingUpdateListener(this);
			mediaPlayer.setOnPreparedListener(this);
		} catch (Exception e) {
			Log.e("mediaPlayer", "error", e);
		}
		Log.e("mediaPlayer", "surface created");
	}

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

	
	@Override
	/**
	 * 通过onPrepared播放
	 */
	public void onPrepared(MediaPlayer arg0) {
		videoWidth = mediaPlayer.getVideoWidth();
		videoHeight = mediaPlayer.getVideoHeight();
		if (videoHeight != 0 && videoWidth != 0) {
			arg0.start();
		}
		Log.e("mediaPlayer", "onPrepared");
	}

	@Override
	public void onCompletion(MediaPlayer arg0) {
		// TODO Auto-generated method stub
		
	}

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

}


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

package com.videoplayer;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;

public class test_videoplayer extends Activity {
	private SurfaceView surfaceView;
	private Button btnPause, btnPlayUrl, btnStop;
	private SeekBar skbProgress;
	private Player player;

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

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

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

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

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

	}

	class ClickEvent implements OnClickListener {

		@Override
		public void onClick(View arg0) {
			if (arg0 == btnPause) {
				player.pause();
			} else if (arg0 == btnPlayUrl) {
				String url="http://daily3gp.com/vids/family_guy_penis_car.3gp";
				player.playUrl(url);
			} else if (arg0 == btnStop) {
				player.stop();
			}

		}
	}

	class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {
		int progress;

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

		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {

		}

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

}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics