Android10+用Camera2 API+MediaRecorder录像prepare报-2147483648错误
问题根因与解决方案
1. 前台服务配置修正(你猜测的点是核心原因之一)
Android 10(API 29)及以上版本要求,使用前台服务访问相机、麦克风时必须显式声明服务类型:
- 修改
AndroidManifest.xml中服务声明,添加foregroundServiceType属性:
<service android:name="xyz.kumaraswamy.procam.CameraService" android:exported="true" android:foregroundServiceType="camera|microphone"/>
- 调用
startForeground启动服务时,Android 10及以上版本需要传入对应服务类型参数:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { startForeground(通知ID, 通知实例, ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE); } else { startForeground(通知ID, 通知实例); }
2. MediaRecorder参数设置错误
你当前的参数设置顺序不符合MediaRecorder的要求,且存在冗余调用,是日志中Failed to create video encoder的直接原因:
- 必须先设置音视频编码器,再设置编码器相关的参数(比特率、分辨率、帧率)
- 使用
VideoSource.SURFACE配合Camera2 API时,不需要调用setPreviewDisplay,该方法是旧Camera1 API的接口,会引发Surface冲突
修正后的参数配置代码:
mediaRecorder = new MediaRecorder(); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // 先设置编码器 mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 再设置编码器相关参数 mediaRecorder.setVideoSize(videoDimension.getWidth(), videoDimension.getHeight()); mediaRecorder.setVideoFrameRate(30); mediaRecorder.setVideoEncodingBitRate(1000000); mediaRecorder.setOutputFile(new File(recordingPath).getAbsolutePath()); // 删除下面这行冗余代码 // mediaRecorder.setPreviewDisplay(this.previewSurface);
3. 分区存储适配
如果你的录像文件保存路径是外部公共目录(比如DCIM、Download目录),Android 10及以上版本不能直接用普通File路径写入,会导致输出文件创建失败,触发prepare错误:
- 保存到公共目录需要使用MediaStore创建文件,传入文件描述符给MediaRecorder:
ContentValues values = new ContentValues(); values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/你的应用目录名"); values.put(MediaStore.Video.Media.MIME_TYPE, "video/3gpp"); values.put(MediaStore.Video.Media.DISPLAY_NAME, "record_" + System.currentTimeMillis() + ".3gp"); Uri uri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values); ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "w"); mediaRecorder.setOutputFile(pfd.getFileDescriptor());
如果是保存到应用私有目录(/data/data/包名/xxx)则不需要做该适配。
4. 可选:参数合法性校验
可以调用CamcorderProfile.hasProfile(摄像头ID, CamcorderProfile.QUALITY_XXX)确认当前设备的摄像头支持你设置的分辨率、帧率、编码器组合,避免设置了设备不支持的参数导致编码器创建失败。
内容的提问来源于stack exchange,提问作者Alien tackers
相关产品推荐
相关产品推荐

