Android 7.1.1+带GPS自定义相机拍摄图片无法写入文件求助
Hey there, let's dig into this tricky issue you're facing. You mentioned your custom GPS camera works perfectly on Android 7.0 and below, but on 7.1.1+ (like Oreo on your Galaxy Note 8 and Pixel XL 2), the ImageReader.OnImageAvailableListener code never runs—even though you have proper storage permissions and can create temporary files. Here's what's likely going on and how to fix it:
Possible Root Causes
ImageReader Instance Getting Garbage-Collected Early
Android 7.1+ tightened up garbage collection rules. If yourImageReaderis a local variable (created inside a method), it might get recycled before the camera can send image data to it. Without a strong reference, the system cleans it up, and the callback never fires.Misconfigured Camera Session/Capture Request
Starting with Android 7.1, the Camera2 API (which I assume you're using for your custom camera) has stricter requirements for linking surfaces to capture requests. If yourImageReader's surface isn't properly added to the camera session or capture request, the camera won't send any image data to it.Insufficient Image Buffer Allocation
SettingmaxImagesto 1 when creating theImageReadercan cause buffer queue issues on 7.1+ systems, preventing the callback from triggering.
Step-by-Step Fixes
1. Add a Strong Reference to ImageReader
Move your ImageReader from a local variable to a member variable of your Activity/Fragment to keep it in memory:
// Declare as a member variable in your Activity/Fragment private ImageReader mImageReader; // Initialize it where you set up your camera (e.g., onCreate or onResume) private void initCamera() { // Replace with your actual image width/height int imageWidth = 1920; int imageHeight = 1080; // Set maxImages to 2 or 3 to avoid buffer bottlenecks mImageReader = ImageReader.newInstance(imageWidth, imageHeight, ImageFormat.JPEG, 2); mImageReader.setOnImageAvailableListener(readerListener, null); // Use a Handler to offload to a background thread if needed }
2. Link ImageReader's Surface to Camera Session & Capture Request
When creating your CameraCaptureSession, include the ImageReader's surface in the target surfaces list, and explicitly add it to your capture request:
// When setting up the camera session cameraDevice.createCaptureSession(Arrays.asList(mImageReader.getSurface(), previewSurface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { // Build your still capture request try { CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); // Add the ImageReader surface as a target captureBuilder.addTarget(mImageReader.getSurface()); // Optional: Add focus/exposure settings captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // Send the capture request session.capture(captureBuilder.build(), null, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Log.e("CameraError", "Capture session failed to configure"); } }, null);
3. Add Detailed Logging to Diagnose Hidden Issues
Add logs to all camera-related callbacks to pinpoint where the flow breaks:
- Log in
CameraDevice.StateCallback'sonOpenedandonErrormethods - Log in
CameraCaptureSession.StateCallback'sonConfiguredandonConfigureFailedmethods - Log at the start of your
OnImageAvailableListenerto confirm if it ever runs
4. Verify Image Format Compatibility
Double-check that the ImageFormat you're using for ImageReader matches what your camera supports. For JPEG captures, ImageFormat.JPEG is standard, but use CameraCharacteristics to confirm supported formats for your specific devices.
Quick Check for Your Existing Code
Looking at your snippet, confirm:
- The
ImageReaderisn't a local variable (it looks like it might be, since you're defining the listener right after creating the temp file) - You're explicitly adding the
ImageReader's surface to both the camera session and capture request
Once you implement these changes, your OnImageAvailableListener should fire consistently on Android 7.1.1+ devices.
内容的提问来源于stack exchange,提问作者Bindu K S

