2017-05-18 7 views
2

この質問は何度も尋ねられましたが、私はもう一度この質問をする以外の選択肢はありません。私はcamera2 apiを使用して、前画面と後画面の両方のカメラを同じ画面に表示しています。 2つのカメラインスタンスを持つ2つのテクスチャビューを作成しました。それでも私は例外を得ています。前と後ろのカメラを同じアクティビティで使用するandroid

これは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(); 
    } 
} 

コード:私は取得しています

<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> 

例外は以下の通りです:

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

私はこの行で例外が発生する:

cameraDevice1.close(); 

答えて

1

cameraDevice1.close()のどちらが失敗しますか?あなたはそのカメラのためにonOpenedコールを受けたことがありますか?

特定のAndroid搭載端末で複数のカメラを同時に開くことはできません。知る唯一の方法は試してみることです。できなければ2番目のカメラはonOpenedを発しません。エラーコードTOO_MANY_CAMERAS_IN_USEでonErrorを発生させます。

ここでそれが起こっていると、onOpenedを使わずにonErrorを取得し、cameraDevice1は決して設定されません。

+0

はい2番目のカメラのonOpenedコールはありません。あなたが言ったように、デバイスは同時に複数のカメラを開いていてはいけません。しかし、これにはどんな解決策がありますか? –

+0

残念ながらこれは一般的にハードウェアの制限です。フロントカメラとバックカメラは処理ハードウェアを共有し、同時に両方を実行するのに十分ではありません。 (時には、1つのカメラを非常に低い解像度で、または他の限られた機能で動作させるには十分ですが、これはAPIが教えてくれるものではありませんが、組み込みのカメラアプリでカスタムインターフェイスを使用できるかもしれません。 –

+0

よろしくお願い申し上げます –

関連する問題