2017-03-12 5 views
0

Je crée une application qui prend en charge l'API de caméra obsolète et nouvelle. Le premier fonctionne comme un charme, mais je suis aux prises avec l'API Camera2. Dans une phase de test, j'ai remarqué un comportement étrange. Dispositif d'essai est Samsung Galaxy S5 avec Android 6.0.1 Quand j'appuyez sur la touche Marche/Arrêt, puis revenir à l'application ce que je reçois (il ne se produit pas à chaque fois):API Camera2 et java.lang.IllegalStateException

03-12 16:14:32.704 24117-24117/pl.tripper.tripper E/MainActivity: onPause 
03-12 16:14:32.774 24117-24128/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] dequeueBuffer: BufferQueue has been abandoned 
03-12 16:14:32.784 24117-24145/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] queueBuffer: BufferQueue has been abandoned 
03-12 16:14:33.044 24117-24128/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] cancelBuffer: BufferQueue has been abandoned 
03-12 16:14:33.044 24117-24145/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] cancelBuffer: BufferQueue has been abandoned 
03-12 16:14:33.054 24117-24129/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] cancelBuffer: BufferQueue has been abandoned 
03-12 16:14:33.054 24117-24128/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-24117-2] cancelBuffer: BufferQueue has been abandoned 
03-12 16:14:33.264 24117-24117/pl.tripper.tripper E/CameraNewApi: cameraComponentsReleased 
03-12 16:14:33.264 24117-24117/pl.tripper.tripper E/CameraNewApi: StopCameraThread 
03-12 16:14:33.264 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewRemoved 
03-12 16:14:33.264 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceDestroyed 
03-12 16:14:33.634 24117-24117/pl.tripper.tripper E/MainActivity: onCreate 
03-12 16:14:33.634 24117-24117/pl.tripper.tripper E/MainActivity: onResume 
03-12 16:14:33.634 24117-24117/pl.tripper.tripper E/CameraNewApi: startCameraThread 
03-12 16:14:33.634 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewCreated 
03-12 16:14:33.644 24117-24117/pl.tripper.tripper E/CameraNewApi: initCamera 
03-12 16:14:33.674 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceCreated 
03-12 16:14:33.674 24117-24117/pl.tripper.tripper E/CameraNewApi: openCamera 
03-12 16:14:33.914 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceChanged 
03-12 16:14:33.914 24117-25053/pl.tripper.tripper E/CameraNewApi: onOpened 
03-12 16:14:33.914 24117-25053/pl.tripper.tripper E/CameraNewApi: createCameraPreview 
03-12 16:14:33.934 24117-24117/pl.tripper.tripper E/MainActivity: onPause 
03-12 16:14:34.174 24117-24117/pl.tripper.tripper E/CameraNewApi: cameraComponentsReleased 
03-12 16:14:34.174 24117-25053/pl.tripper.tripper E/CameraNewApi: onConfigured 
03-12 16:14:34.174 24117-24117/pl.tripper.tripper E/CameraNewApi: StopCameraThread 
03-12 16:14:34.174 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewRemoved 
03-12 16:14:34.184 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceDestroyed 
03-12 16:14:34.914 24117-24117/pl.tripper.tripper E/MainActivity: onResume 
03-12 16:14:34.914 24117-24117/pl.tripper.tripper E/CameraNewApi: startCameraThread 
03-12 16:14:34.924 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewCreated 
03-12 16:14:34.924 24117-24117/pl.tripper.tripper E/CameraNewApi: initCamera 
03-12 16:14:34.964 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceCreated 
03-12 16:14:34.964 24117-24117/pl.tripper.tripper E/CameraNewApi: openCamera 
03-12 16:14:35.294 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceChanged 
03-12 16:14:35.294 24117-25121/pl.tripper.tripper E/CameraNewApi: onOpened 
03-12 16:14:35.294 24117-25121/pl.tripper.tripper E/CameraNewApi: createCameraPreview 
03-12 16:14:35.354 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceChanged 
03-12 16:14:35.374 24117-24117/pl.tripper.tripper E/MainActivity: onPause 
03-12 16:14:35.384 24117-25121/pl.tripper.tripper E/CameraNewApi: onConfigured 
03-12 16:14:35.594 24117-24117/pl.tripper.tripper E/CameraNewApi: cameraComponentsReleased 
03-12 16:14:35.594 24117-25121/pl.tripper.tripper E/CameraNewApi: Session was closed or camera device has been closed. 
                    java.lang.IllegalStateException: CameraDevice was already closed 
                     at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1997) 
                     at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:844) 
                     at android.hardware.camera2.impl.CameraDeviceImpl.setRepeatingRequest(CameraDeviceImpl.java:899) 
                     at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:236) 
                     at pl.tripper.tripper.camera.CameraNewApi$2.onConfigured(CameraNewApi.java:107) 
                     at java.lang.reflect.Method.invoke(Native Method) 
                     at android.hardware.camera2.dispatch.InvokeDispatcher.dispatch(InvokeDispatcher.java:39) 
                     at android.hardware.camera2.dispatch.HandlerDispatcher$1.run(HandlerDispatcher.java:65) 
                     at android.os.Handler.handleCallback(Handler.java:739) 
                     at android.os.Handler.dispatchMessage(Handler.java:95) 
                     at android.os.Looper.loop(Looper.java:158) 
                     at android.os.HandlerThread.run(HandlerThread.java:61) 
