Search code examples
androidandroid-camera2

Android: camera2 crash in capture()


I recently started to learn how to use Android camera2, but when I want to take a picture it will crash. I just know where it crashed but I don't know why it . Does anyone help me to find the problem? thanks.

public void takePicture(){
    if(cameraDevice == null){
        return ;
    }
    try {
        ImageReader imageReader = ImageReader.newInstance(600, 800, ImageFormat.JPEG, 1);
        Surface imageReaderSurface = imageReader.getSurface();
        imageReader.setOnImageAvailableListener(new OnImageAvailableListener(), null);


        picturesRequestBuilder = cameraDevice.createCaptureRequest(cameraDevice.TEMPLATE_STILL_CAPTURE);
        // 将imageReader的surface作为CaptureRequest.Builder的目标
        picturesRequestBuilder.addTarget(imageReaderSurface);
        // 自动对焦
        CaptureRequest captureRequest = picturesRequestBuilder.build();
     /*   ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
        for(int i=0;i<10;i++){
            captureRequests.add(captureRequest);
        }*/
        mCameraCaptureSession.capture(captureRequest, new CaptureCallback(),null);
        // mCameraCaptureSession.captureBurst(captureRequests, new CaptureCallback(),null);
    }
    catch (CameraAccessException e) {
        e.printStackTrace();
    }

}

My ERROR LOG.

2020-07-20 14:50:23.506 21999-21999/com.example.mycamera E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mycamera, PID: 21999
java.lang.IllegalStateException: Could not execute method for android:onClick
    at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:402)
    at android.view.View.performClick(View.java:7448)
    at android.view.View.performClickInternal(View.java:7425)
    at android.view.View.access$3600(View.java:810)
    at android.view.View$PerformClick.run(View.java:28296)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:397)
    at android.view.View.performClick(View.java:7448) 
    at android.view.View.performClickInternal(View.java:7425) 
    at android.view.View.access$3600(View.java:810) 
    at android.view.View$PerformClick.run(View.java:28296) 
    at android.os.Handler.handleCallback(Handler.java:938) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7656) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
 Caused by: java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!
    at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:738)
    at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:1191)
    at android.hardware.camera2.impl.CameraDeviceImpl.capture(CameraDeviceImpl.java:1051)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.capture(CameraCaptureSessionImpl.java:188)
    at com.example.mycamera.MainActivity.takePicture(MainActivity.java:267)
    at com.example.mycamera.MainActivity.button(MainActivity.java:69)
    at java.lang.reflect.Method.invoke(Native Method) 
    at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:397) 
    at android.view.View.performClick(View.java:7448) 
    at android.view.View.performClickInternal(View.java:7425) 
    at android.view.View.access$3600(View.java:810) 
    at android.view.View$PerformClick.run(View.java:28296) 
    at android.os.Handler.handleCallback(Handler.java:938) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7656) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

2020-07-20 14:50:23.693 21999-21999/? I/Process: Sending signal. PID: 21999 SIG: 9


Solution

  • You can't add a Surface in a CaptureRequest that wasn't part of the Surfaces given to createCaptureSession. In your code, you're creating an ImageReader only once you want to take a picture, and the API is telling you that's not valid:

    Caused by: java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!

    So either set up the ImageReader the same time you're setting up your capture session and include its Surface in the output target list, or create a new capture session in takePicture that includes the newly-created ImageReader.

    The latter isn't really recommended, because creating a new capture session will pause preview briefly. So create the ImageReader where you're calling CameraDevice.createCaptureSession, and make sure you keep the ImageReader as part of your enclosing class to avoid it getting garbage-collected.