前言:
前面我们介绍MediaPlayer相关方法,有人说,没有实际例子,看得不是很明白,
今天在分析MediaPlayer时,顺带一个播放网络视频例子。
可以自行试试。
同样先看下今天的Agenda:
(1)Android中的MediaPlayer框架
(2)MediaPlayer播放视频主要模块
(3)播放主要模块对应组件
(4)MediaPlayer方法对应有效状态及无效状态
(5)案例:Mediaplayer播放网络视频
为演示,我在本地搭建了一个服务器,将视频文件放在tomcat中的ROOT目录下。名字为sanpan.mp4的一个视频。
设置播放相关的方法:在上一篇中MediaPlayer各状态的理解。
MediaPlayerSample/app/src/main/java/com/hejunlin/mediaplayersample/MainActivity.java
package com.hejunlin.mediaplayersample;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity implements OnSeekBarChangeListener, OnCompletionListener {
private boolean isStopUpdatingProgress=false;
private EditText etPath;
private MediaPlayer mMediapPlayer;
private SeekBar mSeekbar;
private TextView tvCurrentTime;
private TextView tvTotalTime;
private final int NORMAL=0;//闲置
private final int PLAYING=1;//播放中
private final int PAUSING=2;//暂停
private final int STOPING=3;//停止中
private int currentstate=NORMAL;//播放器当前的状态,默认是空闲状态
//用行动打消忧虑
private SurfaceHolder holder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etPath=(EditText)findViewById(R.id.et_path);
mSeekbar=(SeekBar) findViewById(R.id.sb_progress);
tvCurrentTime=(TextView)findViewById(R.id.tv_current_time);
tvTotalTime=(TextView)findViewById(R.id.tv_total_time);
mSeekbar.setOnSeekBarChangeListener(this);
SurfaceView mSurfaceView=(SurfaceView) findViewById(R.id.surfaceview);
holder=mSurfaceView.getHolder();//SurfaceView帮助类对象
//是采用自己内部的双缓冲区,而是等待别人推送数据
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/**
* 开始
* @param v
*/
public void start(View v){
if(mMediapPlayer!=null){
if(currentstate!=PAUSING){
mMediapPlayer.start();
currentstate=PLAYING;
isStopUpdatingProgress=false;//每次在调用刷新线程时,都要设为false
return ;
//下面这个判断完美的解决了停止后重新播放的,释放两个资源的问题
}else if(currentstate==STOPING){
mMediapPlayer.reset();
mMediapPlayer.release();
}
}
play();
}
/**
* 停止
* @param v
*/
public void stop(View v){
if(mMediapPlayer!=null){
mMediapPlayer.stop();
}
}
/**
* 播放输入框的文件
*/
private void play(){
String path=etPath.getText().toString().trim();
mMediapPlayer=new MediaPlayer();
try {
//设置数据类型
mMediapPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置以下播放器显示的位置
mMediapPlayer.setDisplay(holder);
mMediapPlayer.setDataSource(path);
mMediapPlayer.prepare();
mMediapPlayer.start();
mMediapPlayer .setOnCompletionListener(this);
//把当前播放器的状诚置为:播放中
currentstate=PLAYING;
//把音乐文件的总长度取出来,设置给seekbar作为最大值
int duration=mMediapPlayer.getDuration();//总时长
mSeekbar.setMax(duration);
//把总时间显示textView上
int m=duration/1000/60;
int s=duration/1000%60;
tvTotalTime.setText("/"+m+":"+s);
tvCurrentTime.setText("00:00");
isStopUpdatingProgress=false;
new Thread(new UpdateProgressRunnable()).start();
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* 暂停
* @param v
*/
public void pause(View v){
if(mMediapPlayer!=null&¤tstate==PLAYING){
mMediapPlayer.pause();
currentstate=PAUSING;
isStopUpdatingProgress=true;//停止刷新主线程
}
}
/**
* 重播
* @param v
*/
public void restart(View v){
if(mMediapPlayer!=null){
mMediapPlayer.reset();
mMediapPlayer.release();
play();
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
isStopUpdatingProgress=true;//当开始拖动时,那么就开始停止刷新线程
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress=seekBar.getProgress();
//播放器切换到指定的进度位置上
mMediapPlayer.seekTo(progress);
isStopUpdatingProgress=false;
new Thread(new UpdateProgressRunnable()).start();
}
/**
* 当播放完成时回调此方法
*/
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(this, "播放完了,重新再播放", 0).show();
mp.start();
}
/**
* 刷新进度和时间的任务
* @author hjl
*
*/
class UpdateProgressRunnable implements Runnable{
@Override
public void run() {
//每隔1秒钟取一下当前正在播放的进度,设置给seekbar
while(!isStopUpdatingProgress){
//得到当前进度
int currentPosition=mMediapPlayer.getCurrentPosition();
mSeekbar.setProgress(currentPosition);
final int m=currentPosition/1000/60;
final int s=currentPosition/1000%60;
//此方法给定的runable对象,会执行主线程(UI线程中)
runOnUiThread(new Runnable(){
@Override
public void run() {
tvCurrentTime.setText(m+":"+s);
}
});
SystemClock.sleep(1000);
}
}
}
}
MediaPlayerSample/app/src/main/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<EditText
android:id="@+id/et_path"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="请输入视频文件的路径"
android:text="http://192.168.0.100/sanpan.mp4" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="start"
android:text="播放" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="pause"
android:text="暂停" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="stop"
android:text="停止" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="restart"
android:text="重播" />
LinearLayout>
<SeekBar
android:id="@+id/sb_progress"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:03"
android:textColor="#FF0000" />
<TextView
android:id="@+id/tv_total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/03:33"
android:textColor="#FF0000" />
LinearLayout>
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
LinearLayout>
由于是网络视频,记得在Manifest加上访问网络的权限
MediaPlayerSample/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hejunlin.mediaplayersample" >
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
application>
manifest>
上面代码摘自 Github:https://github.com/hejunlin2013/MultiMediaSample
本文转自:Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例