03-12 16:14:35.594 24117-24117/pl.tripper.tripper E/CameraNewApi: StopCameraThread 
03-12 16:14:35.594 24117-25121/pl.tripper.tripper E/CameraNewApi: cameraComponentsReleased 
03-12 16:14:35.594 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewRemoved 
03-12 16:14:35.604 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceDestroyed 
03-12 16:14:35.644 24117-24117/pl.tripper.tripper E/MainActivity: onCreate 
03-12 16:14:35.654 24117-24117/pl.tripper.tripper E/MainActivity: onResume 
03-12 16:14:35.654 24117-24117/pl.tripper.tripper E/CameraNewApi: startCameraThread 
03-12 16:14:35.654 24117-24117/pl.tripper.tripper E/CameraApiManager: cameraPreviewCreated 
03-12 16:14:35.654 24117-24117/pl.tripper.tripper E/CameraNewApi: initCamera 
03-12 16:14:35.694 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceCreated 
03-12 16:14:35.694 24117-24117/pl.tripper.tripper E/CameraNewApi: openCamera 
03-12 16:14:35.934 24117-24117/pl.tripper.tripper E/CameraNewApi: onSurfaceChanged 
03-12 16:14:35.934 24117-25184/pl.tripper.tripper E/CameraNewApi: onOpened 
03-12 16:14:35.934 24117-25184/pl.tripper.tripper E/CameraNewApi: createCameraPreview 
03-12 16:14:35.944 24117-24117/pl.tripper.tripper E/ViewRootImpl: sendUserActionEvent() mView == null 
03-12 16:14:35.944 24117-24117/pl.tripper.tripper E/ViewRootImpl: sendUserActionEvent() mView == null 
03-12 16:14:35.994 24117-25184/pl.tripper.tripper E/CameraNewApi: onConfigured 

Ajout de quelques journaux d'erreurs quand les méthodes sont appelées. Je sais que cameraDevice est null lorsque la session est encore en cours, mais je n'ai aucune idée de comment le réparer. L'appareil photo continue de fonctionner après les erreurs java.lang.IllegalStateException. Le deuxième problème est erreur BufferQueueProducer mais je ne peux pas comprendre d'où cela vient.

03-12 15:47:40.244 30720-30731/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] dequeueBuffer: BufferQueue has been abandoned 03-12 15:47:40.244 30720-30751/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] queueBuffer: BufferQueue has been abandoned 03-12 15:47:40.524 30720-30731/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] cancelBuffer: BufferQueue has been abandoned 03-12 15:47:40.524 30720-30751/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] cancelBuffer: BufferQueue has been abandoned 03-12 15:47:40.524 30720-30732/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] cancelBuffer: BufferQueue has been abandoned 03-12 15:47:40.524 30720-30731/pl.tripper.tripper E/BufferQueueProducer: [SurfaceTexture-1-30720-1] cancelBuffer: BufferQueue has been abandoned

Voici mon code:

