安卓开发:如何使用camera2类并兼容API 16及以下版本?
Hey there! Let's work through your camera compatibility problem together—since you're new to Android dev, I'll break this down clearly with actionable options.
First, a quick reminder: android.hardware.camera2 was introduced in API 21 (Lollipop). That means devices running API 16 can't use these classes natively. Let's go through your options, starting with the most practical ones.
Option 1: Use CameraX (Highly Recommended)
If you want to avoid messy version checks and keep support for API 16, CameraX is your best bet. It's part of Jetpack, supports API 16+, and automatically uses camera1 under the hood for older devices and camera2 for newer ones—all with a unified, easy-to-use API. You don't have to write any if-else logic for version differences.
How to Set Up CameraX
- Add these dependencies to your app-level
build.gradle(check for the latest version if needed):
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}" }
- Add a
PreviewViewto your layout for camera preview:
<androidx.camera.view.PreviewView android:id="@+id/previewView" android:layout_width="match_parent" android:layout_height="match_parent" />
- Initialize the camera in your activity/fragment (with permission handling):
public class CameraActivity extends AppCompatActivity { private PreviewView previewView; private ProcessCameraProvider cameraProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); previewView = findViewById(R.id.previewView); // Request camera permission first if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 100); return; } // Initialize CameraX ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { try { cameraProvider = cameraProviderFuture.get(); bindCameraUseCases(); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } }, ContextCompat.getMainExecutor(this)); } private void bindCameraUseCases() { // Set up preview Preview preview = new Preview.Builder().build(); preview.setSurfaceProvider(previewView.getSurfaceProvider()); // Select rear camera CameraSelector cameraSelector = new CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); // Bind camera to lifecycle cameraProvider.bindToLifecycle(this, cameraSelector, preview); } }
Option 2: Bump Min SDK to API 21 + Handle Low-Version Users
If you're okay with dropping support for API 16-20 devices (or just showing them a fallback), this is the simplest path for using camera2 directly:
- Set
minSdkVersion 21in yourbuild.gradle—no more compilation errors fromcamera2classes. - For users on older devices, show a friendly message like "This feature requires Android 5.0+", or redirect them to a basic alternative (like using the system camera via
Intent).
Option 3: Manual Version Check with Fallbacks (If You Must Stick to API 16)
Since you can't import android.hardware.camera, you'll need a fallback for API 16-20 devices (like using the system camera or a third-party library). Here's how to implement the if-else logic safely:
Step 1: Create a Camera Interface
Define a common interface for your camera operations to keep code clean:
public interface CameraHandler { void startCamera(); void capturePhoto(); // Add other needed methods }
Step 2: Implement Camera2 for API 21+
Use @TargetApi to suppress Lint warnings about unsupported classes:
@TargetApi(Build.VERSION_CODES.LOLLIPOP) public class Camera2Handler implements CameraHandler { private Context context; public Camera2Handler(Context context) { this.context = context; } @Override public void startCamera() { // Your camera2 code here (e.g., initialize CameraManager, set up preview) CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); // ... rest of your camera2 implementation } @Override public void capturePhoto() { // Camera2 photo capture logic } }
Step 3: Implement Fallback for Older Devices
Since you can't use camera1, use the system camera intent as a fallback:
public class FallbackCameraHandler implements CameraHandler { private Context context; private static final int REQUEST_IMAGE_CAPTURE = 1; public FallbackCameraHandler(Context context) { this.context = context; } @Override public void startCamera() { // Launch system camera app Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) { ((Activity) context).startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } else { // Show error if no camera app is available Toast.makeText(context, "No camera app found", Toast.LENGTH_SHORT).show(); } } @Override public void capturePhoto() { // Already handled by the system camera intent } }
Step 4: Initialize the Right Handler at Runtime
CameraHandler cameraHandler; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cameraHandler = new Camera2Handler(this); } else { cameraHandler = new FallbackCameraHandler(this); } // Use the handler cameraHandler.startCamera();
内容的提问来源于stack exchange,提问作者Erika

