Why `UnsupportedOperationException` is thrown trying to associate SurfaceView with the camera?

679 Views Asked by At

I want to display what the camera films using the Surface class:

SurfaceView view = (SurfaceView) findViewById(R.id.camera_view);
Surface appSurface = view.getHolder().getSurface();

I pass the Surface object into the CameraManager API:

CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
manager.openCamera(
    manager.getCameraIdList()[0],
    new CameraDevice.StateCallback() {
        @Override
        public void onOpened(CameraDevice camera) {                
          // Why this line throws an exception?
          camera.createCaptureSession(
              Collections.singletonList(appSurface),
              new CameraCaptureSession.StateCallback() {...},
              null);
        }

        // other @Override methods
        ...
    },
    new Handler(getMainLooper())
);

And receive the following exception:

FATAL EXCEPTION: main                                                                                            
Process: com.google.android.apps.internal.smartcamera.tagger, PID: 8563                                                                                             
java.lang.UnsupportedOperationException: Unknown error -22                                                                                                  
at android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnError(LegacyExceptionUtils.java:77)                                                                                                    
at android.hardware.camera2.legacy.LegacyCameraDevice.getSurfaceSize(LegacyCameraDevice.java:583)                                                                                                   
at android.hardware.camera2.utils.SurfaceUtils.getSurfaceSize(SurfaceUtils.java:68)

It seems that the SurfaceUtils class (which is a piece of native c code) fails to read the Surface size correctly. Why?

2

There are 2 best solutions below

1
On

Try adding this to Manafiest.xml.

 <uses-permission android:name="android.permission.CAMERA" />
 <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2
On

A Surface is a weak pointer to the source it was obtained from.

Your ImageReader is going out of scope, and getting garbage collected, and the camera device runs into an abandoned surface, and throws an exception. The timing will be somewhat random, which is why you don't see this always.

Store your image reader somewhere persistent (you have to anyway to use it to retrieve images from it).