<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/widget34" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:context=".MainActivity" > <EditText android:id="@+id/et_src" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请输入资源路径……" android:textSize="18sp" /> <SeekBar android:id="@+id/seekBar_progress" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/widget35" android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btn_play" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="播放" /> <Button android:id="@+id/btn_pause" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="暂停" /> <Button android:id="@+id/btn_replay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="01" android:text="重播" /> <Button android:id="@+id/btn_stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="停止" /> </LinearLayout> <SurfaceView android:id="@+id/sfView" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
package com.pas.video.play; import java.io.File; import java.util.Timer; import java.util.TimerTask; import com.pas.video.play.R; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private EditText et_mediaSrc; private Button bt_play, bt_pause, bt_replay, bt_stop; private SurfaceView sv; private SeekBar seekBar_progress; private Timer timer; private TimerTask timerTask; /** * 互斥变量 解决进度条手动改变 与进度条线程中run方法自动改变之间的冲突 */ private Boolean ischanging = false; // 媒体对象 private MediaPlayer mediaPlayer; private int currentPosition = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_mediaSrc = (EditText) findViewById(R.id.et_src); sv = (SurfaceView) findViewById(R.id.sfView); seekBar_progress = (SeekBar) findViewById(R.id.seekBar_progress); seekBar_progress.setOnSeekBarChangeListener(new MySeekListener()); // 设置SurfaceView不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送用户界面 // 低版本必须 4.0之上无需设置 sv.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 应用最小化后的处理与恢复处理 sv.getHolder().addCallback(new Callback() { // 最小化后 系统自动销毁surfaceview中的holder对象 // 保存进度 @Override public void surfaceDestroyed(SurfaceHolder holder) { System.out.println("Holder销毁"); if (mediaPlayer != null && mediaPlayer.isPlaying()) { currentPosition = mediaPlayer.getCurrentPosition(); stop(); } } @Override public void surfaceCreated(SurfaceHolder holder) { System.out.println("Holder创建"); if (currentPosition > 0) { play(currentPosition); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { System.out.println("Holder大小改变"); } }); bt_play = (Button) findViewById(R.id.btn_play); bt_pause = (Button) findViewById(R.id.btn_pause); bt_replay = (Button) findViewById(R.id.btn_replay); bt_stop = (Button) findViewById(R.id.btn_stop); bt_play.setOnClickListener(this); bt_pause.setOnClickListener(this); bt_replay.setOnClickListener(this); bt_stop.setOnClickListener(this); et_mediaSrc.setText(Environment.getExternalStorageDirectory() + "/2.mp4"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private void showToast(String info) { Toast.makeText(this, info, Toast.LENGTH_SHORT).show(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_play: play(0); break; case R.id.btn_pause: pause(); break; case R.id.btn_replay: rePlay(); break; case R.id.btn_stop: stop(); break; default: break; } } /** * 开启进度条 */ private void seekBarChanging() { seekBar_progress.setMax(mediaPlayer.getDuration()); seekBar_progress.setProgress(currentPosition); timer = new Timer(); timerTask = new TimerTask() { @Override public void run() { if (ischanging == true) { return; } seekBar_progress.setProgress(mediaPlayer.getCurrentPosition()); } }; timer.schedule(timerTask, 0, 10); } /** * 初始化进度条 */ private void initSeekBar() { timer.cancel(); seekBar_progress.setProgress(0); } /** * 播放 正常应写在服务中 * * @param currentPosition2 */ private void play(final int Position) { String path = et_mediaSrc.getText().toString().trim(); File file = new File(path); if (file.exists()) { if (mediaPlayer != null) { mediaPlayer.stop(); // 释放资源 mediaPlayer.release(); mediaPlayer = null; } mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); try { // 指定video播放容器 // 播放视频只多一行 mediaPlayer.setDisplay(sv.getHolder()); mediaPlayer.setDataSource(path); // 异步的准备 不阻塞主线程 但需要注册准备完毕的回调函数 mediaPlayer.prepareAsync(); // 回调 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 进度条 mediaPlayer.start(); mediaPlayer.seekTo(Position); seekBarChanging(); } }); // 播放完毕的回调函数 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 播放完毕后设置播放按钮可用 bt_play.setEnabled(true); initSeekBar(); } }); // 播放中出现错误(如流损坏)的回调函数 mediaPlayer.setOnErrorListener(new OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { stop(); return false; } }); // 播放开始后设置播放按钮不可用 bt_play.setEnabled(false); } catch (Exception e) { showToast("播放失败"); } } else { showToast("文件不存在"); } } /** * 停止播放并回收资源 */ private void stop() { if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { // 转到开头并关闭对象 mediaPlayer.seekTo(0); mediaPlayer.stop(); } // 释放进度条线程 initSeekBar(); // 释放资源 mediaPlayer.release(); mediaPlayer = null; // 播放完毕后设置播放按钮可用 bt_play.setEnabled(true); } } /** * 重新播放 */ private void rePlay() { if (bt_pause.getText().equals("继续")) { bt_pause.setText("暂停"); } if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.seekTo(0); } else { stop(); play(0); } } /** * 暂停播放 */ private void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); bt_pause.setText("继续"); } else if (bt_pause.getText().equals("继续")) { mediaPlayer.start(); bt_pause.setText("暂停"); } else { showToast("当前未播放"); } } /** * 进度条手动处理 */ private class MySeekListener implements OnSeekBarChangeListener { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mediaPlayer == null) { return; } if (fromUser) { // 如果用户拖动才执行 否则造成进度条线程 多重调用 ischanging = true; mediaPlayer.seekTo(progress); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { ischanging = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (mediaPlayer == null) { return; } mediaPlayer.seekTo(seekBar.getProgress()); ischanging = false; } } }