From 2f889f5855fe6e478dcbe476cfa68c89fa5d961e Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 7 Jul 2021 15:00:32 +0200 Subject: [PATCH] fix: Fix hot-reload crash caused by Frame Processor Runtime being initialized twice (#258) * Fix Frame Processor Runtime being initialized twice causing a hot-reload to crash * Remove unnecessary `HasRegisteredPlugins` singleton * make non-optional * `REACT_CLASS` -> `TAG` * fix nullable --- .../java/com/mrousavy/camera/CameraView.kt | 5 ++-- .../com/mrousavy/camera/CameraViewManager.kt | 6 ++--- .../com/mrousavy/camera/CameraViewModule.kt | 19 ++++++++------ .../FrameProcessorRuntimeManager.kt | 25 ++++++------------- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/android/src/main/java/com/mrousavy/camera/CameraView.kt b/android/src/main/java/com/mrousavy/camera/CameraView.kt index 59cf3d5..04a85f7 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -113,7 +113,7 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner { private var maxZoom: Float = 1f @DoNotStrip - private var mHybridData: HybridData? + private var mHybridData: HybridData @Suppress("LiftReturnOrAssignment", "RedundantIf") internal val fallbackToSnapshot: Boolean @@ -185,7 +185,7 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner { } fun finalize() { - mHybridData?.resetNative() + mHybridData.resetNative() } private external fun initHybrid(): HybridData @@ -478,7 +478,6 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner { const val TAG_PERF = "CameraView.performance" private val propsThatRequireSessionReconfiguration = arrayListOf("cameraId", "format", "fps", "hdr", "lowLightBoost", "photo", "video", "frameProcessorFps") - private val arrayListOfZoom = arrayListOf("zoom") } } diff --git a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt index 55035ee..081f5e9 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraViewManager.kt @@ -155,16 +155,16 @@ class CameraViewManager : SimpleViewManager() { } override fun onDropViewInstance(view: CameraView) { - Log.d(REACT_CLASS, "onDropViewInstance() called!") + Log.d(TAG, "onDropViewInstance() called!") super.onDropViewInstance(view) } override fun getName(): String { - return REACT_CLASS + return TAG } companion object { - const val REACT_CLASS = "CameraView" + const val TAG = "CameraView" val cameraViewTransactions: HashMap> = HashMap() } diff --git a/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt b/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt index 417dcf5..8a5f97c 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt @@ -25,7 +25,7 @@ import kotlinx.coroutines.guava.await class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { companion object { - const val REACT_CLASS = "CameraView" + const val TAG = "CameraView" var RequestCode = 10 val FrameProcessorThread: ExecutorService = Executors.newSingleThreadExecutor() @@ -42,10 +42,12 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase override fun initialize() { super.initialize() - FrameProcessorThread.execute { - frameProcessorManager = FrameProcessorRuntimeManager(reactApplicationContext) - reactApplicationContext.runOnJSQueueThread { - frameProcessorManager!!.installJSIBindings() + if (frameProcessorManager == null) { + FrameProcessorThread.execute { + frameProcessorManager = FrameProcessorRuntimeManager(reactApplicationContext) + reactApplicationContext.runOnJSQueueThread { + frameProcessorManager!!.installJSIBindings() + } } } } @@ -53,10 +55,11 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase override fun onCatalystInstanceDestroy() { super.onCatalystInstanceDestroy() frameProcessorManager?.destroy() + frameProcessorManager = null } override fun getName(): String { - return REACT_CLASS + return TAG } private fun findCameraView(id: Int): CameraView = reactApplicationContext.currentActivity?.findViewById(id) ?: throw ViewNotFoundError(id) @@ -208,7 +211,7 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase val secondsPerFrame = try { cameraConfig.getOutputMinFrameDuration(formatId, size) / 1_000_000_000.0 } catch (error: Throwable) { - Log.e(REACT_CLASS, "Minimum Frame Duration for MediaRecorder Output cannot be calculated, format \"$formatName\" is not supported.") + Log.e(TAG, "Minimum Frame Duration for MediaRecorder Output cannot be calculated, format \"$formatName\" is not supported.") null } @@ -264,7 +267,7 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase } val difference = System.currentTimeMillis() - startTime - Log.w(REACT_CLASS, "CameraViewModule::getAvailableCameraDevices took: $difference ms") + Log.w(TAG, "CameraViewModule::getAvailableCameraDevices took: $difference ms") return@withPromise cameraDevices } } diff --git a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorRuntimeManager.kt b/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorRuntimeManager.kt index 736f984..34e0b98 100644 --- a/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorRuntimeManager.kt +++ b/android/src/main/java/com/mrousavy/camera/frameprocessor/FrameProcessorRuntimeManager.kt @@ -15,15 +15,7 @@ import java.lang.ref.WeakReference class FrameProcessorRuntimeManager(context: ReactApplicationContext) { companion object { const val TAG = "FrameProcessorRuntime" - private var HasRegisteredPlugins = false val Plugins: ArrayList = ArrayList() - get() { - if (HasRegisteredPlugins) { - throw Error("Tried to access Frame Processor Plugin list, " + - "but plugins have already been registered (list is frozen now!).") - } - return field - } init { System.loadLibrary("reanimated") @@ -32,15 +24,15 @@ class FrameProcessorRuntimeManager(context: ReactApplicationContext) { } @DoNotStrip - private var mHybridData: HybridData? - private var mContext: WeakReference? - private var mScheduler: Scheduler? + private var mHybridData: HybridData + private var mContext: WeakReference + private var mScheduler: Scheduler init { val holder = context.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl mScheduler = Scheduler(context) mContext = WeakReference(context) - mHybridData = initHybrid(context.javaScriptContextHolder.get(), holder, mScheduler!!) + mHybridData = initHybrid(context.javaScriptContextHolder.get(), holder, mScheduler) initializeRuntime() Log.i(TAG, "Installing Frame Processor Plugins...") @@ -48,19 +40,18 @@ class FrameProcessorRuntimeManager(context: ReactApplicationContext) { registerPlugin(plugin) } Log.i(TAG, "Successfully installed ${Plugins.count()} Frame Processor Plugins!") - HasRegisteredPlugins = true } fun destroy() { - mScheduler?.deactivate() - mHybridData?.resetNative() + mScheduler.deactivate() + mHybridData.resetNative() } @DoNotStrip @Keep fun findCameraViewById(viewId: Int): CameraView { Log.d(TAG, "finding view $viewId...") - val view = mContext?.get()?.currentActivity?.findViewById(viewId) + val view = mContext.get()?.currentActivity?.findViewById(viewId) Log.d(TAG, "found view $viewId! is null: ${view == null}") return view ?: throw ViewNotFoundError(viewId) } @@ -70,7 +61,7 @@ class FrameProcessorRuntimeManager(context: ReactApplicationContext) { jsContext: Long, jsCallInvokerHolder: CallInvokerHolderImpl, scheduler: Scheduler - ): HybridData? + ): HybridData private external fun initializeRuntime() private external fun registerPlugin(plugin: FrameProcessorPlugin)