之前写好的工具类,直接封装好了,代码如下:
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) { } });
新闻热点
疑难解答