MainActivity.class

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     ButterKnife.bind(this); 

     Log.e(TAG, "onCreate"); 
     isImmersiveAvailable(); 
     cameraApiManager = new CameraApiManager(this, this); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 

     Log.e(TAG, "onResume"); 
     cameraApiManager.createCamera(); 

    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 

     Log.e(TAG, "onPause"); 
     cameraApiManager.releaseCameraAndPreview(); 
    } 

CameraApiManager.class

public class CameraApiManager implements CameraUtility.cameraOpenedListener { 

    private static final String TAG = "CameraApiManager"; 

    private final WeakReference<MainActivity> mainActivity; 
    private Context context; 

    private CameraSourceApi cameraSourceApi; 
    private CameraPreview cameraPreview; 

    public CameraApiManager(Context context, MainActivity mainActivity){ 

     this.mainActivity= new WeakReference<>(mainActivity); 

     cameraSourceApi = new CameraSourceApi<>(new CameraNewApi(context)); 
     this.context = context; 
    } 

    private boolean cameraProgressBarEnable(){ 
     return context.getResources().getBoolean(R.bool.camera_progress_bar_enable); 
    } 

    private void setCameraProgressBarVisibility(final int visibility){ 
     final MainActivity mainActivity = this.mainActivity.get(); 
     if(mainActivity!= null){ 
      // UI/Main Thread 
      if(Looper.myLooper() == Looper.getMainLooper()){ 
       ProgressBar cameraProgressBar = (ProgressBar) mainActivity.findViewById(R.id.camera_progress_bar); 
       cameraProgressBar.setVisibility(visibility); 
      } else { 
       mainActivity.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         ProgressBar cameraProgressBar = (ProgressBar) mainActivity.findViewById(R.id.camera_progress_bar); 
         cameraProgressBar.setVisibility(visibility); 
        } 
       }); 
      } 
     } 
    } 

    private void showCameraOpenErrorToast(){ 
     Toast.makeText(context, context.getResources().getString(R.string.camera_open_error_toast), Toast.LENGTH_LONG).show(); 
    } 

    private boolean cameraPermissionGranted() { 
     return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; 
    } 

    public void createCamera(){ 
     if(cameraPermissionGranted()){ 
      if(cameraProgressBarEnable()){ 
       setCameraProgressBarVisibility(View.VISIBLE); 
      } 
      cameraSourceApi.createCamera(this); 
     } 
    } 

    public void releaseCameraAndPreview(){ 
     if(cameraPermissionGranted()){ 
      cameraSourceApi.releaseCamera(); 
      removeCameraPreview(); 
     } 
    } 

    @Override 
    public void onCameraOpened(boolean succeeded, boolean addPreview, boolean progressBar) { 
     if(addPreview) { 
      if (cameraPreview == null) { 
       Log.e(TAG, "cameraPreviewCreated"); 
       cameraPreview = new CameraPreview(context, cameraSourceApi); 
       addCameraPreview(); 
      } 
     } 
     if(!progressBar){ 
      if(cameraProgressBarEnable()){ 
       setCameraProgressBarVisibility(View.GONE); 
      } 
     } 
     if(!succeeded){ 
      showCameraOpenErrorToast(); 
     } 
    } 

    private void addCameraPreview(){ 
     MainActivity mainActivity = this.mainActivity.get(); 
     if(mainActivity != null && cameraPreview != null){ 
      FrameLayout preview = (FrameLayout) mainActivity.findViewById(R.id.camera_preview); 
      preview.addView(cameraPreview); 
     } 
    } 

    private void removeCameraPreview(){ 
     MainActivity mainActivity = this.mainActivity.get(); 
     if(mainActivity!= null && cameraPreview != null){ 
      Log.e(TAG, "cameraPreviewRemoved"); 
      FrameLayout preview = (FrameLayout) mainActivity.findViewById(R.id.camera_preview); 
      preview.removeView(cameraPreview); 
      cameraPreview = null; 
     } 
    } 

    class CameraSourceApi<T extends CameraUtility> implements CameraUtility{ 

     private T camera; 

     CameraSourceApi(T camera){ 
      this.camera = camera; 
     } 

     @Override 
     public void createCamera(CameraUtility.cameraOpenedListener cameraOpenedListener) { 
      camera.createCamera(cameraOpenedListener); 
     } 

     @Override 
     public void releaseCamera() { 
      camera.releaseCamera(); 
     } 

     @Override 
     public void onSurfaceCreated(SurfaceHolder surfaceHolder) { 
      camera.onSurfaceCreated(surfaceHolder); 
     } 

     @Override 
     public void onSurfaceChanged(SurfaceHolder surfaceHolder, int width, int height) { 
      camera.onSurfaceChanged(surfaceHolder, width, height); 
     } 

     @Override 
     public void onSurfaceDestroyed(SurfaceHolder surfaceHolder) { 
      camera.onSurfaceDestroyed(surfaceHolder); 
     } 
    } 
} 

