Xamarin.Android中Camera2+MediaRecorder录制启动失败问题求助
使用Xamarin.Android的Camera2组件开发短视频录制应用,调用后置摄像头,已成功选择并打开相机,但调用mediaRecorder.Start()时抛出Java.Lang.RuntimeException: start failed,伴随扬声器响声,测试设备为Techno Spark 4(Android 9)。
已实现的相机初始化代码:
// Create an instance of CameraManager CameraManager manager = (CameraManager)Android.App.Application.Context.GetSystemService(Context.CameraService); string cameraId = null; // Get the ID of the back-facing camera App.cameraId = manager.GetCameraIdList().FirstOrDefault(id => (int)manager.GetCameraCharacteristics(id).Get(CameraCharacteristics.LensFacing) == (int)LensFacing.Back); // Create an instance of CameraDevice CameraDevice cameraDevice = null; manager.OpenCamera(cameraId, new MyCameraDeviceStateCallback(this), null);
MediaRecorder配置代码:
// Create a new instance of MediaRecorder MediaRecorder mediaRecorder = new MediaRecorder(); // Set the video source to the camera mediaRecorder.SetVideoSource(VideoSource.Camera); // Set the output format and file path mediaRecorder.SetOutputFormat(OutputFormat.Default); mediaRecorder.SetOutputFile(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal).ToString() + "/video.mp4"); // Set the video encoder mediaRecorder.SetVideoEncoder(VideoEncoder.Default); // Prepare and start recording mediaRecorder.Prepare(); mediaRecorder.Start();
错误栈信息:
Java.Lang.RuntimeException: start failed.
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod(...)
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod(...)
at Android.Media.MediaRecorder.Start ()
...
--- End of managed Java.Lang.RuntimeException stack trace ---
java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)
- Camera2与MediaRecorder未绑定:Camera2组件需要将相机输出Surface与MediaRecorder的Surface关联,直接启动MediaRecorder会导致相机资源未正确分配。
- MediaRecorder配置不完整:缺少视频尺寸、帧率等关键参数,Android 9设备对MediaRecorder的配置要求更严格,使用
Default选项可能无法匹配相机硬件支持的格式。 - 相机会话未正确初始化:CameraDevice打开后需创建
CameraCaptureSession,并将MediaRecorder的Surface加入会话配置,否则相机无法向MediaRecorder输出数据。 - 权限与路径问题:需确保已申请
CAMERA和RECORD_AUDIO权限(即使不录制音频,部分设备仍需该权限),同时确认文件路径可写入。
1. 完善权限配置
在AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
运行时动态申请权限(Android 6+):
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != Permission.Granted || ContextCompat.CheckSelfPermission(this, Manifest.Permission.RecordAudio) != Permission.Granted) { ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.Camera, Manifest.Permission.RecordAudio }, 100); }
2. 正确关联Camera2与MediaRecorder
修改MyCameraDeviceStateCallback,在相机打开后创建CaptureSession并绑定MediaRecorder的Surface:
public class MyCameraDeviceStateCallback : CameraDevice.StateCallback { private readonly YourActivity _activity; private CameraDevice _cameraDevice; private MediaRecorder _mediaRecorder; public MyCameraDeviceStateCallback(YourActivity activity) { _activity = activity; } public override void OnOpened(CameraDevice camera) { _cameraDevice = camera; InitializeMediaRecorder(); CreateCaptureSession(); } private void InitializeMediaRecorder() { _mediaRecorder = new MediaRecorder(); _mediaRecorder.SetVideoSource(VideoSource.Camera); _mediaRecorder.SetOutputFormat(OutputFormat.Mpeg4); string outputPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "video.mp4"); _mediaRecorder.SetOutputFile(outputPath); // 获取相机支持的视频尺寸 var characteristics = _activity.GetSystemService<CameraManager>().GetCameraCharacteristics(App.cameraId); var configs = characteristics.Get(CameraCharacteristics.ScalerStreamConfigurationMap); var videoSize = configs.GetOutputSizes(Class.FromType(typeof(MediaRecorder)))[0]; _mediaRecorder.SetVideoSize(videoSize.Width, videoSize.Height); _mediaRecorder.SetVideoFrameRate(30); _mediaRecorder.SetVideoEncoder(VideoEncoder.H264); // 可选:若不需要音频可注释,但部分设备需保留 _mediaRecorder.SetAudioSource(AudioSource.Mic); _mediaRecorder.SetAudioEncoder(AudioEncoder.Aac); try { _mediaRecorder.Prepare(); } catch (IOException ex) { // 处理准备失败异常 } } private void CreateCaptureSession() { Surface recorderSurface = _mediaRecorder.Surface; List<Surface> surfaces = new List<Surface> { recorderSurface }; _cameraDevice.CreateCaptureSession(surfaces, new CameraCaptureSession.StateCallback() { public override void OnConfigured(CameraCaptureSession session) { try { var captureRequestBuilder = _cameraDevice.CreateCaptureRequest(CameraTemplate.Record); captureRequestBuilder.AddTarget(recorderSurface); captureRequestBuilder.Set(CaptureRequest.ControlAfMode, (int)ControlAFMode.ContinuousVideo); session.SetRepeatingRequest(captureRequestBuilder.Build(), null, null); _mediaRecorder.Start(); } catch (Exception ex) { // 处理启动失败异常 } } public override void OnConfigureFailed(CameraCaptureSession session) { // 处理会话配置失败 } }, null); } // 实现OnDisconnected、OnError等回调方法省略 }
3. 清理资源
录制结束后,正确释放MediaRecorder和Camera资源:
private void StopRecording() { try { _mediaRecorder.Stop(); _mediaRecorder.Reset(); _mediaRecorder.Release(); } catch (Exception ex) { // 处理停止异常 } _cameraDevice.Close(); }
- 必须在
CameraDevice.StateCallback.OnOpened回调中初始化MediaRecorder,避免相机未完全就绪时操作。 - 使用相机硬件支持的视频尺寸,避免直接设置不兼容的参数。
- Android 9设备需明确指定MediaRecorder的格式、编码器,避免使用
Default选项。
内容的提问来源于stack exchange,提问作者Md Idiake

