mrousavy / react-native-vision-camera

📸 A powerful, high-performance React Native Camera library.
https://react-native-vision-camera.com
MIT License
7.26k stars 1.06k forks source link

🐛 - Error while updating property 'cameraId' of a view managed by: CameraView #2245

Closed cauediademi closed 7 months ago

cauediademi commented 9 months ago

What's happening?

Just after updating my app to react-native-vision-camera version 3.6.11, it started crashing every time I make a call to the vision-camera Camera component. However, this bug only seems to occur on Galaxy S20 and Note 10 devices.

1st Edit: After I got my hands on an S20, I could do some digging on the code and found the exact error location: CameraCharacteristics+getPreviewSize.kt at line 36. Android just can't get screen size from the SurfaceHolder for the SurfaceView.

Also I could get the StreamConfiguration output for Galaxy S20:

StreamConfiguration(Outputs([w:640, h:480, format:DEPTH16(1144402265), min_duration:200000000, stall:0], [w:320, h:240, format:DEPTH16(1144402265), min_duration:50000000, stall:0]), HighResolutionOutputs(), Inputs(), ValidOutputFormatsForInput(), HighSpeedVideoConfigurations())

The Google documentation about getOutputSizes: https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap#getOutputSizes(int)

See the bug reported by one of my users: cameraIdBug Alert translation: An error has occurred with DoctorID DoctorID has closed because this app has a bug. Try to update the app after the developer has provided a fix for this error.

Reproduceable Code

package com.mrousavy.camera.extensions

import android.content.res.Resources
import android.hardware.camera2.CameraCharacteristics
import android.util.Size
import android.view.SurfaceHolder
import kotlin.math.abs

fun getMaximumPreviewSize(): Size {
  // See https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap
  // According to the Android Developer documentation, PREVIEW streams can have a resolution
  // of up to the phone's display's resolution, with a maximum of 1920x1080.
  val display1080p = Size(1920, 1080)
  val displaySize = Size(
    Resources.getSystem().displayMetrics.widthPixels,
    Resources.getSystem().displayMetrics.heightPixels
  )
  val isHighResScreen = displaySize.bigger >= display1080p.bigger || displaySize.smaller >= display1080p.smaller

  return if (isHighResScreen) display1080p else displaySize
}

fun CameraCharacteristics.getPreviewSizeFromAspectRatio(aspectRatio: Double): Size {
  val config = this.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
  val maximumPreviewSize = getMaximumPreviewSize()
  val outputSizes = config.getOutputSizes(SurfaceHolder::class.java)
    .sortedByDescending { it.width * it.height }
    .sortedBy { abs(aspectRatio - (it.bigger.toDouble() / it.smaller)) }

  return outputSizes.first { it.bigger <= maximumPreviewSize.bigger && it.smaller <= maximumPreviewSize.smaller }
}

fun CameraCharacteristics.getAutomaticPreviewSize(): Size {
  val config = this.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
  val maximumPreviewSize = getMaximumPreviewSize()
  val outputSizes = config.getOutputSizes(SurfaceHolder::class.java)
    .sortedByDescending { it.width * it.height }

  return outputSizes.first { it.bigger <= maximumPreviewSize.bigger && it.smaller <= maximumPreviewSize.smaller }
}

fun CameraCharacteristics.getPreviewTargetSize(aspectRatio: Double?): Size =
  if (aspectRatio != null) {
    getPreviewSizeFromAspectRatio(aspectRatio)
  } else {
    getAutomaticPreviewSize()
  }

Relevant log output

