2017-03-03 357 views
0

我想用攝像頭api2來捕捉圖像。該代碼在MOTO g4上運行良好,但是當我在NEXUS 6上測試代碼時,onImageAvailable在session.capture之後未被調用,並且沒有保存圖像。真的很沮喪,非常感謝,如果有人可以幫助!非常感謝。android camera2 api - onImageAvailable在session.capture之後不會被調用

 ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); 
     List<Surface> outputSurfaces = new ArrayList<Surface>(2); 
     outputSurfaces.add(reader.getSurface()); 
     outputSurfaces.add(new Surface(textureView.getSurfaceTexture())); 
     final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
     captureBuilder.addTarget(reader.getSurface()); 
     captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
     // Orientation 
     int rotation = getWindowManager().getDefaultDisplay().getRotation(); 
     captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); 
     sendUri = getImageUri(); 
     final File file = new File(Environment.getExternalStorageDirectory()+"/" + sendUri +".jpg"); 
     ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() { 
      @Override 
      public void onImageAvailable(ImageReader reader) { 
       Image image = null; 
       try { 
        image = reader.acquireLatestImage(); 
        ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
        byte[] bytes = new byte[buffer.capacity()]; 
        buffer.get(bytes); 
        save(bytes); 

       } catch (FileNotFoundException e) { 
        e.printStackTrace(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } finally { 
        if (image != null) { 
         image.close(); 
        } 
       } 
      } 
      private void save(byte[] bytes) throws IOException { 
       OutputStream output = null; 
       try { 
        output = new FileOutputStream(file); 
        output.write(bytes); 
       } finally { 
        if (null != output) { 
         output.close(); 
        } 
       } 
      } 
     }; 
     reader.setOnImageAvailableListener(readerListener, mBackgroundHandler); 
     final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() { 

      @Override 
      public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
       super.onCaptureCompleted(session, request, result); 
       //Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show(); 
       toast1("Saved:"+file); 
       //createCameraPreview(); 
      } 
     }; 
     cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 
      @Override 
      public void onConfigured(CameraCaptureSession session) { 
       try { 
        session.capture(captureBuilder.build(), captureListener, mBackgroundHandler); 
       } catch (CameraAccessException e) { 
        e.printStackTrace(); 
       } 
      } 
      @Override 
      public void onConfigureFailed(CameraCaptureSession session) { 
      } 
     }, mBackgroundHandler); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 

下面是承上啓下6輸出的完整的logcat運行相機功能時,似乎沒有什麼用處...

03-07 13:04:34.526 1838-1838/examples.hello E/AndroidCameraApi: is camera open 
03-07 13:04:34.527 1838-1838/examples.hello I/CameraManagerGlobal: Connecting to camera service 
03-07 13:04:34.659 1838-1838/examples.hello E/AndroidCameraApi: openCamera X 
03-07 13:04:34.694 1838-1838/examples.hello E/AndroidCameraApi: onOpened 
03-07 13:04:34.722 1838-1883/examples.hello D/OpenGLRenderer: endAllActiveAnimators on 0x931bee80 (RippleDrawable) with handle 0x92c2cea0 
03-07 13:04:43.952 1838-1838/examples.hello E/AndroidCameraApi: onPause 
+0

謝謝!我正在使用的nexus 6正在運行android版本7.0。我認爲它應該能夠支持camera2 api。 – song

+0

我認爲android.camera2 API會受到指責。複合這個問題的事實是這個API不支持低於21的任何API級別。許多攝像頭應用程序仍然使用棄用的Camera API。 –

回答

0

這將會是,如果你提供從發生故障的設備全輸出logcat的有益,但我懷疑的問題是這樣的:

ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); 

你創建本地ImageReader對象,而不是將其保存爲進一步使用。你從它得到一個Surface,但是Surface很像一個弱指針;如果沒有引用它,它將不會使ImageReader獲取GC'd(請參閱note in the developer references

所以我懷疑如果您只是創建一個類成員mReader變量並將讀取器存儲在其中,那麼一切都會正常工作。

由於GC算法的不同,它可能在Moto手機上工作;運行時尚未完全清除讀者對象,因此有時間調用回調函數。

+0

非常感謝!你能更具體地告訴我嗎? – song

+0

1)添加一個'私人ImageReader mReader'給你的班級。 2)將閱讀器保存到mReader中 –

相關問題