feat: New JS API for useCameraDevice
and useCameraFormat
and much faster getAvailableCameraDevices()
(#1784)
* Update podfile * Update useCameraFormat.ts * Update API * Delete FormatFilter.md * Format CameraViewManager.m ObjC style * Make `getAvailableCameraDevices` synchronous/blocking * Create some docs * fix: Fix HardwareLevel types * fix: Use new device/format API * Use 60 FPS format as an example * Replace `Camera.getAvailableCameraDevices` with new `CameraDevices` API/Module * Fix Lint * KTLint options * Use continuation indent of 8 * Use 2 spaces for indent * Update .editorconfig * Format code * Update .editorconfig * Format more * Update VideoStabilizationMode.kt * fix: Expose `CameraDevicesManager` to ObjC * Update CameraPage.tsx * fix: `requiresMainQueueSetup() -> false` * Always prefer higher resolution * Update CameraDevicesManager.swift * Update CameraPage.tsx * Also filter pixelFormat * fix: Add AVFoundation import
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package com.mrousavy.camera
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.util.Log
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||
import com.facebook.react.bridge.ReactMethod
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule
|
||||
import com.mrousavy.camera.core.CameraDeviceDetails
|
||||
|
||||
class CameraDevicesManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
||||
companion object {
|
||||
private const val TAG = "CameraDevices"
|
||||
}
|
||||
private val cameraManager = reactContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
|
||||
private val callback = object : CameraManager.AvailabilityCallback() {
|
||||
private var devices = cameraManager.cameraIdList.toMutableList()
|
||||
|
||||
// Check if device is still physically connected (even if onCameraUnavailable() is called)
|
||||
private fun isDeviceConnected(cameraId: String): Boolean =
|
||||
try {
|
||||
cameraManager.getCameraCharacteristics(cameraId)
|
||||
true
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
|
||||
override fun onCameraAvailable(cameraId: String) {
|
||||
Log.i(TAG, "Camera #$cameraId: Available!")
|
||||
if (!devices.contains(cameraId)) {
|
||||
devices.add(cameraId)
|
||||
sendAvailableDevicesChangedEvent()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCameraUnavailable(cameraId: String) {
|
||||
Log.i(TAG, "Camera #$cameraId: Unavailable!")
|
||||
if (devices.contains(cameraId) && !isDeviceConnected(cameraId)) {
|
||||
devices.remove(cameraId)
|
||||
sendAvailableDevicesChangedEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName(): String = TAG
|
||||
|
||||
override fun initialize() {
|
||||
cameraManager.registerAvailabilityCallback(callback, null)
|
||||
}
|
||||
|
||||
override fun invalidate() {
|
||||
cameraManager.unregisterAvailabilityCallback(callback)
|
||||
super.invalidate()
|
||||
}
|
||||
|
||||
private fun getDevicesJson(): ReadableArray {
|
||||
val devices = Arguments.createArray()
|
||||
cameraManager.cameraIdList.forEach { cameraId ->
|
||||
val device = CameraDeviceDetails(cameraManager, cameraId)
|
||||
devices.pushMap(device.toMap())
|
||||
}
|
||||
return devices
|
||||
}
|
||||
|
||||
fun sendAvailableDevicesChangedEvent() {
|
||||
val eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
eventEmitter.emit("CameraDevicesChanged", getDevicesJson())
|
||||
}
|
||||
|
||||
override fun hasConstants(): Boolean = true
|
||||
|
||||
override fun getConstants(): MutableMap<String, Any> = mutableMapOf("availableCameraDevices" to getDevicesJson())
|
||||
|
||||
// Required for NativeEventEmitter, this is just a dummy implementation:
|
||||
@ReactMethod
|
||||
fun addListener(eventName: String) {}
|
||||
|
||||
@ReactMethod
|
||||
fun removeListeners(count: Int) {}
|
||||
}
|
Reference in New Issue
Block a user