2017-05-18 1 views
2

Je sais que cette question a été posée plusieurs fois mais je n'ai pas d'autre choix que de poser à nouveau cette question. J'utilise camera2 api pour afficher les caméras avant et arrière sur le même écran. J'ai créé deux vues de texture chacune avec deux instances de caméra. Même alors, je reçois une exception.Utiliser la caméra avant et arrière sur la même activité android

Ceci est mon code pour le MainActivity.java:

public class MainActivity extends AppCompatActivity { 

    private static final String TAG = "AndroidCameraApi"; 
    private TextureView textureView,textureView1; 
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 
    static { 
     ORIENTATIONS.append(Surface.ROTATION_0, 90); 
     ORIENTATIONS.append(Surface.ROTATION_90, 0); 
     ORIENTATIONS.append(Surface.ROTATION_180, 270); 
     ORIENTATIONS.append(Surface.ROTATION_270, 180); 
    } 
    private String cameraId,cameraId1; 
    protected CameraDevice cameraDevice,cameraDevice1; 
    protected CameraCaptureSession cameraCaptureSessions,cameraCaptureSessions1; 
    protected CaptureRequest.Builder captureRequestBuilder,captureRequestBuilder1; 
    private Size imageDimension,imageDimension1; 
    private static final int REQUEST_CAMERA_PERMISSION = 200; 
    private Handler mBackgroundHandler,mBackgroundHandler1; 
    private HandlerThread mBackgroundThread,mBackgroundThread1; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_android_camera_api); 
     textureView = (TextureView) findViewById(R.id.texture); 
     textureView1 = (TextureView) findViewById(texture1); 
     assert textureView != null; 
     assert textureView1 != null; 
     textureView.setSurfaceTextureListener(textureListener); 
     textureView1.setSurfaceTextureListener(textureListener1); 

    } 
    TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() { 
     @Override 
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
      //open your camera here 
      openCamera(); 
     } 
     @Override 
     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 
      // Transform you image captured size according to the surface width and height 
     } 
     @Override 
     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 
      return false; 
     } 
     @Override 
     public void onSurfaceTextureUpdated(SurfaceTexture surface) { 
     } 
    }; 

    TextureView.SurfaceTextureListener textureListener1 = new TextureView.SurfaceTextureListener() { 
     @Override 
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
      //open your camera here 
      openBackCamera(); 
     } 
     @Override 
     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 
      // Transform you image captured size according to the surface width and height 
     } 
     @Override 
     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 
      return false; 
     } 
     @Override 
     public void onSurfaceTextureUpdated(SurfaceTexture surface) { 
     } 
    }; 

    private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice camera) { 
      //This is called when the camera is open 
      Log.e(TAG, "onOpened"); 
      cameraDevice = camera; 
      createCameraPreview(); 
     } 
     @Override 
     public void onDisconnected(CameraDevice camera) { 
      cameraDevice.close(); 
     } 
     @Override 
     public void onError(CameraDevice camera, int error) { 
      cameraDevice.close(); 
      cameraDevice = null; 
     } 
    }; 


    private final CameraDevice.StateCallback stateCallback1 = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice camera) { 
      //This is called when the camera is open 
      Log.e(TAG, "onOpened"); 
      cameraDevice1 = camera; 
      createCameraPreview1(); 
     } 
     @Override 
     public void onDisconnected(CameraDevice camera) { 
      cameraDevice1.close(); 
     } 
     @Override 
     public void onError(CameraDevice camera, int error) { 
      cameraDevice1.close(); 
      cameraDevice1 = null; 
     } 
    }; 


    protected void startBackgroundThread() { 
     mBackgroundThread = new HandlerThread("Camera Background"); 
     mBackgroundThread.start(); 
     mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); 
    } 
    protected void stopBackgroundThread() { 
     mBackgroundThread.quitSafely(); 
     try { 
      mBackgroundThread.join(); 
      mBackgroundThread = null; 
      mBackgroundHandler = null; 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    protected void startBackgroundThread1() { 
     mBackgroundThread1 = new HandlerThread("Camera Background"); 
     mBackgroundThread1.start(); 
     mBackgroundHandler1 = new Handler(mBackgroundThread1.getLooper()); 
    } 
    protected void stopBackgroundThread1() { 
     mBackgroundThread1.quitSafely(); 
     try { 
      mBackgroundThread1.join(); 
      mBackgroundThread1 = null; 
      mBackgroundHandler1 = null; 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 


    protected void createCameraPreview() { 
     try { 
      SurfaceTexture texture = textureView.getSurfaceTexture(); 
      assert texture != null; 
      texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight()); 
      Surface surface = new Surface(texture); 
      captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
      captureRequestBuilder.addTarget(surface); 
      cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){ 
       @Override 
       public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { 
        //The camera is already closed 
        if (null == cameraDevice) { 
         return; 
        } 
        // When the session is ready, we start displaying the preview. 
        cameraCaptureSessions = cameraCaptureSession; 
        updatePreview(); 
       } 
       @Override 
       public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { 
        Toast.makeText(MainActivity.this, "Configuration change", Toast.LENGTH_SHORT).show(); 
       } 
      }, null); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    protected void createCameraPreview1() { 
     try { 
      SurfaceTexture texture1 = textureView1.getSurfaceTexture(); 
      assert texture1 != null; 
      texture1.setDefaultBufferSize(imageDimension1.getWidth(), imageDimension1.getHeight()); 
      Surface surface = new Surface(texture1); 
      captureRequestBuilder1 = cameraDevice1.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
      captureRequestBuilder1.addTarget(surface); 
      cameraDevice1.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){ 
       @Override 
       public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { 
        //The camera is already closed 
        if (null == cameraDevice1) { 
         return; 
        } 
        // When the session is ready, we start displaying the preview. 
        cameraCaptureSessions1 = cameraCaptureSession; 
        updatePreview1(); 
       } 
       @Override 
       public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { 
        Toast.makeText(MainActivity.this, "Configuration change", Toast.LENGTH_SHORT).show(); 
       } 
      }, null); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 


    private void openCamera() { 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     Log.e(TAG, "is camera open"); 
     try { 
      cameraId = manager.getCameraIdList()[0]; 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); 
      StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      assert map != null; 
      imageDimension = map.getOutputSizes(SurfaceTexture.class)[0]; 
      // Add permission for camera and let user grant the permission 
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
       ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION); 
       return; 
      } 
      manager.openCamera(cameraId, stateCallback, null); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
     Log.e(TAG, "openCamera X"); 
    } 

    private void openBackCamera() { 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     Log.e(TAG, "is camera open"); 
     try { 
      cameraId1 = manager.getCameraIdList()[1]; 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId1); 
      StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      assert map != null; 
      imageDimension1 = map.getOutputSizes(SurfaceTexture.class)[0]; 
      // Add permission for camera and let user grant the permission 
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
       ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION); 
       return; 
      } 
      manager.openCamera(cameraId1, stateCallback1, null); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
     Log.e(TAG, "openCamera X"); 
    } 


    protected void updatePreview() { 
     if(null == cameraDevice) { 
      Log.e(TAG, "updatePreview error, return"); 
     } 
     captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
     try { 
      cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    protected void updatePreview1() { 
     if(null == cameraDevice1) { 
      Log.e(TAG, "updatePreview error, return"); 
     } 
     captureRequestBuilder1.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
     try { 
      cameraCaptureSessions1.setRepeatingRequest(captureRequestBuilder1.build(), null, mBackgroundHandler1); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     if (requestCode == REQUEST_CAMERA_PERMISSION) { 
      if (grantResults[0] == PackageManager.PERMISSION_DENIED) { 
       // close the app 
       Toast.makeText(MainActivity.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show(); 
       finish(); 
      } 
     } 
    } 
    @Override 
    protected void onResume() { 
     super.onResume(); 
     Log.e(TAG, "onResume"); 
     startBackgroundThread(); 
     startBackgroundThread1(); 
     if (textureView.isAvailable()) { 
      openCamera(); 
     } else { 
      textureView.setSurfaceTextureListener(textureListener); 
     } 

     if (textureView1.isAvailable()) { 
      openBackCamera(); 
     } else { 
      textureView1.setSurfaceTextureListener(textureListener1); 
     } 

    } 
    @Override 
    protected void onPause() { 
     Log.e(TAG, "onPause"); 
     //closeCamera(); 
     stopBackgroundThread(); 
     stopBackgroundThread1(); 
     super.onPause(); 
    } 
} 

code pour le fichier de mise en page:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    > 
    <TextureView 
     android:id="@+id/texture" 
     android:layout_width="match_parent" 
     android:layout_height="200dp" 
     android:layout_marginBottom="10dp"/> 

    <TextureView 
     android:id="@+id/texture1" 
     android:layout_width="match_parent" 
     android:layout_height="200dp" 
     /> 

</LinearLayout> 

Exception je reçois est comme ci-dessous:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.camera2.CameraDevice.close()' on a null object reference 

Je suis obtenir une exception sur cette ligne:

cameraDevice1.close(); 

Répondre

1

Lequel des appels cameraDevice1.close() échoue? Avez-vous déjà eu un appel surOpened pour cette caméra?

Rien ne garantit qu'un appareil Android donné peut avoir plusieurs caméras ouvertes en même temps. la seule façon de savoir est d'essayer, et si cela ne peut pas être fait, la seconde caméra ne se déclenchera pas sur Oopened, elle se déclenchera sur Error avec le code d'erreur TOO_MANY_CAMERAS_IN_USE.

Donc, si cela se produit ici, alors vous obtiendrez onError sans onOpened, et votre cameraDevice1 n'aura jamais été défini.

+0

Oui, il n'y a pas d'appel onOpened pour la deuxième caméra. L'appareil ne doit donc pas avoir plusieurs caméras ouvertes en même temps comme vous l'avez dit. Mais y a-t-il une solution pour cela? –

+0

Malheureusement non - c'est généralement une limitation matérielle; les caméras avant et arrière partagent le matériel de traitement, et il n'y en a pas assez pour les deux à la fois. (Parfois, il y en a assez pour exécuter une caméra à très basse résolution ou avec d'autres fonctionnalités limitées, mais ce n'est pas quelque chose que l'API peut vous dire - mais l'application caméra intégrée peut utiliser des interfaces personnalisées). –

+0

Ok merci beaucoup –