在 Android 中,我们可以通过 android.media.MediaPlayer 类完成音频或视频文件的播放操作。需要注意的是视频和音频有许多格式,但是 MediaPlayer 类只能完成一些基本格式的操作,如果 MP3 、 3GP 等,而其他媒体格式则需要编写相应的解码器进行解码播放。
生命周期解释:
1、 Idle 状态 :当使用关键字 new 实例化一个 MediaPlayer 对象或者是调用了类中的 reset() 方法时会进入到此状态
2、 End 状态 :当调用 release() 方法之后将进入到此状态,此时会释放所有占用的硬件和软件的资源,并且不会再进入其他任何一种状态。
3、 Initialized 状态 :当 MediaPlayer 对象设置好要播放的媒体 (setDataSource()) 之后进入到此状态。
4、 Prepared 状态 :预播放状态 (prepare() 、 prepareAsync()) ,进入到此状态则表示目前的媒体文件没有任何问题,可以使用 OnPreparedListener 监听。
·如果用户调用的是 prepare() 方法(同步),则表示该 MediaPlayer 对象已经进入 Prepared 状态;
·如果用户调用的是 prepareAsync() 方法(异步),则表示该 MediaPlayer 对象进入 Preparing 状态并返回,而内部播放引擎会继续执行为完成的准备工作。
5、 Started 状态 :正在进行媒体播放 (start()) ,此时可以使用 seekTo() 方法指定媒体播放的位置。
6、 Paused 状态 :在 Started 状态下使用 Paused 状态可以暂停 MediaPlayer 的播放,暂停之后可以通过 Start() 方法将其变回到 Started 状态,继续播放。
7、 Stopped 状态 :在 Started 和 Paused 状态下都可以通过 stop() 方法停止 MediaPlayer 的播放,在 Stopped 状态下要想重新进行播放,则可以使用 prepare() 和 prepareAsync() 方法进入到就绪状态。
8、 PlaybackCompleted 状态 :当媒体文件播放完毕之后会进入此状态,用户可以使用 OnCompletionListener 监听此状态,此时可以使用 start() 方法重新播放,也可以使用 stop() 方法停止播放,或者使用 seekTo() 方法来重新定义播放位置。
9、 Error 状态: 当用户播放操作中出现某些错误(文件格式不正确、播放文件过大等)时则进入此状态,用户可以使用 OnErrorListener 来监听此状态,如果 MediaPlayer 进入此状态,可以用 reset() 方法重新变回 Idle 状态。
MP3 播放器:
MediaPlayer01_Mp3PlayerActivity.java
package com.iflytek.demo;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MediaPlayer01_Mp3PlayerActivity extends Activity {
private ImageButton play = null;
private ImageButton pause = null;
private ImageButton stop = null;
private TextView info = null;
private MediaPlayer mediaPlayer = null;
private SeekBar seekbar = null;
private boolean playFlag = true; // 播放标记
private boolean pauseFlag = true; // 暂停标记
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.info = (TextView) super.findViewById(R.id.info);
this.play = (ImageButton) super.findViewById(R.id.play);
this.pause = (ImageButton) super.findViewById(R.id.pause);
this.stop = (ImageButton) super.findViewById(R.id.stop);
this.seekbar = (SeekBar) super.findViewById(R.id.seekbar);
this.play.setOnClickListener(new PlayOnClickListener());
this.pause.setOnClickListener(new PauseOnClickListener());
this.stop.setOnClickListener(new StopOnClickListener());
this.seekbar
.setOnSeekBarChangeListener(new OnSeekBarChangeListenerImpl());
}
private class UpdateSeekBar extends AsyncTask<Integer, Integer, String> {
@Override
protected void onPostExecute(String result) {//任务执行完后执行
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Integer... values) {//每次更新后的数值
MediaPlayer01_Mp3PlayerActivity.this.seekbar.setProgress(values[0]);//更新拖动条
}
@Override
protected String doInBackground(Integer... params) {//处理后台任务
while (MediaPlayer01_Mp3PlayerActivity.this.playFlag) { // 播放的话,进度要累加
try {
Thread.sleep(params[0]);//延缓执行
} catch (InterruptedException e) {
}
this.publishProgress(MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer
.getCurrentPosition());//修改拖动条
}
return null;//返回执行结果
}
}
private class PlayOnClickListener implements OnClickListener {
@Override
public void onClick(View v) {
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer = MediaPlayer
.create(MediaPlayer01_Mp3PlayerActivity.this, R.raw.hight); // 要播放的文件
if (MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer != null) {
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.stop(); // 停止操作
}
MediaPlayer01_Mp3PlayerActivity.this.seekbar
.setMax(MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer
.getDuration()); // 设置拖拽条的长度
UpdateSeekBar update = new UpdateSeekBar();
update.execute(500);
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer
.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
MediaPlayer01_Mp3PlayerActivity.this.playFlag = false; // 播放完毕
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer
.release(); // 释放资源
}
});
try {
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.prepare();
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.start();
MediaPlayer01_Mp3PlayerActivity.this.info
.setText("正在播放音频文件...");
} catch (Exception e) {
MediaPlayer01_Mp3PlayerActivity.this.info.setText("文件播放出现异常,"
+ e);
}
}
}
private class PauseOnClickListener implements OnClickListener {
@Override
public void onClick(View v) {
if (MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer != null) {
if (MediaPlayer01_Mp3PlayerActivity.this.pauseFlag) { // 现在暂停
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.start();
MediaPlayer01_Mp3PlayerActivity.this.pauseFlag = false;
} else {
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.pause(); // 暂停
MediaPlayer01_Mp3PlayerActivity.this.pauseFlag = true;
MediaPlayer01_Mp3PlayerActivity.this.info
.setText("暂停音频文件...");
}
}
}
}
private class StopOnClickListener implements OnClickListener {
@Override
public void onClick(View v) {
if (MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer != null) {
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.stop(); // 停止
MediaPlayer01_Mp3PlayerActivity.this.info
.setText("停止播放音频文件...");
}
}
}
private class OnSeekBarChangeListenerImpl implements
OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {//进度条停止拖拽
MediaPlayer01_Mp3PlayerActivity.this.mediaPlayer.seekTo(seekBar
.getProgress());//定义播放位置
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/info" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="等待音频文件播放" /> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageButton android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" /> <ImageButton android:id="@+id/pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pause" /> <ImageButton android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/stop" /> </LinearLayout> <SeekBar android:id="@+id/seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
MediaPlayer 除了可以播放音频之外,还可以播放视频,但是如果要视频,只依靠 MediaPlayer 是不够的,还需要编写一个可以用于视频显示的控件,而这块显示空间要求可以快速进行 GUI 的更新,而且可以在渲染代码时对 GUI 进行无阻塞的渲染,如果要完成此功能,则必须依靠 android.view.SurfaceView 组件, SurfaceView 组件封装了一个 Surface 对象,而不是一个 Canvas 对象,使用 Surface 可以完成对后台线程的控制,对于视频、 3D 是图形等需要快速更新或者高帧率的对象有很大的用处。
视频播放 Demo
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageButton android:id="@+id/play" android:src="@drawable/play" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageButton android:id="@+id/stop" android:src="@drawable/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <SurfaceView android:id="@+id/surfaceView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
对于 SurfaceView 现在只是一个基本的使用,而关于它的更多应用,会在后面说拍照等功能实现的时候再深入。
如果要想操作 SurfaceView ,那么就必须对其做一些基本的设置,设置其操作类型,如果要想设置 SurfaceView 的一些参数,那么就必须依靠 SurfaceHolder 类完成。
MediaPlayer02_VideoPlayerActivity.java
package com.iflytek.demo;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
public class MediaPlayer02_VideoPlayerActivity extends Activity {
private ImageButton play = null;
private ImageButton stop = null;
private MediaPlayer mediaPlayer = null;
private SurfaceView surfaceView = null;
private SurfaceHolder surfaceHolder = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.play = (ImageButton) super.findViewById(R.id.play);
this.stop = (ImageButton) super.findViewById(R.id.stop);
this.surfaceView = (SurfaceView) super.findViewById(R.id.surfaceView);
this.surfaceHolder = this.surfaceView.getHolder();// 取得SurfaceHolder
this.surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 设置SurfaceView的类型
this.mediaPlayer = new MediaPlayer();// 创建MediaPlayer对象
try {
this.mediaPlayer.setDataSource("/sdcard/test.3gp"); // 设置播放文件的路径,这里就没有判断sdcard是否存在了
} catch (Exception e) {
e.printStackTrace();
}
this.play.setOnClickListener(new PlayOnClickListenerImpl());
this.stop.setOnClickListener(new StopOnClickListenerImpl());
}
private class PlayOnClickListenerImpl implements OnClickListener {
@Override
public void onClick(View v) {
MediaPlayer02_VideoPlayerActivity.this.mediaPlayer
.setAudioStreamType(AudioManager.STREAM_MUSIC);// 设置音频类型
MediaPlayer02_VideoPlayerActivity.this.mediaPlayer
.setDisplay(MediaPlayer02_VideoPlayerActivity.this.surfaceHolder);// 设置显示区域
try {
MediaPlayer02_VideoPlayerActivity.this.mediaPlayer.prepare();// 预备状态
MediaPlayer02_VideoPlayerActivity.this.mediaPlayer.start();// 播放视频
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class StopOnClickListenerImpl implements OnClickListener {
@Override
public void onClick(View v) {
MediaPlayer02_VideoPlayerActivity.this.mediaPlayer.stop();// 停止播放
}
}
}