Android Camera2 API开发实战:拍照录像应用实现

发布时间:2026/9/14 2:04:25
Android Camera2 API开发实战:拍照录像应用实现 1. 项目概述Android拍照录像应用开发这个基于Android Studio和Java语言的拍照录像软件源代码是一个完整的移动端多媒体采集解决方案。作为一名有多年Android开发经验的工程师我经常遇到需要快速实现基础拍照录像功能的需求场景。这个项目代码结构清晰封装了Camera2 API的核心功能适合作为二次开发的基础框架或学习Camera开发的参考案例。项目采用标准的MVC架构将相机预览、拍照控制、视频录制等功能模块化。核心优势在于对Android不同版本相机API的兼容处理以及针对常见设备差异性的适配方案。我在实际开发中发现很多团队在实现这类功能时容易忽略内存管理和线程调度的优化而这个项目在这些细节上处理得相当到位。2. 开发环境准备2.1 Android Studio配置要点建议使用最新稳定版的Android Studio当前为Giraffe版本配置时需要注意几个关键点Gradle版本兼容性在gradle-wrapper.properties中指定7.4以上的Gradle版本NDK配置如果涉及原生代码处理需要安装对应版本的NDKJava环境项目使用Java 17特性需确保IDE和Gradle都配置了正确的JDK版本常见问题如果遇到源发行版17需要目标发行版17的警告检查以下配置File → Project Structure → SDK Location中的JDK路径build.gradle中的compileOptions配置2.2 权限与设备兼容性处理在AndroidManifest.xml中需要声明以下权限uses-permission android:nameandroid.permission.CAMERA/ uses-permission android:nameandroid.permission.RECORD_AUDIO/ uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE/对于Android 6.0设备必须实现运行时权限申请。我封装了一个通用的权限检查工具类public class PermissionUtil { public static boolean checkAndRequest(Activity activity, String[] permissions) { ListString denied new ArrayList(); for (String perm : permissions) { if (ContextCompat.checkSelfPermission(activity, perm) ! PackageManager.PERMISSION_GRANTED) { denied.add(perm); } } if (!denied.isEmpty()) { ActivityCompat.requestPermissions(activity, denied.toArray(new String[0]), REQUEST_CODE); return false; } return true; } }3. 相机功能实现详解3.1 Camera2 API核心架构项目采用Camera2 API而非已废弃的Camera API主要架构包括CameraManager - 设备相机系统服务入口CameraCharacteristics - 相机特性查询CameraDevice - 具体的相机设备CameraCaptureSession - 捕获会话管理CaptureRequest - 捕获请求构建初始化相机的典型流程// 1. 获取CameraManager CameraManager manager (CameraManager) context.getSystemService(CAMERA_SERVICE); // 2. 遍历可用相机 for (String cameraId : manager.getCameraIdList()) { CameraCharacteristics characteristics manager.getCameraCharacteristics(cameraId); Integer facing characteristics.get(CameraCharacteristics.LENS_FACING); if (facing ! null facing CameraCharacteristics.LENS_FACING_BACK) { this.cameraId cameraId; break; } } // 3. 打开相机 manager.openCamera(cameraId, new CameraDevice.StateCallback() { Override public void onOpened(NonNull CameraDevice camera) { this.cameraDevice camera; createCaptureSession(); } // ...其他回调方法 }, backgroundHandler);3.2 预览画面实现预览画面通过TextureView实现关键步骤设置TextureView的SurfaceTextureListener在onSurfaceTextureAvailable回调中配置相机预览创建CaptureRequest.Builder设置预览目标Surface优化点根据设备支持的分辨率选择最佳预览尺寸处理屏幕旋转时的方向适配考虑不同屏幕宽高比的适配问题我常用的分辨率选择算法private Size chooseOptimalSize(Size[] choices, int width, int height) { ListSize bigEnough new ArrayList(); for (Size option : choices) { if (option.getWidth() width option.getHeight() height) { bigEnough.add(option); } } if (bigEnough.isEmpty()) { return choices[choices.length - 1]; // 返回最大可用尺寸 } return Collections.min(bigEnough, new CompareSizesByArea()); }4. 多媒体捕获功能实现4.1 拍照功能实现拍照流程的核心代码private void takePicture() { try { final CaptureRequest.Builder captureBuilder cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); captureBuilder.addTarget(imageReader.getSurface()); captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 设置方向 int rotation activity.getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation)); // 执行拍照 captureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() { Override public void onCaptureCompleted(...) { // 保存照片 } }, backgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } }4.2 视频录制实现视频录制需要处理音频和视频的同步采集主要步骤配置MediaRecorderprivate void prepareRecorder() { mediaRecorder new MediaRecorder(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setOutputFile(createVideoFile().getAbsolutePath()); mediaRecorder.setVideoEncodingBitRate(10000000); mediaRecorder.setVideoFrameRate(30); mediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight()); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setOrientationHint(rotation); mediaRecorder.prepare(); }在录制过程中处理相机预览和视频采集的Surface切换5. 性能优化与问题排查5.1 内存管理最佳实践相机应用常见的内存问题及解决方案Bitmap内存泄漏使用BitmapFactory.Options.inSampleSize进行图片压缩及时回收不再使用的Bitmap对象Surface泄漏确保在Activity/Fragment生命周期结束时释放所有Surface实现正确的TextureView.SurfaceTextureListener相机资源释放Override protected void onStop() { super.onStop(); if (cameraDevice ! null) { cameraDevice.close(); cameraDevice null; } if (mediaRecorder ! null) { mediaRecorder.release(); mediaRecorder null; } }5.2 常见问题排查指南问题现象可能原因解决方案预览画面黑屏Surface未正确配置检查TextureView状态和相机预览Surface设置拍照延迟高自动对焦模式设置不当使用CONTROL_AF_MODE_CONTINUOUS_PICTURE视频录制失败权限不足或存储空间不够检查权限和存储状态测试不同分辨率相机启动崩溃相机被其他应用占用实现相机可用性检查优雅降级处理我在实际项目中总结的几个调试技巧使用CameraCharacteristics获取设备支持的全部参数为CameraDevice.StateCallback实现完整的错误处理在不同厂商设备上测试关键功能6. 功能扩展建议基于这个基础框架可以进一步实现高级拍摄模式手动对焦/曝光控制HDR模式连拍模式实时滤镜处理// 使用OpenGL ES实现实时滤镜 public class CameraGLRenderer implements GLSurfaceView.Renderer { Override public void onDrawFrame(GL10 gl) { // 应用滤镜效果 filter.apply(); // 绘制相机预览帧 texture.draw(); } }云端同步功能集成Firebase Storage自动备份实现拍摄内容分类管理这个项目代码结构清晰各功能模块解耦良好非常适合作为基础进行二次开发。我在实际使用中发现将相机控制逻辑封装成独立的CameraController类可以大大提高代码的可维护性和复用性。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询