Process: com.example.mycamera2, PID: 24086 java.lang.RuntimeException: start failed. at android.media.MediaRecorder.native_start(Native Method) at android.media.MediaRecorder.start(MediaRecorder.java:1157) at com.example.mycamera2.CameraUtils.startRecord(CameraUtils.java:161) at com.example.mycamera2.MainActivity$1.onClick(MainActivity.java:88) at android.view.View.performClick(View.java:5264) at android.view.View$PerformClick.run(View.java:21297) at android.os.Handler.handleCallback(Handler.java:743) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:150) at android.app.ActivityThread.main(ActivityThread.java:5621) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
code:
package com.example.mycamera2; import android.content.Context; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaCodec; import android.media.MediaRecorder; import android.os.Environment; import android.os.StatFs; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.io.File; import java.io.IOException; import java.util.List; import static android.content.ContentValues.TAG; /** * Created by guoxw on 2017/10/31. */ public class CameraUtils { private MediaRecorder mediaRecorder; private Camera camera; private boolean isCheck; private SurfaceHolder.Callback callback; private Context context; private SurfaceView surfaceView; private int height=240,width=300; private MediaCodec mediaCodec; public void create(SurfaceView surfaceView, Context context) { this.context = context; this.surfaceView = surfaceView; surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.setKeepScreenOn(true); callback = new SurfaceHolder.Callback() { public void surfaceCreated(SurfaceHolder holder) { camera = Camera.open(); getVideoSize(); //setVideoFrameRate(); mediaRecorder = new MediaRecorder(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { doChange(holder); // setVideoFrameRate(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { if(camera!=null){ camera.release(); camera=null; } } }; surfaceView.getHolder().addCallback(callback); } private void doChange(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.setDisplayOrientation(0); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } /** * startRecord 前调用一次,保证为前置摄像头 */ public void changeCamera() { int cameraCount = 0; Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); cameraCount = Camera.getNumberOfCameras(); for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo); if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { camera.stopPreview(); camera.release(); camera = null; camera = Camera.open(i); try { camera.setPreviewDisplay(surfaceView.getHolder()); camera.setDisplayOrientation(0); } catch (IOException e) { e.printStackTrace(); } camera.startPreview(); isCheck = true; break; } } } public void stopRecord() { mediaRecorder.release(); /****/ camera.stopPreview(); camera.release(); mediaRecorder = null; camera = Camera.open(); mediaRecorder = new MediaRecorder(); doChange(surfaceView.getHolder()); } public void destroy(){ if(mediaRecorder!=null&&camera!=null){ mediaRecorder.release(); camera.release(); mediaRecorder = null; camera=null; } } /** * * @param path 保存的路径 * @param name 录像视频名称(不包含后缀) */ public void startRecord(String path, String name) { camera.unlock(); mediaRecorder.setCamera(camera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //--mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //--好像不起作用 //mediaRecorder.setVideoFrameRate(14); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setVideoEncodingBitRate(500*1024); mediaRecorder.setVideoSize(width, height); // setVideoFrameRate(); // mediaRecorder.setVideoFrameRate(14); //--getVideoSize(); File file = new File(path); if (!file.exists()) { file.mkdirs(); } mediaRecorder.setOutputFile(path + File.separator + name + ".mp4"); File file1=new File(path + File.separator + name + ".mp4"); if(file1.exists()){ file1.delete(); } mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); /***不设置时,录制的视频总是倒着,翻屏导致视频上下翻滚*/ mediaRecorder.setOrientationHint(0); try { mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "startRecord: --"+e.getMessage()); } } /*** * 获取SupportedVideoSizes 控制输出视频width在300到600之间,选择最小的 */ public void getVideoSize(){ Camera.Parameters parameters=camera.getParameters(); List<Camera.Size> videoSize=parameters.getSupportedVideoSizes(); if(videoSize!=null){ for(int i=0;i<videoSize.size();i++){ int width1=videoSize.get(i).width; int height1=videoSize.get(i).height; if(width1>=300&&width1<=500){ if(height1>=200&&height1<=500){ width=width1; height=height1; break; } } Log.d(TAG, "getVideoSize:----w:-- "+videoSize.get(i).width+"---h:--"+videoSize.get(i).height); } } } /** * 没用 */ public void setVideoFrameRate(){ CamcorderProfile cProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_LOW); mediaRecorder.setProfile(cProfile); //设置录制的视频帧率,注意文档的说明: mediaRecorder.setVideoFrameRate(20); } /** * 获取手机内存可用大小 (返回kb值) */ public long getAvailableBlicks(){ File path = Environment.getDataDirectory(); StatFs stat = new StatFs(path.getPath()); long blockSize = stat.getBlockSize(); long Blocks = stat.getAvailableBlocks(); long size=blockSize*Blocks/1024; return size; } }
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(x==0){ cameraUtils.changeCamera(); cameraUtils.startRecord(path,name); image.setVisibility(View.INVISIBLE); btn.setImageResource(R.drawable.camera_begain); x=1; } else if(x==1){ cameraUtils.stopRecord(); image.setVisibility(View.VISIBLE); btn.setImageResource(R.drawable.camera_stop); x=0; } } });
结论:
方法: public void getVideoSize()获取手机支持的分辨率时,获得到的 List<Camera.Size> videoSize这个
结果集为null,导致seartRecord方法中的 mediaRecorder.setVideoSize(width, height)设置的宽高不支持。
至于getVideoSize返回为null的原因,待查。
public List<Size> getSupportedVideoSizes() { String str = get(KEY_VIDEO_SIZE + SUPPORTED_VALUES_SUFFIX); return splitSize(str); } private ArrayList<Size> splitSize(String str) { if (str == null) return null; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); ArrayList<Size> sizeList = new ArrayList<Size>(); for (String s : splitter) { Size size = strToSize(s); if (size != null) sizeList.add(size); } if (sizeList.size() == 0) return null; return sizeList; }