react-native-vision-camera icon indicating copy to clipboard operation
react-native-vision-camera copied to clipboard

🐛 java.lang.NullPointerException in FrameProcessorRuntimeManager.<init>

Open pistonsky opened this issue 3 years ago • 1 comments

What were you trying to do?

We have 40k MAU and we see 230 occurrences of this error for the last 30 days.

Reproduceable Code

No response

What happened instead?

The issue seems to happen on app start.

Relevant log output

java.lang.NullPointerException: 
  at java.util.Objects.requireNonNull (Objects.java:245)
  at com.mrousavy.camera.frameprocessor.FrameProcessorRuntimeManager.<init> (FrameProcessorRuntimeManager.kt:33)
  at com.mrousavy.camera.CameraViewManager$1.run (CameraViewManager.kt:20)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
  at java.lang.Thread.run (Thread.java:920)

Device

Android only: most seen on Google Pixel 4a, Google Pixel 6, Samsung Galaxy S20 FE 5G, Samsung Galaxy Z Flip3 5G, all have Android 12

VisionCamera Version

2.10.0

Additional information

pistonsky avatar Mar 29 '22 14:03 pistonsky

Any solution?

hasnainbaloch avatar Sep 08 '22 15:09 hasnainbaloch

+1

foolem avatar Oct 10 '22 10:10 foolem

+1

andreshsingh avatar Oct 13 '22 13:10 andreshsingh

same problem, I'm using:

"react-native": "0.70.6", "react-native-vision-camera": "^2.15.2", "vision-camera-code-scanner": "^0.2.0", "react-native-reanimated": "^2.12.0",

MadsonChavante avatar Nov 21 '22 12:11 MadsonChavante

same issue

zienna avatar Dec 05 '22 14:12 zienna

Facing very similar issue.

Seeing lot of crashes due to this error. 60 crashes in the last week.

Exception java.lang.NullPointerException: null cannot be cast to non-null type com.facebook.react.turbomodule.core.CallInvokerHolderImpl
  at java.util.Objects.requireNonNull (Objects.java:245)
  at com.mrousavy.camera.frameprocessor.FrameProcessorRuntimeManager.<init> (FrameProcessorRuntimeManager.java)
  at com.mrousavy.camera.CameraViewModule.initialize$lambda-0 (CameraViewModule.java)
  at com.mrousavy.camera.CameraViewModule.$r8$lambda$YiRnUrObfbO8oH48lnR0UOsrros (CameraViewModule.java)
  at com.mrousavy.camera.CameraViewModule$$InternalSyntheticLambda$0$15c136e33c636d11a2dd0aeb7487301cc8ebad6f30ea165f989afc83412e349f$0.run (CameraViewModule.java)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1137)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:637)
  at java.lang.Thread.run (Thread.java:1012)

"react-native": "0.68.3", "react-native-vision-camera": "^2.14.1", "vision-camera-code-scanner": "^0.2.0",

sachitram-cv avatar Feb 09 '23 11:02 sachitram-cv

Anyone found a solution?

sachitram-cv avatar Feb 15 '23 05:02 sachitram-cv

Not sure if this is a solution or not as I've only seen one crash. But I added this to FrameProcessorRuntimeManager.kt if (enableFrameProcessors && context.catalystInstance.jsCallInvokerHolder != null) { instead of if (enableFrameProcessors) {

I did a postinstall script

const fs = require("fs");

const updateRNVC = () => {
  const codeToObscure = "if (enableFrameProcessors) {";
  const problemFilePath =
    "./node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorRuntimeManager.kt";
  const problemFileContent = fs.readFileSync(problemFilePath, "utf8");
  fs.writeFileSync(
    problemFilePath,
    problemFileContent.replace(
      codeToObscure,
      "// added by updateRNVC.js\n" +
        "if (enableFrameProcessors && context.catalystInstance.jsCallInvokerHolder != null) {",
    ),
    "utf8",
  );
};

updateRNVC();

JustinRohweller avatar Feb 18 '23 01:02 JustinRohweller

same in 2.15.2

2sem avatar Mar 01 '23 10:03 2sem

Not sure if this is a solution or not as I've only seen one crash. But I added this to FrameProcessorRuntimeManager.kt if (enableFrameProcessors && context.catalystInstance.jsCallInvokerHolder != null) { instead of `if (enableFrameProcessors)

But then the frame processors would never be initialized @JustinRohweller? btw: you can use patch-package to apply this patch

pke avatar Mar 22 '23 10:03 pke

@mrousavy My guess is, the frameprocessor manager is initialised before the catalys context is fully initalised. That is a race conditon issue.

context.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl here jsCallInvokerHolder is still null. Couldn't the creation of the manager delayed until the catalystInstance is fully ready?

pke avatar Mar 22 '23 10:03 pke

same issue in 2.15.4

devoren avatar Mar 22 '23 15:03 devoren

