在Android中实现在后台拍照(静默)

代码解释:

  • CameraService 是一个后台服务,用于管理摄像头的打开、预览以及图像的捕获和保存。
  • onBind 方法返回服务的绑定接口。
  • onCreate 方法初始化服务。
  • onStartCommand 方法在服务启动时调用,启动后台线程并打开摄像头。
  • onDestroy 方法在服务销毁时调用,关闭摄像头并停止后台线程。
  • startBackgroundThreadstopBackgroundThread 方法分别启动和停止后台线程。
  • 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添加权限,开启相机权限等等

要在Android实现后台连续静默拍照,我们可以使用Camera2 API来控制相机硬件,并在后台进行照片的捕获。下面是一种可能的实现方法: 首先,在AndroidManifest.xml文件添加相应的权限,例如: ``` <uses-permission android:name="android.permission.CAMERA" /> ``` 然后,在你的代码创建一个CameraCaptureSession.StateCallback的实例,以便相机会话状态发生变化时进行相应的处理。在这个回调接口,我们需要实现onConfigured()方法来设置照片的捕获设置,并在准备好的时候调用CameraCaptureSession.capture()方法来捕获照片。 接下来,我们需要创建一个CameraCaptureSession.CaptureCallback的实例,用于监听相机捕获照片的过程,并在照片捕获完成时进行相应的处理。在onCaptureCompleted()方法,我们可以对捕获到的照片进行保存,例如将其保存到指定的文件夹。 之后,我们需要获取CameraManager的实例,并使用其方法打开相机设备。在打开相机设备之后,我们可以创建一个预览Surface,并将其添加到捕获请求。 最后,我们可以调用CameraCaptureSession.capture()方法开始捕获照片,捕获的方式可以使用CameraDevice.TEMPLATE_STILL_CAPTURE来指定。 综上所述,通过以上步骤,我们可以在Android实现后台连续静默拍照的功能。同时,为了避免闪退,我们需要注意合理地进行线程管理和异常处理。 需要注意的是,在使用相机硬件资源时,请确保适当地释放它们,以免造成资源浪费和性能问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值