之前写好的工具类,直接封装好了,代码如下:
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) {
}
});