Android应用开发之视频播放器

资源:

ImageButton所用图片4张

Strings:
<string name="app_name">MyVideoPlayer</string>
    <string name="video_text">视频文件</string>
    <string name="notfoundsdcard_error">找不到Sd卡</string>
    <string name="notfoundfile_error">找不到视频文件</string>

布局


<?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:background="#FFFFCC"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/video_text" />

    <EditText
        android:id="@+id/videoFileEt"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="cat.3gp" />

    <TableLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:stretchColumns="*" >

        <TableRow >

            <ImageButton
                android:id="@+id/playBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/play" />

            <ImageButton
                android:id="@+id/pauseBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/pause" />

            <ImageButton
                android:id="@+id/resetBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/reset" />

            <ImageButton
                android:id="@+id/stopBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/stop" />
        </TableRow>
    </TableLayout>

    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="fill_parent"
        android:layout_height="240dip" />

</LinearLayout>

Activity

package cn.class3g.videoplayer;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
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.EditText;
import android.widget.ImageButton;
import android.widget.Toast;

public class VideoPlayerActivity extends Activity implements OnClickListener {

	private static final String TAG = "VideoPlayerActivity";
	private ImageButton playBtn, pauseBtn, resetBtn, stopBtn;
	private EditText fileEt;
	private SurfaceView videoSv;

	private MediaPlayer mediaPlayer;

	private SurfaceHolder holder;
	private int position = 0;
	File videoFile = null;
	

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		findViews();

		mediaPlayer = new MediaPlayer();
	}

	private void findViews() {
		fileEt = (EditText) this.findViewById(R.id.videoFileEt);
		playBtn = (ImageButton) this.findViewById(R.id.playBtn);
		pauseBtn = (ImageButton) this.findViewById(R.id.pauseBtn);
		resetBtn = (ImageButton) this.findViewById(R.id.resetBtn);
		stopBtn = (ImageButton) this.findViewById(R.id.stopBtn);

		playBtn.setOnClickListener(this);
		pauseBtn.setOnClickListener(this);
		resetBtn.setOnClickListener(this);
		stopBtn.setOnClickListener(this);

		videoSv = (SurfaceView) this.findViewById(R.id.surfaceView);
		holder = videoSv.getHolder();

		holder.setFixedSize(176, 144); // 设置分辨率
		/* 下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 */
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		//holder.addCallback(new SurfaceCallback());
	}

	public void onClick(View v) {

		if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) {
			String fileName = fileEt.getText().toString().trim();

			videoFile = new File(
					Environment.getExternalStorageDirectory(), fileName);
			if (videoFile.exists()) {
				try {
					switch (v.getId()) {
					case R.id.playBtn:
						playVideo(videoFile);
						break;
					case R.id.pauseBtn:
//						if(mediaPlayer.isPlaying()){
//							mediaPlayer.pause();
//						}else{
//							mediaPlayer.start();
//						}
						if(mediaPlayer.isPlaying()){
							position = mediaPlayer.getCurrentPosition();
							mediaPlayer.pause();
						}
						
						break;
					case R.id.resetBtn:
						if(mediaPlayer.isPlaying()){
							mediaPlayer.seekTo(0);
						}else{
							playVideo(videoFile);
						}
						break;
					case R.id.stopBtn:
						if(mediaPlayer.isPlaying()){
							mediaPlayer.stop();
						}
						break;
					}
				} catch (Exception e) {
					Log.e(TAG, e.toString());
				}

			} else {
				showToast(R.string.notfoundfile_error);
			}
		} else {
			showToast(R.string.notfoundsdcard_error);
		}
	}

	private void playVideo(File videoFile) throws IOException {
		mediaPlayer.reset();
		mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
		mediaPlayer.setDataSource(videoFile.getAbsolutePath());
		mediaPlayer.setDisplay(holder);
		mediaPlayer.prepare();
		mediaPlayer.start();
	}

	private void showToast(int resId) {
		Toast.makeText(this, resId, 1).show();
	}
}

解决来电显示问题

protected void onDestroy() {
		
		if(mediaPlayer != null){
			if(mediaPlayer.isPlaying()){
				mediaPlayer.stop();
			}
			mediaPlayer.release();
		}
		super.onDestroy();
	}

	protected void onPause() {
		if(mediaPlayer != null && !mediaPlayer.isPlaying()){
			position = mediaPlayer.getCurrentPosition();
			mediaPlayer.stop();
		}
		super.onPause();
	}

	protected void onResume() {
		if(position >0 && videoFile != null){
			try {
				playVideo(videoFile);
				Log.i(TAG,"position="+ position);
				mediaPlayer.seekTo(position);
				position = 0;
			} catch (IOException e) {
				Log.e(TAG,e.toString());
			}
			
		}
		
		super.onResume();
	}

问题:

       来电后返回后,只有声音,没有画面

原因:

       当前activity对象被遮挡后,SurfaceView对象被销毁,而activity重新显示时他的重建晚于onResume()方法的执行,所以此时只有声音而没有图象

 

 

解决SurfaceView的重建问题

Android应用开发之视频播放器_第1张图片

取消onPause和onResume,由下面方法代替

private final class SurfaceCallback implements Callback{

		public void surfaceCreated(SurfaceHolder holder) {
			if(position >0 && videoFile != null){
				try {
					playVideo(videoFile);
					Log.i(TAG,"position="+ position);
					mediaPlayer.seekTo(position);
					position = 0;
				} catch (IOException e) {
					Log.e(TAG,e.toString());
				}
			}
			Log.i(TAG, "surfaceCreated");
		}

		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			// TODO Auto-generated method stub
			
		}

		public void surfaceDestroyed(SurfaceHolder holder) {
			if(mediaPlayer != null && mediaPlayer.isPlaying()){
				position = mediaPlayer.getCurrentPosition();
				mediaPlayer.stop();
			}
			Log.i(TAG, "surfaceDestroyed");
		}
		
	}

为SurfaceView对象添加Callback对象

holder.addCallback(new SurfaceCallback());

问题:

       应用程序如处于后台,且系统需要内存时会把应用杀死,此时回到播放器界面,需要重新调用onCreate()方法,所以无法继续之前的播放。

 

解决内存不足时应用被杀死问题:

protected void onRestoreInstanceState(Bundle savedInstanceState) {
		position = savedInstanceState.getInt("position");
		String fn = savedInstanceState.getString("fileName");
		if(fn!=null){
			videoFile = new File(Environment.getExternalStorageDirectory(),fn);
		}
			
		super.onRestoreInstanceState(savedInstanceState);
	}

	protected void onSaveInstanceState(Bundle outState) {
		outState.putInt("position", position);
		outState.putString("fileName", videoFile.getName());
		super.onSaveInstanceState(outState);

注意:

1.        在2.1和2.2版本的模拟器中视频播放有bug,真机没事儿。

2.        有些视频文件,不能正常的调整播放位置(估计跟格式转换时索引丢失有关)。



你可能感兴趣的:(android,String,File,layout,null,callback)