CameraNewApi.class

@TargetApi(21) 
class CameraNewApi implements CameraUtility { 

    private static final String TAG = "CameraNewApi"; 

    private Semaphore cameraOpenCloseLock = new Semaphore(1); 

    private CameraUtility.cameraOpenedListener cameraOpenedListener; 

    private Context context; 

    private Handler backgroundHandler; 
    private HandlerThread backgroundThread; 

    private SurfaceHolder surfaceHolder; 

    private String backFacingCameraId; 
    private CaptureRequest.Builder captureRequestBuilder; 
    private CameraDevice cameraDevice; 
    private CameraCaptureSession cameraCaptureSessions; 

    CameraNewApi(Context context){ 
     this.context = context; 
    } 


    private final CameraDevice.StateCallback cameraDeviceStateCallback = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(@NonNull CameraDevice camera) { 
      Log.e(TAG, "onOpened"); 
      cameraOpenCloseLock.release(); 
      cameraDevice = camera; 
      if(surfaceHolder != null){ 
       createCameraPreview(); 
      } else { 
       releaseCameraComponents(); 
      } 
     } 

     @Override 
     public void onDisconnected(@NonNull CameraDevice camera) { 
      Log.d(TAG, "deviceCallback.onDisconnected() start"); 
      Log.e(TAG, "onDisconnected"); 
      if(cameraOpenedListener != null) { 
       cameraOpenedListener.onCameraOpened(false, false, false); 
      } 
      cameraOpenCloseLock.release(); 
      camera.close(); 
      cameraDevice = null; 
     } 

