之前寫好的工具類,直接封裝好了,代碼如下:
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) { } });
新聞熱點
疑難解答