我正在尝试创建一个从前置摄像头录制视频的 Android 应用程序。预览工作正常,但一旦我开始录制应用程序崩溃并出现错误“java.lang.RuntimeException:启动失败”。我用后置摄像头尝试了同样的方法,但它有同样的问题。我正在使用运行 Android ICS 4.0.3 的三星 Tab 2 P5110。
这是我的 Activity 类,它显示预览并且应该开始录制。
import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; import android.app.Activity; import android.content.Intent; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Bundle; import android.os.CountDownTimer; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.FrameLayout; public class VideoActivity extends Activity implements OnClickListener, SurfaceHolder.Callback, MediaRecorder.OnInfoListener { MediaRecorder recorder; SurfaceHolder holder; Camera camera; boolean recording = false; public static final String TAG = "VIDEOCAPTURE"; private int show_id; private CamcorderProfile mProfile; private CountDownTimer cdt = null; private static final int max_length_in_ms = 30000; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature( Window.FEATURE_NO_TITLE ); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN ); show_id = getIntent().getIntExtra(Database.SHOW_ID, -1); camera = this.openFrontFacingCamera(); // frontfacing camera camera = camera.open(); //rearfacing recorder = new MediaRecorder(); recorder.setCamera(camera); setContentView(R.layout.video); FrameLayout cameraView = (FrameLayout) findViewById(R.id.CameraView); CameraSurfaceView cameraSurface = new CameraSurfaceView(getBaseContext(), camera); cameraView.addView(cameraSurface); holder = cameraSurface.getHolder(); cameraView.setClickable(true); findViewById(R.id.recBtn).setOnClickListener(this); } private void initRecorder() { recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)); recorder.setOutputFile("/sdcard/videotemp.mp4"); recorder.setMaxDuration(VideoActivity.max_length_in_ms); recorder.setMaxFileSize(50000000); // Approximately 50 megabytes } private void prepareRecorder() { recorder.setPreviewDisplay(holder.getSurface()); try { recorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); finish(); } catch (IOException e) { e.printStackTrace(); finish(); } } public void onClick(View v) { if (recording) { recorder.stop(); recorder.release(); recording = false; camera.release(); Log.v(TAG, "Recording Stopped"); // Let's initRecorder so we can record again Intent intent = new Intent(this, UploadActivity.class); intent.putExtra(Database.SHOW_ID, show_id); intent.putExtra(Database.FILENAME, "/sdcard/videotemp.mp4"); intent.putExtra(Database.EXTENTION, ".mp4"); startActivity(intent); finish(); } else { recording = true; initRecorder(); prepareRecorder(); recorder.start(); ProgressBar pb = (ProgressBar) findViewById(R.id.videoProgress); pb.setMax(VideoActivity.max_length_in_ms); this.cdt = new CountDownTimer(VideoActivity.max_length_in_ms, 50) { public void onTick(long millisUntilFinished) { ProgressBar pb = (ProgressBar) findViewById(R.id.videoProgress); pb.setProgress( VideoActivity.max_length_in_ms - (int)((millisUntilFinished) )); } public void onFinish() { ProgressBar pb = (ProgressBar) findViewById(R.id.videoProgress); pb.setProgress(100); } }; this.cdt.start(); Log.v(TAG, "Recording Started"); } } private Camera openFrontFacingCamera() { Camera camera = null; // Look for front-facing camera, using the Gingerbread API. // Java reflection is used for backwards compatibility with // pre-Gingerbread APIs. try { Class<?> cameraClass = Class.forName("android.hardware.Camera"); Object cameraInfo = null; Field field = null; int cameraCount = 0; Method getNumberOfCamerasMethod = cameraClass .getMethod("getNumberOfCameras"); if (getNumberOfCamerasMethod != null) { cameraCount = (Integer) getNumberOfCamerasMethod.invoke(null, (Object[]) null); } Class<?> cameraInfoClass = Class .forName("android.hardware.Camera$CameraInfo"); if (cameraInfoClass != null) { cameraInfo = cameraInfoClass.newInstance(); } if (cameraInfo != null) { field = cameraInfo.getClass().getField("facing"); } Method getCameraInfoMethod = cameraClass.getMethod("getCameraInfo", Integer.TYPE, cameraInfoClass); if (getCameraInfoMethod != null && cameraInfoClass != null && field != null) { for (int camIdx = 0; camIdx < cameraCount; camIdx++) { getCameraInfoMethod.invoke(null, camIdx, cameraInfo); int facing = field.getInt(cameraInfo); if (facing == 1) { // Camera.CameraInfo.CAMERA_FACING_FRONT try { Method cameraOpenMethod = cameraClass.getMethod( "open", Integer.TYPE); if (cameraOpenMethod != null) { camera = (Camera) cameraOpenMethod.invoke(null, camIdx); mProfile = CamcorderProfile .get(camIdx, CamcorderProfile.QUALITY_LOW); } } catch (RuntimeException e) { Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage()); } } } } } // Ignore the bevy of checked exceptions the Java Reflection API throws // - if it fails, who cares. catch (ClassNotFoundException e) { Log.e(TAG, "ClassNotFoundException" + e.getLocalizedMessage()); } catch (NoSuchMethodException e) { Log.e(TAG, "NoSuchMethodException" + e.getLocalizedMessage()); } catch (NoSuchFieldException e) { Log.e(TAG, "NoSuchFieldException" + e.getLocalizedMessage()); } catch (IllegalAccessException e) { Log.e(TAG, "IllegalAccessException" + e.getLocalizedMessage()); } catch (InstantiationException e) { Log.e(TAG, "InstantiationException" + e.getLocalizedMessage()); } catch (SecurityException e) { Log.e(TAG, "SecurityException" + e.getLocalizedMessage()); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (camera == null) { // Try using the pre-Gingerbread APIs to open the camera. try { camera = Camera.open(); } catch (RuntimeException e) { Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage()); } } return camera; } }
对于预览,我正在使用 SurfaceView 的扩展版本
package nl.raakict.android.VideoCapture; import java.io.IOException; import android.content.Context; import android.hardware.Camera; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraSurfaceView(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d("DEBUG", "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d("DEBUG", "Error starting camera preview: " + e.getMessage()); } } }
任何帮助将不胜感激。