     @Override 
     public void onError(@NonNull CameraDevice camera, int error) { 
      Log.e(TAG, "onError"); 
      Log.d(TAG, "deviceCallback.onError() start"); 
      if(cameraOpenedListener != null) { 
       cameraOpenedListener.onCameraOpened(false, false, false); 
      } 
      cameraOpenCloseLock.release(); 
      camera.close(); 
      cameraDevice = null; 
     } 
    }; 

    private final CameraCaptureSession.StateCallback captureSessionStateCallback = new CameraCaptureSession.StateCallback() { 
     @Override 
     public void onConfigured(@NonNull CameraCaptureSession session) { 
      Log.e(TAG, "onConfigured"); 
      if(cameraDevice != null){ 
       cameraCaptureSessions = session; 
       captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
       try { 
        if(cameraOpenedListener != null) { 
         cameraOpenedListener.onCameraOpened(true, false, false); 
        } 
        session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler); 
       } catch (CameraAccessException e) { 
        Log.e(TAG, "Camera has been disconnected", e); 
       } catch (IllegalStateException e){ 
        Log.e(TAG, "Session was closed or camera device has been closed. ", e); 
        releaseCameraComponents(); 
       } 
      } 
     } 

     @Override 
     public void onConfigureFailed(@NonNull CameraCaptureSession session) { 
      Log.d(TAG, "Capture session configure failed: " + session); 
      Log.e(TAG, "onConfigureFailed"); 
     } 
    }; 

    @Override 
    public void createCamera(CameraUtility.cameraOpenedListener cameraOpenedListener) { 
     this.cameraOpenedListener = cameraOpenedListener; 

     startBackgroundThread(); 
     if(cameraOpenedListener != null){ 
      cameraOpenedListener.onCameraOpened(true, true, true); 
     } 
     initCamera(); 
    } 

    private void releaseCameraComponents(){ 
     try{ 
      cameraOpenCloseLock.acquire(); 
      if(cameraCaptureSessions != null){ 
       cameraCaptureSessions.close(); 
       cameraCaptureSessions = null; 
      } 
      if(cameraDevice != null){ 
       cameraDevice.close(); 
       cameraDevice = null; 
      } 
      if(surfaceHolder != null){ 
       surfaceHolder = null; 
      } 
      if(cameraOpenedListener != null){ 
       cameraOpenedListener = null; 
      } 
      Log.e(TAG, "cameraComponentsReleased"); 
     } catch (InterruptedException e) { 
      throw new RuntimeException("Interrupted while trying to lock camera closing.", e); 
     } finally { 
      cameraOpenCloseLock.release(); 
     } 
    } 
    @Override 
    public void releaseCamera() { 
     releaseCameraComponents(); 
     stopBackgroundThread(); 
    } 

    @Override 
    public void onSurfaceCreated(SurfaceHolder surfaceHolder) { 
     Log.e(TAG, "onSurfaceCreated"); 
     this.surfaceHolder = surfaceHolder; 
     openCamera(); 
    } 

    @Override 
    public void onSurfaceChanged(SurfaceHolder surfaceHolder, int width, int height) { 
     Log.e(TAG, "onSurfaceChanged"); 
     setSurfaceSize(width, height); 
    } 

    @Override 
    public void onSurfaceDestroyed(SurfaceHolder surfaceHolder) { 
     Log.e(TAG, "onSurfaceDestroyed"); 
    } 

    private void startBackgroundThread() { 
     Log.e(TAG, "startCameraThread"); 
     backgroundThread = new HandlerThread("CameraBackground"); 
     backgroundThread.start(); 
     backgroundHandler = new Handler(backgroundThread.getLooper()); 
    } 

    private void stopBackgroundThread() { 
     Log.e(TAG, "StopCameraThread"); 
     backgroundThread.quitSafely(); 
     try { 
      backgroundThread.join(); 
      backgroundThread = null; 
      backgroundHandler = null; 
     } catch (InterruptedException e) { 
      Log.e(TAG, "Error message: ", e); 
     } 
    } 

    private void initCamera(){ 
     Log.e(TAG, "initCamera"); 
     CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 

     try{ 
      for (String cameraId : cameraManager.getCameraIdList()) { 
       CameraCharacteristics characteristics 
         = cameraManager.getCameraCharacteristics(cameraId); 

       // Use back camera 
       Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); 
       if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) { 
        backFacingCameraId = cameraId; 
        break; 
       } 
      } 
      if(backFacingCameraId == null){ 
       Log.d(TAG, "Could not detect a camera"); 
      } 
     } catch (CameraAccessException e) { 
      Log.e(TAG, "Could not get camera list", e); 
     } 
    } 

    private void openCamera(){ 
     Log.e(TAG, "openCamera"); 
     CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 
     try{ 
      if(backFacingCameraId != null && cameraDevice == null){ 
       try{ 
        if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { 
         throw new RuntimeException("Time out waiting to lock camera opening."); 
        } 
        cameraManager.openCamera(backFacingCameraId, cameraDeviceStateCallback, backgroundHandler); 
       } catch (InterruptedException e) { 
        throw new RuntimeException("Interrupted while trying to lock camera opening.", e); 
       } 
      } 
     } catch(SecurityException e){ 
      Log.e(TAG, "Camera permission is not granted", e); 
     } catch(CameraAccessException e){ 
      Log.e(TAG, "Could not open camera", e); 
     } 
    } 

    private void createCameraPreview(){ 

     Log.e(TAG, "createCameraPreview"); 
     Surface surface = surfaceHolder.getSurface(); 

     List<Surface> surfaceList = Collections.singletonList(surface); 

     try { 
      captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
      captureRequestBuilder.addTarget(surface); 
      cameraDevice.createCaptureSession(surfaceList, captureSessionStateCallback, null); 
     } catch (CameraAccessException e){ 
      Log.e(TAG, "Could not create capture session for camera: " + cameraDevice.getId(), e); 
     } catch (IllegalStateException e){ 
      Log.e(TAG, "Camera has been closed", e); 
     } 
    } 

CameraUtility.interface

interface CameraUtility { 

