首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 串口開發:相機預覽常駐內存實現「閃拍」功能,消除 2-3 秒啟動延遲

     編輯:程式設計綜合問答

問題分析

當前方案:收到串口數據 → startActivity(CameraActivity) → 相機啟動預覽 → 拍照。每次拍照都重新啟動 Activity 並打開相機,導致 2-3 秒延遲 (相機硬件初始化、預覽啟動、對焦)。

核心解決思路:相機實例單例化 + 預覽常駐 + 事件驅動拍照

1. 相機管理單例

public class CameraManager {
    private static CameraManager instance;
    private Camera camera;
    private Camera.Parameters params;
    private SurfaceHolder previewHolder;
    private boolean isPreviewing = false;
    
    private CameraManager() {}
    public static synchronized CameraManager getInstance() {
        if (instance == null) instance = new CameraManager();
        return instance;
    }
    
    public void initCamera(Context context, SurfaceHolder holder) {
        if (camera != null) return;
        camera = Camera.open(); // 或 Camera.open(cameraId)
        params = camera.getParameters();
        // 配置參數: 圖片尺寸、對焦模式、預覽尺寸等
        camera.setParameters(params);
        previewHolder = holder;
        startPreview();
    }
    
    public void startPreview() {
        try {
            camera.setPreviewDisplay(previewHolder);
            camera.startPreview();
            isPreviewing = true;
        } catch (IOException e) { e.printStackTrace(); }
    }
    
    public void takePicture(Camera.PictureCallback jpegCallback) {
        if (camera != null && isPreviewing) {
            camera.takePicture(null, null, jpegCallback);
        }
    }
    
    public void release() {
        if (camera != null) {
            camera.stopPreview();
            camera.release();
            camera = null;
            isPreviewing = false;
        }
    }
}

2. 串口服務中直接調用拍照


// 串口數據接收回調 (運行在非 UI 線程)
@Override
protected void onDataReceived(final byte[] buffer, final int size) {
    // 解析指令
    String cmd = new String(buffer, 0, size).trim();
    if ("SNAP".equals(cmd)) {
        // 直接在後台線程觸發拍照,無需切換 Activity
        CameraManager.getInstance().takePicture(new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                // 保存圖片、上傳、通知 UI 更新
                saveImage(data);
                // 重新啟動預覽 (部分機型拍照後預覽停止)
                CameraManager.getInstance().startPreview();
            }
        });
    }
}

3. UI 層僅負責預覽顯示

  • MainActivity 或專用 CameraPreviewFragment 持有 SurfaceView/TextureView。
  • onResume 調用 CameraManager.initCamera(this, surfaceHolder)。
  • onPause 調用 CameraManager.release() (或應用退出時統一釋放)。

關鍵優勢

指標原方案 (跳轉 Activity)優化方案 (單例常駐)
首次拍照延遲2-3 秒~100ms (僅對焦+曝光)
連拍間隔>3 秒~500ms (受硬件限制)
內存佔用波動大穩定 (常駐相機實例)
代碼複雜度低中 (需管理生命周期)

避坑指南

  1. 權限:<uses-permission android:name="android.permission.CAMERA"/> + 運行時權限請求 (Android 6.0+)。
  2. 相機 ID 選擇:遍歷 Camera.getNumberOfCameras(),Camera.getCameraInfo() 選擇後置/前置。
  3. SurfaceHolder 回調:surfaceCreated 初始化相機,surfaceDestroyed 釋放,surfaceChanged 適配尺寸變化。
  4. Android 5.0+ Camera2 API:新項目建議直接使用 Camera2 (或 CameraX Jetpack 庫),Camera 已棄用但兼容性好。
  5. 硬件限制:若優化後延遲仍大,確為硬件 ISP 處理速度問題,需更換模組 (如文中最佳回答所述)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved