使用mediaRecorder录像的小坑

之前写好的工具类,直接封装好了,代码如下:

package jun.yuanlai;

import android.content.Context;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by cj on 2016/11/29.
 */

public class Recorderutil {
    private static final String TAG = "cj";

    Context context;
    private MediaRecorder mediaRecorder;
    private SurfaceView sv_view;
    private boolean isRecording;
    private int time;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            sv_view.setVisibility(View.GONE);
            Toast.makeText(context, "停止录像,并保存文件", Toast.LENGTH_SHORT).show();
        }
    };

    public Recorderutil(Context context, MediaRecorder mediaRecorder, SurfaceView sv_view, int time) {
        this.context = context;
        this.mediaRecorder = mediaRecorder;
        this.sv_view = sv_view;
        this.time = time;
    }

    public void startRecord() {
        //准备名字
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
        String format = dateFormat.format(date);
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        String name = path + "/" + format + ".mp4";
        //准备好了
        sv_view.setVisibility(View.VISIBLE);

        try {
            File file = new File(name);
            if (file.exists()) {
                // 如果文件存在,删除它,演示代码保证设备上只有一个录音文件
                file.delete();
            }

            mediaRecorder = new MediaRecorder();
//			mediaRecorder.reset();

//            mediaRecorder.setCamera(Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT));
            // 设置音频录入源
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            // 设置视频图像的录入源
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            Log.e(TAG, "start: 输出格式");
            // 设置录入媒体的输出格式
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            // 设置音频的编码格式
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
            // 设置视频的编码格式
//			mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            // 设置视频的采样率,每秒4帧
            mediaRecorder.setVideoFrameRate(4);

            // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错
//			mediaRecorder.setVideoSize(240, 240);
            //一换这个6.0就走起来了
            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);

            mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
//			mediaRecorder.setVideoEncodingBitRate(640*480);
            // 设置录制视频文件的输出路径
            Log.e(TAG, "start: 输出路径");
            mediaRecorder.setOutputFile(file.getAbsolutePath());
            // 设置捕获视频图像的预览界面
            mediaRecorder.setPreviewDisplay(sv_view.getHolder().getSurface());
//			mediaRecorder.setOrientationHint(180);// 视频旋转

            Log.e(TAG, "start: surfaceholder也有了");
            mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {

                @Override
                public void onError(MediaRecorder mr, int what, int extra) {
                    Log.e(TAG, "onError: 录制出错");
                    // 发生错误,停止录制
                    mediaRecorder.stop();
                    mediaRecorder.release();
                    mediaRecorder = null;
                    isRecording = false;

                    Toast.makeText(context, "录制出错", Toast.LENGTH_SHORT).show();
                }
            });

            // 准备、开始
            mediaRecorder.prepare();
            Log.e(TAG, "start: 不走了");
            mediaRecorder.start();
            Log.e(TAG, "start: 也开始了");

            isRecording = true;
            Toast.makeText(context, "开始录像", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "startRecord: "+e.toString() );
        }

        //录制5秒后自动停止
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                stopRecord();
            }
        },time);
    }

    public  void stopRecord(){
        if (isRecording) {
            // 如果正在录制,停止并释放资源
            mediaRecorder.stop();
            mediaRecorder.release();
            mediaRecorder = null;
            isRecording=false;

            new Thread(new Runnable() {
                @Override
                public void run() {
                    handler.sendEmptyMessage(0);
                }
            }).start();
        }else{
            Log.e(TAG, "已经停止录制" );
        }
    }

}


我调用的时候直接使用这两句就可以了;如下:

MediaRecorder mediaRecorder = new MediaRecorder();
                Recorderutil recorderutil = new Recorderutil(this,mediaRecorder,surfaceview,10000);
                recorderutil.startRecord();

通过按钮调用的时候,我的红米是4.4.2的系统,会弹出一个请求访问相机的对话框,允许之后就可以直接开始录像了,但是蹊跷的是如果不通过button调用,

会出现问题就是mediarecorder启动不了,会执行异常catch块,报的错误是invalid preview surface,意思就是无效的surfaceview,但是为什么会出现那样的问题呢?至今没有想明白,只好百度,不得不说,会点英语还是挺好的,中国的博客没有一个解释清楚的,结果又一个stackoverflow网站上,有这个问题,好好研读了一下,原因就是surfaceview还没有初始化好呢,就调用了 mediaRecorder.setPreviewDisplay(holder.getSurface());解决方法就是等surfaceview完全创建之后再进行调用,所以就需要改代码,改成在activity里调用的时候先getholder,在create回调里面进行录制视频,就好了

SurfaceHolder holder = surfaceview.getHolder();
                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
                holder.addCallback(new SurfaceHolder.Callback() {
                    @Override
                    public void surfaceCreated(SurfaceHolder holder) {
                        surfaceHolder = holder;
                        MediaRecorder mediaRecorder = new MediaRecorder();
                        Recorderutil recorderutil = new Recorderutil(MainActivity.this,mediaRecorder,surfaceHolder,10000);
                        recorderutil.startRecord();

                    }

                    @Override
                    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

                    }

                    @Override
                    public void surfaceDestroyed(SurfaceHolder holder) {

                    }
                });



 
  

你可能感兴趣的:(android)