當前方案:收到串口數據 → startActivity(CameraActivity) → 相機啟動預覽 → 拍照。每次拍照都重新啟動 Activity 並打開相機,導致 2-3 秒延遲 (相機硬件初始化、預覽啟動、對焦)。
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;
}
}
}
// 串口數據接收回調 (運行在非 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();
}
});
}
}
MainActivity 或專用 CameraPreviewFragment 持有 SurfaceView/TextureView。onResume 調用 CameraManager.initCamera(this, surfaceHolder)。onPause 調用 CameraManager.release() (或應用退出時統一釋放)。| 指標 | 原方案 (跳轉 Activity) | 優化方案 (單例常駐) |
|---|---|---|
| 首次拍照延遲 | 2-3 秒 | ~100ms (僅對焦+曝光) |
| 連拍間隔 | >3 秒 | ~500ms (受硬件限制) |
| 內存佔用 | 波動大 | 穩定 (常駐相機實例) |
| 代碼複雜度 | 低 | 中 (需管理生命周期) |
<uses-permission android:name="android.permission.CAMERA"/> + 運行時權限請求 (Android 6.0+)。Camera.getNumberOfCameras(),Camera.getCameraInfo() 選擇後置/前置。surfaceCreated 初始化相機,surfaceDestroyed 釋放,surfaceChanged 適配尺寸變化。Camera2 (或 CameraX Jetpack 庫),Camera 已棄用但兼容性好。