2017-11-28 17 views
1

私はandroidでcamera2 apiを使用していて、TextureViewとSurfaceViewを切り替えようとしたので、TextureViewをSurfaceViewと置き換えて、TextureView.SurfaceTextureListenerをSurfaceHolder.Callbackに置き換えてみました。アンドロイド7のすべての携帯電話がクラッシュするようになりました。 (私は必要なアクセス許可と実行時のアクセス許可を必要としています - アプリケーションはSurfaceViewに切り替える前にうまくいきました)。camera2 throw SecurityException

ラインでのアプリのクラッシュ:

mPreviewBuilder = 
    mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 

古いコード:

private TextureView.SurfaceTextureListener mSurfaceTextureListener 
     = new TextureView.SurfaceTextureListener() { 

    @Override 
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, 
             int width, int height) { 
    openCamera(width, height); 
} 

@Override 
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, 
             int width, int height) { 
    configureTransform(width, height); 
} 

@Override 
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { 
    return true; 
} 

@Override 
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { 
} 

}; 
/** 
* Start the camera preview. 
*/ 
private void startPreview() { 
    if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) { 
     return; 
    } 
    try { 
     closePreviewSession(); 
     SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
     assert texture != null; 
     texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
     mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 

     Surface previewSurface = new Surface(texture); 
     mPreviewBuilder.addTarget(previewSurface); 

mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface), 
     new CameraCaptureSession.StateCallback() { 
       @Override 
       public void onConfigured(@NonNull CameraCaptureSession session) { 
        mPreviewSession = session; 
        updatePreview(); 
       } 

       @Override 
       public void onConfigureFailed(@NonNull CameraCaptureSession session) { 
        if (null != activity) { 
         Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show(); 
        } 
       } 
      }, mBackgroundHandler); 
} catch (CameraAccessException e) { 
    e.printStackTrace(); 
} 
} 

新しいコード:

private SurfaceHolder.Callback mSurfaceViewListener = 
     new SurfaceHolder.Callback() { 
      @Override 
      public void surfaceCreated(SurfaceHolder surfaceHolder) { 
       SurfaceViewLifeCycle.setSurfaceState(SurfaceViewLifeCycle.SURFACE_VIEW_LIFE_CYCLE_CREATED); 
       openCamera(640, 480); 
      } 

      @Override 
      public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { 

      } 

      @Override 
      public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 
       SurfaceViewLifeCycle.setSurfaceState(SurfaceViewLifeCycle.SURFACE_VIEW_LIFE_CYCLE_DESTROYED); 
       closeCamera(); 
      } 
     }; 


    /** 
* Start the camera preview. 
*/ 
private void startPreview() { 
    if (null == mCameraDevice || 
      SurfaceViewLifeCycle.getSurfaceState() != SurfaceViewLifeCycle.SURFACE_VIEW_LIFE_CYCLE_CREATED || 
      null == mPreviewSize) { 
     return; 
    } 
    try { 
     closePreviewSession(); 
     //SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
     //assert texture != null; 
     //texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
     mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     //Surface previewSurface = new Surface(texture); 
     Surface previewSurface = mSurfaceView.getHolder().getSurface(); 
     mPreviewBuilder.addTarget(previewSurface); 

     mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface), 
       new CameraCaptureSession.StateCallback() { 

        @Override 
        public void onConfigured(@NonNull CameraCaptureSession session) { 
         mPreviewSession = session; 
         updatePreview(); 
        } 

        @Override 
        public void onConfigureFailed(@NonNull CameraCaptureSession session) { 
         if (null != activity) { 
          Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show(); 
         } 
        } 
       }, mBackgroundHandler); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

エラーログ:

11-28 15:38:32.253 13516-13516/rifdsafsda.com.phase9try12 E/AndroidRuntime: FATAL EXCEPTION: main 
                      Process: rifdsafsda.com.phase9try12, PID: 13516 
                      java.lang.SecurityException: Lacking privileges to access camera service 
                       at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108) 
                       at android.hardware.camera2.utils.CameraBinderDecorator$CameraBinderDecoratorListener.onAfterInvocation(CameraBinderDecorator.java:73) 
                       at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81) 
                       at java.lang.reflect.Proxy.invoke(Proxy.java:393) 
                       at $Proxy1.createDefaultRequest(Unknown Source) 
                       at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureRequest(CameraDeviceImpl.java:628) 
                       at rifdsafsda.com.phase9try12.media.camera.RecordingManager.startPreview(RecordingManager.java:282) 
                       at rifdsafsda.com.phase9try12.media.camera.RecordingManager.access$300(RecordingManager.java:41) 
                       at rifdsafsda.com.phase9try12.media.camera.RecordingManager$2.onOpened(RecordingManager.java:121) 
                       at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:134) 
                       at android.os.Handler.handleCallback(Handler.java:739) 
                       at android.os.Handler.dispatchMessage(Handler.java:95) 
                       at android.os.Looper.loop(Looper.java:148) 
                       at android.app.ActivityThread.main(ActivityThread.java:5417) 
                       at java.lang.reflect.Method.invoke(Native Method) 
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

答えて

0

openCameraを試み、このチェックと呼ばれた後、カメラのアクセス許可が付与されているようだ:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && 
ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) 
{ 
    ActivityCompat.requestPermissions(AndroidCameraApi.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_PERMISSION_REQUEST_ID); 
} 
else 
{ 
    openCamera(640, 480); 
} 
+0

カメラの権限とその他のすべての権限が(外部記憶装置、記録オーディオなどを書き込む)前のアクティビティでユーザーが付与されていますそうでなければ、彼はカメラアクティビティに進むことができなくなるでしょう – Admond

+0

SurfaceViewコールバックがTextureViewコールバックより速く働いていて、カメラオフなどのようなものの順序が変更を必要としたので、問題が見つかりました。 – Admond

+0

openCameraを呼び出したときに、私が指摘したように、まだアクセス許可がなかったので、あなたの呼び出しを同期することができれば幸いです。 –