    void createCamera(CameraUtility.cameraOpenedListener cameraOpenedListener); 
    void releaseCamera(); 
    void onSurfaceCreated(SurfaceHolder surfaceHolder); 
    void onSurfaceChanged(SurfaceHolder surfaceHolder, int width, int height); 
    void onSurfaceDestroyed(SurfaceHolder surfaceHolder); 

    interface cameraOpenedListener{ 
     void onCameraOpened(boolean succeeded, boolean addPreview, boolean progressBar); 
    } 
} 

MISE À JOUR

Voilà pourquoi cela ne se produit pas à chaque fois. Une erreur se produit lorsque, juste après l'appel de onPause, la session commence à répéter les demandes pour conserver l'aperçu (onConfigured). Puis cameraComponentsReleased triggers où tout le nettoyage est fait, y compris l'objet CameraDevice actuel. Vous n'avez toujours pas la moindre idée de comment gérer cette situation.

03-13 12:12:24.375 17555-17555/pl.tripper.tripper E/MainActivity: onPause 
03-13 12:12:24.395 17555-20454/pl.tripper.tripper E/CameraNewApi: onConfigured 
03-13 12:12:24.625 17555-17555/pl.tripper.tripper E/CameraNewApi: cameraComponentsReleased 
03-13 12:12:24.625 17555-17555/pl.tripper.tripper E/CameraNewApi: StopCameraThread 
03-13 12:12:24.625 17555-20454/pl.tripper.tripper E/CameraNewApi: Session was closed or camera device has been closed. 
                    java.lang.IllegalStateException: CameraDevice was already closed 
                     at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1997) 
                     at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:844) 
                     at android.hardware.camera2.impl.CameraDeviceImpl.setRepeatingRequest(CameraDeviceImpl.java:899) 
                     at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:236) 
                     at pl.tripper.tripper.camera.CameraNewApi$2.onConfigured(CameraNewApi.java:114) 
                     at java.lang.reflect.Method.invoke(Native Method) 
                     at android.hardware.camera2.dispatch.InvokeDispatcher.dispatch(InvokeDispatcher.java:39) 
                     at android.hardware.camera2.dispatch.HandlerDispatcher$1.run(HandlerDispatcher.java:65) 
                     at android.os.Handler.handleCallback(Handler.java:739) 
                     at android.os.Handler.dispatchMessage(Handler.java:95) 
                     at android.os.Looper.loop(Looper.java:158) 
                     at android.os.HandlerThread.run(HandlerThread.java:61) 
03-13 12:12:24.625 17555-20454/pl.tripper.tripper E/CameraNewApi: Camera onClosed 
03-13 12:12:24.625 17555-17555/pl.tripper.tripper E/CameraApiManager: cameraPreviewRemoved 

Répondre

1
java.lang.IllegalStateException: CameraDevice was already closed 

Cela signifie CameraDevice est fermée par une personne dans certaines situations. (ex: mémoire insuffisante) Pour gérer cela, vous pouvez ajouter le rappel onClosed() dans votre StateCallback - cameraDeviceStateCallback.

android.hardware.camera2.CameraDevice.StateCallback.onClosed(CameraDevice) 

Mise à jour:

Il ressemble à une condition de course. IMO, releaseCameraComponents et onConfigured doivent être synchronisés.

private void releaseCameraComponents(){ 
    synchronized(lock) { 
      .... 
    } 
} 
.... 

@Override 
public void onConfigured(@NonNull CameraCaptureSession session) { 
    synchronized(lock) { 
     .... 
    } 
} 
+0

Ajout d'informations nouvelles à la question – sheddar

+0

@You Kim - Je pense que vous avez raison.Il existe quelques conditions de concurrence possibles avec l'exemple camera2Basic, mais le rappel onConfigured est effectivement la dernière étape de la séquence ouverte, il est donc logique de l'inclure dans les plans de synchronisation. – Mick

1
mCameraOpenCloseLock.release() 

ce Sémaphore devraient être libérés après l'action createCaptureSession de la caméra pour éviter les conflits de ressources entre plusieurs threads. Le code source libère le sémaphore trop tôt juste après l'ouverture de la caméra. La suspension de l'application fermera l'appareil photo qui provoque l'erreur.

Pour le tester, appelez finish() avant mCameraOpenCloseLock.release(), vous ne verrez pas l'erreur