@pke Correct, my fix just works if you're not using frame processors. And yea using patch-package likely would have been the wise thing to do.

JustinRohweller avatar Mar 22 '23 18:03 JustinRohweller

I created a working patch that will fix this issue. Will create PR soon.

pke avatar Mar 22 '23 18:03 pke

@pke any idea when do you will do a PR to fix?

ClaudionorJunior avatar Apr 12 '23 16:04 ClaudionorJunior

I attach the patch file here, if someone has the time to create a PR from it. But I guess since V3 is being worked on that PR might not be merged soon.

react-native-vision-camera+2.15.4.patch

diff --git a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt
index 7672b15..e6bab61 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt
@@ -58,16 +58,6 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase
     frameProcessorManager = null
   }
 
-  override fun initialize() {
-    super.initialize()
-
-    if (frameProcessorManager == null) {
-      frameProcessorThread.execute {
-        frameProcessorManager = FrameProcessorRuntimeManager(reactApplicationContext, frameProcessorThread)
-      }
-    }
-  }
-
   override fun onCatalystInstanceDestroy() {
     super.onCatalystInstanceDestroy()
     cleanup()
@@ -89,6 +79,21 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase
     return view ?: throw ViewNotFoundError(viewId)
   }
 
+  @ReactMethod
+  fun installFrameProcessorBindings(): Boolean {
+    try {
+      if (frameProcessorManager == null) {
+        frameProcessorThread.execute {
+          frameProcessorManager = FrameProcessorRuntimeManager(reactApplicationContext, frameProcessorThread)
+        }
+      }
+      return true;
+    } catch (e: Error) {
+      Log.e(TAG, "Failed to install Frame Processor JSI Bindings!", e)
+      return false;
+    }
+  }
+
   @ReactMethod
   fun takePhoto(viewTag: Int, options: ReadableMap, promise: Promise) {
     coroutineScope.launch {
diff --git a/node_modules/react-native-vision-camera/lib/typescript/Camera.d.ts b/node_modules/react-native-vision-camera/lib/typescript/Camera.d.ts
index 7efd264..e9bc88e 100644
--- a/node_modules/react-native-vision-camera/lib/typescript/Camera.d.ts
+++ b/node_modules/react-native-vision-camera/lib/typescript/Camera.d.ts
@@ -48,6 +48,7 @@ export declare class Camera extends React.PureComponent<CameraProps> {
     /** @internal */
     constructor(props: CameraProps);
     private get handle();
+
     /**
      * Take a single photo and write it's content to a temporary file.
      *
diff --git a/node_modules/react-native-vision-camera/src/hooks/useFrameProcessor.ts b/node_modules/react-native-vision-camera/src/hooks/useFrameProcessor.ts
index 697872f..6d6b161 100644
--- a/node_modules/react-native-vision-camera/src/hooks/useFrameProcessor.ts
+++ b/node_modules/react-native-vision-camera/src/hooks/useFrameProcessor.ts
@@ -1,10 +1,16 @@
 /* global _setGlobalConsole */
 
 import { DependencyList, useCallback } from 'react';
+import { NativeModules, Platform } from 'react-native';
 import type { Frame } from '../Frame';
+const CameraModule = NativeModules.CameraView;
 
 type FrameProcessor = (frame: Frame) => void;
 
+if (Platform.OS === "android") {
+  CameraModule.installFrameProcessorBindings();
+}
+
 const capturableConsole = console;
 
 /**

pke avatar Apr 13 '23 11:04 pke

I am having the same issue, my current version:

  "react": "18.2.0",
  "react-native": "0.71.4",
  "react-native-vision-camera": "2.15.4",
  "vision-camera-code-scanner": "0.2.0"

If the PR can fix the issue, can you guys please help us to merge it. Many thanks!

LuongTruong avatar Apr 25 '23 04:04 LuongTruong

I created a PR for this, appreciate any support in reviewing/testing that you can give #1583

jthure avatar May 04 '23 09:05 jthure

Hey! I've rewritten the entire Android codebase of VisionCamera from CameraX to Camera2 in the efforts of ✨ VisionCamera V3.

I just now completed the Camera2 rewrite and I believe the core structure is running, but there might be some edge cases to iron out. Can you try and test the PR #1674 for me to see if you can still reproduce this issue here?

Here's an instruction on how you can test that: https://github.com/mrousavy/react-native-vision-camera/pull/1674#issuecomment-1684104217

If the issue cannot be reproduced with that version/PR anymore, then hoorayy, I fixed it! 🎉 Otherwise please let me know and I'll keep this issue open to keep track of it.

Thank you!

mrousavy avatar Aug 18 '23 16:08 mrousavy

@mrousavy in 2.x we are facing this same issue and 3.x is also not stable (code scanner crash, no Flash support). Can you please suggest if anyway we can avoid this crash i 2.x version.

deepakv-z14 avatar Nov 24 '23 13:11 deepakv-z14