You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中如何保持相机持续开启?

Fixing Continuous Camera Capture for Single/Multiple Photos

Hey there! I get your frustration with the current camera flow—having to go back and re-launch the camera every time you want another photo is definitely clunky. Let's break down why this happens and how to fix it properly.

The Root Problem

The MediaStore.ACTION_IMAGE_CAPTURE Intent is designed explicitly for single-shot photo capture. Once the user takes a photo, the system camera app returns control to your original Activity by default. There's no built-in way to make this Intent support continuous shooting across all devices (since system camera apps vary by manufacturer).

The Best Solution: Build a Custom Camera UI with CameraX

To give users the flexibility to take one or multiple photos without leaving the camera view, the most reliable approach is to implement a custom camera interface using CameraX (Jetpack's camera library). It's easy to integrate, works across Android 5.0+, and gives you full control over the capture flow.

Step 1: Add CameraX Dependencies

First, add these dependencies to your app-level build.gradle file:

dependencies {
    def camerax_version = "1.3.0"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    implementation "androidx.camera:camera-view:$camerax_version"
}

Step 2: Create the Camera Layout

Add a preview view and capture button to your layout (e.g., activity_camera.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.camera.view.PreviewView
        android:id="@+id/previewView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:id="@+id/captureBtn"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:background="@drawable/round_button"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="32dp"/>

</RelativeLayout>

Step 3: Implement the Camera Logic

Here's the full Activity code to handle continuous capture. Users can tap the button as many times as they want to take photos, and the camera preview stays active between shots:

import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;

import android.content.ContentValues;
import android.os.Bundle;
import android.provider.MediaStore;
import android.widget.Button;
import android.widget.Toast;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

public class CustomCameraActivity extends AppCompatActivity {

    private ImageCapture imageCapture;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        PreviewView previewView = findViewById(R.id.previewView);
        Button captureBtn = findViewById(R.id.captureBtn);

        // Initialize camera provider
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                bindCameraUseCases(cameraProvider, previewView);
            } catch (ExecutionException | InterruptedException e) {
                Toast.makeText(this, "Camera initialization failed!", Toast.LENGTH_SHORT).show();
            }
        }, ContextCompat.getMainExecutor(this));

        // Handle capture button clicks
        captureBtn.setOnClickListener(v -> takePhoto());
    }

    private void bindCameraUseCases(ProcessCameraProvider cameraProvider, PreviewView previewView) {
        // Configure preview use case
        Preview preview = new Preview.Builder().build();
        preview.setSurfaceProvider(previewView.getSurfaceProvider());

        // Select back camera
        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build();

        // Configure image capture use case
        imageCapture = new ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .build();

        // Bind use cases to lifecycle
        cameraProvider.unbindAll();
        cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
    }

    private void takePhoto() {
        if (imageCapture == null) return;

        // Prepare output file details
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "MyPhoto_" + System.currentTimeMillis());
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");

        ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions
                .Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
                .build();

        // Execute photo capture
        Executor executor = ContextCompat.getMainExecutor(this);
        imageCapture.takePicture(outputOptions, executor, new ImageCapture.OnImageSavedCallback() {
            @Override
            public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
                // Photo saved successfully - you can store the URI in a list here
                Toast.makeText(CustomCameraActivity.this, "Photo saved!", Toast.LENGTH_SHORT).show();
                // Camera stays active - user can tap again for another photo
            }

            @Override
            public void onError(ImageCaptureException exception) {
                Toast.makeText(CustomCameraActivity.this, "Capture failed: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Step 4: Handle Permissions

Don't forget to add the required permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>

You'll also need to request runtime permissions before launching the camera. Add this code to your Activity:

import android.Manifest;
import android.content.pm.PackageManager;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

private static final int REQUEST_PERMISSIONS = 100;
private static final String[] REQUIRED_PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);

    if (!allPermissionsGranted()) {
        ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_PERMISSIONS);
    } else {
        // Initialize camera logic here
    }
}

private boolean allPermissionsGranted() {
    for (String permission : REQUIRED_PERMISSIONS) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSIONS) {
        if (allPermissionsGranted()) {
            // Initialize camera logic here
        } else {
            Toast.makeText(this, "Permissions are required to use the camera!", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

How This Solves Your Problem

  • Users can take one or multiple photos without leaving the camera view.
  • The preview stays active between shots, so no need to re-launch the camera every time.
  • You have full control over where photos are saved and can easily track all captured images (e.g., store their URIs in a list to process later).

内容的提问来源于stack exchange,提问作者SpaceSloth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:25:58