代码解释:
CameraService
是一个后台服务,用于管理摄像头的打开、预览以及图像的捕获和保存。onBind
方法返回服务的绑定接口。onCreate
方法初始化服务。onStartCommand
方法在服务启动时调用,启动后台线程并打开摄像头。onDestroy
方法在服务销毁时调用,关闭摄像头并停止后台线程。startBackgroundThread
和stopBackgroundThread
方法分别启动和停止后台线程。openCamera
方法打开摄像头并设置图像读取器。chooseCamera
方法选择后置摄像头。createCameraPreview
方法创建摄像头预览会话。updatePreview
方法更新预览画面。closeCamera
方法关闭摄像头和图像读取器。saveImageToStorage
方法将捕获的图像保存到存储中。createImageFile
方法创建一个用于保存图像的临时文件。import android.annotation.SuppressLint; import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.ImageFormat; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureRequest; import android.media.Image; import android.media.ImageReader; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.util.Log; import android.view.Surface; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; public class CameraService extends Service { private static final String TAG = "CameraService"; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; private CaptureRequest.Builder captureRequestBuilder; private ImageReader imageReader; private Handler backgroundHandler; private HandlerThread backgroundThread; private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { CameraService getService() { return CameraService.this; } } @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { startBackgroundThread(); // 启动后台线程 openCamera(); // 打开摄像头 return START_NOT_STICKY; } @Override public void onDestroy() { closeCamera(); // 关闭摄像头 stopBackgroundThread(); // 停止后台线程 super.onDestroy(); } private void startBackgroundThread() { backgroundThread = new HandlerThread("CameraBackground"); backgroundThread.start(); backgroundHandler = new Handler(backgroundThread.getLooper()); } private void stopBackgroundThread() { backgroundThread.quitSafely(); try { backgroundThread.join(); backgroundThread = null; backgroundHandler = null; } catch (InterruptedException e) { Log.e(TAG, "Interrupted while waiting for background thread to close", e); } } @SuppressLint("MissingPermission") private void openCamera() { CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { String cameraId = chooseCamera(manager); // 选择摄像头 CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); imageReader = ImageReader.newInstance( 720, 1080, ImageFormat.JPEG, 1); imageReader.setOnImageAvailableListener( reader -> { Image image = reader.acquireLatestImage(); // 处理图像数据,保存到沙箱 saveImageToStorage(image); image.close(); }, backgroundHandler); manager.openCamera(cameraId, new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { cameraDevice = camera; createCameraPreview(); // 创建摄像头预览 } @Override public void onDisconnected(CameraDevice camera) { cameraDevice.close(); } @Override public void onError(CameraDevice camera, int error) { cameraDevice.close(); cameraDevice = null; } }, backgroundHandler); } catch (CameraAccessException e) { Log.e(TAG, "Cannot access the camera.", e); } } private String chooseCamera(CameraManager manager) throws CameraAccessException { for (String cameraId : manager.getCameraIdList()) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { return cameraId; // 返回后置摄像头的ID } } return manager.getCameraIdList()[0]; // 默认返回第一个摄像头 } private void createCameraPreview() { try { Surface surface = imageReader.getSurface(); captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(surface); cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { if (cameraDevice == null) { return; } cameraCaptureSession = session; updatePreview(); // 更新预览 } @Override public void onConfigureFailed(CameraCaptureSession session) { Log.e(TAG, "Failed to configure camera preview."); } }, null); } catch (CameraAccessException e) { Log.e(TAG, "Error creating camera preview.", e); } } private void updatePreview() { if (cameraDevice == null) { return; } captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); try { cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler); } catch (CameraAccessException e) { Log.e(TAG, "Error updating preview.", e); } } private void closeCamera() { if (cameraCaptureSession != null) { cameraCaptureSession.close(); cameraCaptureSession = null; } if (cameraDevice != null) { cameraDevice.close(); cameraDevice = null; } if (imageReader != null) { imageReader.close(); imageReader = null; } } private void saveImageToStorage(Image image) { ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); File imageFile = null; try { imageFile = createImageFile(); // 创建图像文件 } catch (IOException e) { Log.e(TAG, "Error creating image file.", e); } try (FileOutputStream output = new FileOutputStream(imageFile)) { output.write(bytes); closeCamera(); // 关闭摄像头 stopBackgroundThread(); // 停止后台线程 Log.d(TAG, "Image saved: " + imageFile.getAbsolutePath()); } catch (IOException e) { Log.e(TAG, "Error saving image.", e); } } private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getFilesDir(); return File.createTempFile(imageFileName, ".jpg", storageDir); // 创建临时图像文件 } }
-
提示:需在activity中启动CameraService服务,包括在AndroidManifest.xml添加权限,开启相机权限等等