PreviewView: Creating PreviewView...
PreviewView: PreviewView onMeasure(0, 0)
PreviewView: coverSize :: 1920x1080 (0.5625), 0x0 (NaN)
PreviewView: Fitted dimensions set: 0x0
SurfaceView@84653e1: updateSurface: has no frame
unknown:ViewManager: Error while updating prop cameraId
unknown:ViewManager: java.lang.reflect.InvocationTargetException
unknown:ViewManager:    at java.lang.reflect.Method.invoke(Native Method)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:93)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:86)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManager.createViewInstance(ViewManager.java:188)
unknown:ViewManager:    at com.facebook.react.uimanager.ViewManager.createView(ViewManager.java:115)
unknown:ViewManager:    at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:281)
unknown:ViewManager:    at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:194)
unknown:ViewManager:    at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:909)
unknown:ViewManager:    at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1026)
unknown:ViewManager:    at com.facebook.react.uimanager.UIViewOperationQueue.access$2600(UIViewOperationQueue.java:47)
unknown:ViewManager:    at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1086)
unknown:ViewManager:    at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
unknown:ViewManager:    at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
unknown:ViewManager:    at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
unknown:ViewManager:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
unknown:ViewManager:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
unknown:ViewManager:    at android.view.Choreographer.doCallbacks(Choreographer.java:923)
unknown:ViewManager:    at android.view.Choreographer.doFrame(Choreographer.java:847)
unknown:ViewManager:    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
unknown:ViewManager:    at android.os.Handler.handleCallback(Handler.java:942)
unknown:ViewManager:    at android.os.Handler.dispatchMessage(Handler.java:99)
unknown:ViewManager:    at android.os.Looper.loopOnce(Looper.java:226)
unknown:ViewManager:    at android.os.Looper.loop(Looper.java:313)
unknown:ViewManager:    at android.app.ActivityThread.main(ActivityThread.java:8757)
unknown:ViewManager:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
unknown:ViewManager:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
unknown:ViewManager: Caused by: java.lang.NullPointerException: config.getOutputSizes(SurfaceHolder::class.java) must not be null
unknown:ViewManager:    at com.mrousavy.camera.extensions.CameraCharacteristics_getPreviewSizeKt.getAutomaticPreviewSize(CameraCharacteristics+getPreviewSize.kt:36)
unknown:ViewManager:    at com.mrousavy.camera.extensions.CameraCharacteristics_getPreviewSizeKt.getPreviewTargetSize(CameraCharacteristics+getPreviewSize.kt:46)
unknown:ViewManager:    at com.mrousavy.camera.core.PreviewView.resizeToInputCamera(PreviewView.kt:54)
unknown:ViewManager:    at com.mrousavy.camera.CameraView.setCameraId(CameraView.kt:54)
unknown:ViewManager:    at com.mrousavy.camera.CameraViewManager.setCameraId(CameraViewManager.kt:41)
unknown:ViewManager:    ... 29 more
AndroidRuntime: Shutting down VM
AndroidRuntime: FATAL EXCEPTION: main
AndroidRuntime: Process: br.com.accelerare.doctorid, PID: 20521
AndroidRuntime: com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'cameraId' of a view managed by: CameraView
AndroidRuntime:     at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:101)
AndroidRuntime:     at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136)
AndroidRuntime:     at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56)
AndroidRuntime:     at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:86)
AndroidRuntime:     at com.facebook.react.uimanager.ViewManager.createViewInstance(ViewManager.java:188)
AndroidRuntime:     at com.facebook.react.uimanager.ViewManager.createView(ViewManager.java:115)
AndroidRuntime:     at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:281)
AndroidRuntime:     at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:194)
AndroidRuntime:     at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:909)
AndroidRuntime:     at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1026)
AndroidRuntime:     at com.facebook.react.uimanager.UIViewOperationQueue.access$2600(UIViewOperationQueue.java:47)
AndroidRuntime:     at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1086)
AndroidRuntime:     at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
AndroidRuntime:     at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
AndroidRuntime:     at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
AndroidRuntime:     at android.view.Choreographer.doCallbacks(Choreographer.java:923)
AndroidRuntime:     at android.view.Choreographer.doFrame(Choreographer.java:847)
AndroidRuntime:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:942)
AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime:     at android.os.Looper.loopOnce(Looper.java:226)
AndroidRuntime:     at android.os.Looper.loop(Looper.java:313)
AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:8757)
AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
AndroidRuntime:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
AndroidRuntime: Caused by: java.lang.reflect.InvocationTargetException
AndroidRuntime:     at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:93)
AndroidRuntime:     ... 27 more
AndroidRuntime: Caused by: java.lang.NullPointerException: config.getOutputSizes(SurfaceHolder::class.java) must not be null
AndroidRuntime:     at com.mrousavy.camera.extensions.CameraCharacteristics_getPreviewSizeKt.getAutomaticPreviewSize(CameraCharacteristics+getPreviewSize.kt:36)
AndroidRuntime:     at com.mrousavy.camera.extensions.CameraCharacteristics_getPreviewSizeKt.getPreviewTargetSize(CameraCharacteristics+getPreviewSize.kt:46)
AndroidRuntime:     at com.mrousavy.camera.core.PreviewView.resizeToInputCamera(PreviewView.kt:54)
AndroidRuntime:     at com.mrousavy.camera.CameraView.setCameraId(CameraView.kt:54)
AndroidRuntime:     at com.mrousavy.camera.CameraViewManager.setCameraId(CameraViewManager.kt:41)
AndroidRuntime:     ... 29 more

Camera Device

{
  "formats": [],
  "sensorOrientation": "landscape-right",
  "hardwareLevel": "limited",
  "maxZoom": 1,
  "minZoom": 1,
  "supportsLowLightBoost": false,
  "neutralZoom": 1,
  "physicalDevices": ["wide-angle-camera"],
  "supportsFocus": true,
  "supportsRawCapture": false,
  "isMultiCam": false,
  "name": "BACK (4)",
  "hasFlash": false,
  "hasTorch": false,
  "position": "back",
  "id": "4"
}

Device

Galaxy Note10+ (SM-N975F) & Galaxy S20+ (SM-G985F)

VisionCamera Version

3.6.11

Can you reproduce this issue in the VisionCamera Example app?

No, I cannot reproduce the issue in the Example app

Additional information

DzianisAleshkou commented 8 months ago

Any update?

cauediademi commented 8 months ago

Think was fixed in 3.6.15. Uploading my app to production right now to prove it.

mrousavy commented 7 months ago

Hey! I think this is fixed already :)