This commit is contained in:
xsl
2026-03-12 21:13:07 +08:00
parent f7982d45de
commit 55c64a6db4
149 changed files with 15472 additions and 1 deletions
@@ -0,0 +1,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="uts.sdk.modules.XFCameraUTS">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.any" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="true" />
<application android:requestLegacyExternalStorage="true">
<meta-data android:name="ScopedStorage" android:value="true" />
</application>
</manifest>
@@ -0,0 +1,16 @@
{
"minSdkVersion": "19",
"dependencies": [
"androidx.camera:camera-core:1.4.0-alpha04",
"androidx.camera:camera-camera2:1.4.0-alpha04",
"androidx.camera:camera-lifecycle:1.4.0-alpha04",
"androidx.camera:camera-video:1.4.0-alpha04",
"androidx.camera:camera-view:1.4.0-alpha04"
],
"components": [
{
"name": "xf-camera",
"class": "uts.sdk.modules.SkinCameraUTS.XfCameraComponent"
}
]
}
@@ -0,0 +1,745 @@
@file:Suppress("UNCHECKED_CAST", "USELESS_CAST", "INAPPLICABLE_JVM_NAME", "UNUSED_ANONYMOUS_PARAMETER", "NAME_SHADOWING", "UNNECESSARY_NOT_NULL_ASSERTION")
package uts.sdk.modules.SkinCameraUTS
import android.content.Context
import android.graphics.ImageFormat
import android.util.Size
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.camera.core.CameraControl
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
import androidx.camera.core.MirrorMode
import androidx.camera.core.Preview
import androidx.camera.core.UseCaseGroup
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.FileOutputOptions
import androidx.camera.video.Quality
import androidx.camera.video.QualitySelector
import androidx.camera.video.Recorder
import androidx.camera.video.Recording
import androidx.camera.video.VideoCapture
import androidx.camera.video.VideoRecordEvent
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import io.dcloud.uniapp.*
import io.dcloud.uniapp.UniSDKEngine
import io.dcloud.uniapp.appframe.PageProxy
import io.dcloud.uniapp.dom.node.DomNode
import io.dcloud.uniapp.dom.node.PageNode
import io.dcloud.uniapp.extapi.*
import io.dcloud.uniapp.framework.*
import io.dcloud.uniapp.interfaces.INodeData
import io.dcloud.uniapp.runtime.*
import io.dcloud.uniapp.ui.component.IComponentData
import io.dcloud.uniapp.vue.*
import io.dcloud.uniapp.vue.shared.*
import io.dcloud.uts.*
import io.dcloud.uts.Map
import io.dcloud.uts.Set
import io.dcloud.uts.UTSAndroid
import io.dcloud.uts.component.*
import io.dcloud.uts.component.UTSComponent
import java.io.File
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.properties.Delegates
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
open class GeneralCallbackResult (
@JsonNotNull
open var errMsg: String,
) : UTSObject()
open class TakePhotoSuccessCallbackResult (
@JsonNotNull
open var tempImagePath: String,
@JsonNotNull
open var quality: String,
@JsonNotNull
open var errMsg: String,
) : UTSObject()
typealias TakePhotoFailCallback = (res: GeneralCallbackResult) -> Unit
typealias TakePhotoSuccessCallback = (result: TakePhotoSuccessCallbackResult) -> Unit
typealias TakePhotoCompleteCallback = (res: GeneralCallbackResult) -> Unit
open class TakePhotoOption (
open var complete: TakePhotoCompleteCallback? = null,
open var fail: TakePhotoFailCallback? = null,
open var quality: String? = null,
open var selfieMirror: Boolean? = null,
open var success: TakePhotoSuccessCallback? = null,
) : UTSObject()
open class SetZoomSuccessCallbackResult (
@JsonNotNull
open var zoom: Number,
@JsonNotNull
open var errMsg: String,
) : UTSObject()
typealias SetZoomCompleteCallback = (res: GeneralCallbackResult) -> Unit
typealias SetZoomFailCallback = (res: GeneralCallbackResult) -> Unit
typealias CameraContextSetZoomSuccessCallback = (result: SetZoomSuccessCallbackResult) -> Unit
open class CameraContextSetZoomOption (
@JsonNotNull
open var zoom: Number,
open var complete: SetZoomCompleteCallback? = null,
open var fail: SetZoomFailCallback? = null,
open var success: CameraContextSetZoomSuccessCallback? = null,
) : UTSObject()
open class StartRecordTimeoutCallbackResult (
@JsonNotNull
open var tempVideoPath: String,
) : UTSObject()
typealias StartRecordCompleteCallback = (res: GeneralCallbackResult) -> Unit
typealias StartRecordFailCallback = (res: GeneralCallbackResult) -> Unit
typealias StartRecordTimeoutCallback = (result: StartRecordTimeoutCallbackResult) -> Unit
typealias CameraContextStartRecordSuccessCallback = (res: GeneralCallbackResult) -> Unit
open class CameraContextStartRecordOption (
open var complete: StartRecordCompleteCallback? = null,
open var fail: StartRecordFailCallback? = null,
open var selfieMirror: Boolean? = null,
open var success: CameraContextStartRecordSuccessCallback? = null,
open var timeout: Number? = null,
open var timeoutCallback: StartRecordTimeoutCallback? = null,
) : UTSObject()
open class StopRecordSuccessCallbackResult (
@JsonNotNull
open var tempVideoPath: String,
@JsonNotNull
open var errMsg: String,
) : UTSObject()
typealias StopRecordCompleteCallback = (res: GeneralCallbackResult) -> Unit
typealias StopRecordFailCallback = (res: GeneralCallbackResult) -> Unit
typealias CameraContextStopRecordSuccessCallback = (result: StopRecordSuccessCallbackResult) -> Unit
open class CameraContextStopRecordOption (
open var complete: StopRecordCompleteCallback? = null,
open var compressed: Boolean? = null,
open var fail: StopRecordFailCallback? = null,
open var success: CameraContextStopRecordSuccessCallback? = null,
) : UTSObject()
typealias OnCameraFrameCallback = (result: OnCameraFrameCallbackResult) -> Unit
open class OnCameraFrameCallbackResult (
@JsonNotNull
open var data: Any,
@JsonNotNull
open var height: Number,
@JsonNotNull
open var width: Number,
) : UTSObject()
typealias StartSuccessCallback = (res: GeneralCallbackResult) -> Unit
typealias StartFailCallback = (res: GeneralCallbackResult) -> Unit
typealias StartCompleteCallback = (res: GeneralCallbackResult) -> Unit
open class CameraFrameListenerStartOption (
open var complete: StartCompleteCallback? = null,
open var fail: StartFailCallback? = null,
open var success: StartSuccessCallback? = null,
) : UTSObject()
typealias StopCompleteCallback = (res: GeneralCallbackResult) -> Unit
typealias StopFailCallback = (res: GeneralCallbackResult) -> Unit
typealias StopSuccessCallback = (res: GeneralCallbackResult) -> Unit
open class StopOption (
open var complete: StopCompleteCallback? = null,
open var fail: StopFailCallback? = null,
open var success: StopSuccessCallback? = null,
) : UTSObject()
typealias FlashMode = String
typealias DevicePosition = String
typealias Resolution = String
typealias FrameSize = String
typealias QualityType = String
open class CameraConfig (
open var flash: FlashMode? = null,
open var devicePosition: DevicePosition? = null,
open var resolution: Resolution? = null,
open var frameSize: FrameSize? = null,
) : UTSObject()
typealias SwitchCompleteCallback = (res: GeneralCallbackResult) -> Unit
typealias SwitchFailCallback = (res: GeneralCallbackResult) -> Unit
typealias SwitchSuccessCallback = (res: GeneralCallbackResult) -> Unit
open class SwitchOption (
@JsonNotNull
open var position: DevicePosition,
open var complete: SwitchCompleteCallback? = null,
open var fail: SwitchFailCallback? = null,
open var success: SwitchSuccessCallback? = null,
) : UTSObject()
open class OnCameraFrameListenerOption (
open var success: OnCameraFrameCallback? = null,
) : UTSObject()
typealias TakePhoto = (options: TakePhotoOption) -> Unit
typealias SetZoom = (options: CameraContextSetZoomOption) -> Unit
typealias StartRecord = (options: CameraContextStartRecordOption) -> Unit
typealias StopRecord = (options: CameraContextStopRecordOption) -> Unit
typealias StartCameraFrame = (options: CameraFrameListenerStartOption) -> Unit
typealias StopCameraFrame = (options: StopOption) -> Unit
typealias SwitchCamera = (options: SwitchOption) -> Unit
val FLASH_MODE_MAP = Map<String, Int>(_uA(
_uA(
"auto",
ImageCapture.FLASH_MODE_AUTO
),
_uA(
"on",
ImageCapture.FLASH_MODE_ON
),
_uA(
"torch",
ImageCapture.FLASH_MODE_ON
),
_uA(
"off",
ImageCapture.FLASH_MODE_OFF
)
))
val DEVICE_POSITION_MAP = Map<String, Int>(_uA(
_uA(
"back",
CameraSelector.LENS_FACING_BACK
),
_uA(
"front",
CameraSelector.LENS_FACING_FRONT
)
))
val RESOLUTION_MAP = Map<String, Quality>(_uA(
_uA(
"low",
Quality.LOWEST
),
_uA(
"medium",
Quality.HD
),
_uA(
"high",
Quality.HIGHEST
)
))
val QUALITY_MAP = Map<String, Int>(_uA(
_uA(
"high",
ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
),
_uA(
"low",
ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
)
))
val MIRROR_MODE = Map<Boolean, Int>(_uA(
_uA(
true,
MirrorMode.MIRROR_MODE_ON
),
_uA(
false,
MirrorMode.MIRROR_MODE_OFF
)
))
open class CameraView : FrameLayout {
private var previewView: PreviewView
open var cameraProvider: ProcessCameraProvider? = null
open var cameraControl: CameraControl? = null
private var imageCapture: ImageCapture? = null
private var videoCapture: VideoCapture<Recorder>? = null
private var recording: Recording? = null
private var comp: UTSComponent<CameraView>
private var flashMode: FlashMode = "auto"
private var devicePosition: DevicePosition = "back"
private var resolution: Resolution = "medium"
private var quality: QualityType = "normal"
private var videoFile: File? = null
open var maxZoom: Float = 1.toFloat()
open var minZoom: Float = 1.toFloat()
private var initialized: Boolean = false
private var isListening: Boolean = false
private var videoSelfieMirror: Boolean? = null
private var cameraContextStopRecordOption: CameraContextStopRecordOption? = null
private var onCameraFrameCallback: OnCameraFrameCallback? = null
private var cameraExecutor: ExecutorService? = null
private var onCameraFrameListenerOption: OnCameraFrameListenerOption? = null
constructor(context: Context, comp: UTSComponent<CameraView>, config: CameraConfig = CameraConfig()) : super(context) {
this.comp = comp
this.flashMode = config.flash ?: "auto"
this.devicePosition = config.devicePosition ?: "back"
this.resolution = config.resolution ?: "medium"
this.previewView = PreviewView(context)
var layoutParam = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
this.addView(this.previewView, layoutParam)
this.setupCamera()
}
open fun setupCamera() {
var cameraProviderFuture = ProcessCameraProvider.getInstance(UTSAndroid.getUniActivity()!!)
cameraProviderFuture.addListener(fun(){
try {
this.cameraProvider = cameraProviderFuture.get()
this.bindCamera()
}
catch (e: Throwable) {
var ret: Map<String, Any> = Map()
ret.set("errMsg", JSON.stringify(e))
this.comp.`$emit`("error", ret)
}
}
, ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!!))
}
open fun bindCamera() {
var targetResolution = RESOLUTION_MAP.get(this.resolution) ?: Quality.HD
var captureMode = QUALITY_MAP.get(this.quality) ?: ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
var preview = Preview.Builder().build()
preview.setSurfaceProvider(this.previewView.getSurfaceProvider())
var imageCapture = ImageCapture.Builder().setFlashMode(FLASH_MODE_MAP.get(this.flashMode)!!).setCaptureMode(captureMode).build()
var cameraSelector = CameraSelector.Builder().requireLensFacing(DEVICE_POSITION_MAP.get(this.devicePosition)!!).build()
var recorder = Recorder.Builder().setQualitySelector(QualitySelector.from(targetResolution))
var mirrorMode = if (this.videoSelfieMirror == null) {
MirrorMode.MIRROR_MODE_ON_FRONT_ONLY
} else {
MIRROR_MODE.get(this.videoSelfieMirror!!)
}
var videoCapture = VideoCapture.Builder(recorder.build()).setMirrorMode(mirrorMode!!).build()
this.videoCapture = videoCapture
this.imageCapture = imageCapture
this.cameraProvider!!.unbindAll()
var imageAnalysis = ImageAnalysis.Builder().setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build()
var viewPort = this.previewView.getViewPort()!!
var useCaseGroup = UseCaseGroup.Builder().addUseCase(preview).addUseCase(imageAnalysis).addUseCase(imageCapture).addUseCase(videoCapture).setViewPort(viewPort).build()
this.cameraExecutor = Executors.newSingleThreadExecutor()
var _this = this
open class Analyzer : ImageAnalysis.Analyzer {
constructor(){}
override fun analyze(image: ImageProxy) {
if (_this.isListening) {
var imageFormat = image.getFormat()
var width = image.width
var height = image.height
if (imageFormat == ImageFormat.YUV_420_888) {
_this.onCameraFrameCallback?.invoke(OnCameraFrameCallbackResult(width = width, height = height, data = image))
_this.onCameraFrameListenerOption?.success?.invoke(OnCameraFrameCallbackResult(width = width, height = height, data = image))
}
}
image.close()
}
override fun getDefaultTargetResolution(): Size {
return Size(640, 480)
}
}
imageAnalysis.setAnalyzer(this.cameraExecutor!!, Analyzer() as ImageAnalysis.Analyzer)
var camera = this.cameraProvider!!.bindToLifecycle(UTSAndroid.getUniActivity()!! as LifecycleOwner, cameraSelector, useCaseGroup)
this.cameraControl = camera.getCameraControl()
if (!this.initialized) {
this.initialized = true
var zoomState = camera.getCameraInfo().getZoomState().getValue()
this.maxZoom = zoomState?.getMaxZoomRatio() ?: 1.toFloat()
this.minZoom = zoomState?.getMinZoomRatio() ?: 1.toFloat()
var maxZoom = this.maxZoom
var ret: Map<String, Any> = Map()
ret.set("maxZoom", maxZoom)
this.comp.`$emit`("ready", ret)
}
}
open fun unbindCamera() {
this.cameraProvider?.unbindAll()
this.cameraExecutor?.shutdown()
}
open fun setConfig(config: CameraConfig = CameraConfig()) {
this.flashMode = config.flash ?: "auto"
this.devicePosition = config.devicePosition ?: "back"
this.resolution = config.resolution ?: "medium"
}
open fun setFlash(mode: FlashMode) {
this.flashMode = mode
if (FLASH_MODE_MAP.get(mode) == null || this.imageCapture == null) {
return
}
this.imageCapture!!.setFlashMode(FLASH_MODE_MAP.get(mode)!!)
}
open fun switchCamera(position: DevicePosition) {
this.devicePosition = position
if (DEVICE_POSITION_MAP.get(position) == null || this.cameraProvider == null) {
return
}
this.unbindCamera()
this.bindCamera()
}
open fun isResolutionSupported(context: Context, cameraSelector: CameraSelector, targetResolution: Size): Boolean {
return true
}
open fun takePhoto(option: TakePhotoOption) {
var quality = option.quality ?: "high"
this.quality = quality
if (quality == "low") {
this.unbindCamera()
this.bindCamera()
}
var privateDir = UTSAndroid.getAppCachePath()!!
val tempFile = File(privateDir)
if (!tempFile.exists()) {
tempFile.mkdirs()
}
val photoFile = File(privateDir, Date.now() + ".png")
var metadata = ImageCapture.Metadata()
metadata.setReversedHorizontal(option.selfieMirror ?: DEVICE_POSITION_MAP.get(this.devicePosition)!! == CameraSelector.LENS_FACING_FRONT)
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).setMetadata(metadata).build()
open class OnImageSavedCallback : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
option.success?.invoke(TakePhotoSuccessCallbackResult(tempImagePath = photoFile.getAbsolutePath(), quality = quality, errMsg = "ok"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "ok"))
}
override fun onError(err: ImageCaptureException) {
val result = GeneralCallbackResult(errMsg = err.toString())
option.fail?.invoke(result)
option.complete?.invoke(result)
}
override fun onCaptureStarted() {}
}
this.imageCapture!!.takePicture(outputOptions, ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!!), OnImageSavedCallback() as ImageCapture.OnImageSavedCallback)
}
open fun setZoom(option: CameraContextSetZoomOption) {
if (this.cameraControl != null) {
try {
this.cameraControl!!.setZoomRatio(option.zoom.toFloat())
option.success?.invoke(SetZoomSuccessCallbackResult(zoom = option.zoom, errMsg = "ok"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "ok"))
} catch (e: Throwable) {
val result = GeneralCallbackResult(errMsg = e.toString())
option.complete?.invoke(result)
option.fail?.invoke(result)
}
} else {
val result = GeneralCallbackResult(errMsg = "相机不存在")
option.complete?.invoke(result)
option.fail?.invoke(result)
}
}
open fun startRecord(option: CameraContextStartRecordOption) {
if (option.selfieMirror != null && this.videoSelfieMirror != option.selfieMirror) {
this.videoSelfieMirror = option.selfieMirror
this.unbindCamera()
this.bindCamera()
}
if (this.recording != null || this.videoCapture == null) {
option.fail?.invoke(GeneralCallbackResult(errMsg = "已经在录制或相机不存在"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "已经在录制或相机不存在"))
return
}
var privateDir = UTSAndroid.getAppCachePath()!!
this.videoFile = File(privateDir, Date.now() + "video.mp4")
var outputFileOptions = FileOutputOptions.Builder(this.videoFile!!).build()
this.recording = this.videoCapture!!.output.prepareRecording(UTSAndroid.getUniActivity()!!, outputFileOptions).withAudioEnabled().start(ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!!), fun(recordEvent: VideoRecordEvent){
if (recordEvent is VideoRecordEvent.Start) {
option.success?.invoke(GeneralCallbackResult(errMsg = "ok"))
if (option.timeout != null && option.timeout!! > 0) {
setTimeout(fun(){
this.recording?.stop()
}
, option.timeout!!)
}
} else if (recordEvent is VideoRecordEvent.Finalize) {
this.recording?.close()
this.recording = null
var tempVideoPath = this.videoFile?.getAbsolutePath()!!
this.cameraContextStopRecordOption?.success?.invoke(StopRecordSuccessCallbackResult(tempVideoPath = tempVideoPath, errMsg = "ok"))
option.timeoutCallback?.invoke(StartRecordTimeoutCallbackResult(tempVideoPath = tempVideoPath))
}
}
)
}
open fun stopRecord(option: CameraContextStopRecordOption) {
if (this.recording == null) {
option.fail?.invoke(GeneralCallbackResult(errMsg = "未开始录制"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未开始录制"))
return
}
this.cameraContextStopRecordOption = option
this.recording?.stop()
}
open fun onCameraFrame(callback: OnCameraFrameCallback? = null) {
this.onCameraFrameCallback = callback
}
open fun onCameraFrameListener(option: OnCameraFrameListenerOption) {
this.onCameraFrameListenerOption = option
}
open fun cameraFrameOnStart(option: CameraFrameListenerStartOption?) {
this.isListening = true
option?.success?.invoke(GeneralCallbackResult(errMsg = "ok"))
}
open fun cameraFrameOnStop(option: StopOption?) {
this.isListening = false
option?.success?.invoke(GeneralCallbackResult(errMsg = "ok"))
}
}
open class CameraManager {
private var cameraView: CameraView? = null
public open fun setCameraView(cameraView: CameraView?): Unit {
this.cameraView = cameraView!!
}
public open fun getCameraView(): CameraView? {
return this.cameraView
}
public open fun dispose(): Unit {
this.cameraView = null
}
companion object {
private var instance: CameraManager? = null
public fun getInstance(): CameraManager {
if (CameraManager.instance == null) {
CameraManager.instance = CameraManager()
}
return CameraManager.instance!!
}
}
}
open class XfCameraComponent : UTSComponent<CameraView> {
constructor(proxy: PageProxy, componentData: IComponentData) : super(proxy, componentData)
open var mode: String = "normal"
open var resolution: String = "medium"
open var position: String = "back"
open var flash: String = "auto"
open var frameSize: String = "medium"
override fun created() {}
override fun NVBeforeLoad() {}
override fun NVLoad(): CameraView {
var previewView = CameraView(this.`$androidContext`!!, this)
previewView.setTag("9527")
CameraManager.getInstance().setCameraView(previewView)
return previewView
}
override fun NVLoaded() {}
override fun NVLayouted() {
this.`$el`?.setConfig(CameraConfig(resolution = this.resolution, frameSize = this.frameSize, flash = this.flash))
this.`$el`?.switchCamera(this.position)
}
override fun NVBeforeUnload() {
var ret: Map<String, Any> = Map()
this.`$emit`("stop", ret)
this.`$el`?.unbindCamera()
}
override fun NVUnloaded() {
CameraManager.getInstance().dispose()
}
override fun unmounted() {}
override fun `$init`() {
this.`$watch`<String>("position", fun(newValue, _){
this.`$el`?.switchCamera(newValue)
}
)
this.`$watch`<String>("flash", fun(newValue, _){
this.`$el`?.setFlash(newValue)
}
)
}
companion object {
var name = "xf-camera"
init {
io.dcloud.uniapp.UniSDKEngine.registerUniComponent("xf-camera", XfCameraComponent::class.java, XfCameraElement::class.java)
}
}
}
open class XfCameraElement : DomNode {
constructor(data: INodeData, pageNode: PageNode) : super(data, pageNode)
}
open class CameraFrameListener {
open lateinit var context: CameraContext
constructor(context: CameraContext){
this.context = context
}
open fun start(): Unit {
this.start(null)
}
open fun start(option: CameraFrameListenerStartOption?) {
this.context.getCamera().then(fun(camera: CameraView){
camera.cameraFrameOnStart(option)
}
)
}
open fun stop(): Unit {
this.stop(null)
}
open fun stop(option: StopOption?) {
this.context.getCamera().then(fun(camera: CameraView){
camera.cameraFrameOnStop(option)
}
)
}
}
open class CameraContext {
private var mCameraFrameListener: CameraFrameListener? = null
constructor(){}
open fun getCamera(): UTSPromise<CameraView> {
var cameraPreview = CameraManager.getInstance().getCameraView()
if (cameraPreview != null) {
return UTSPromise.resolve<CameraView>(cameraPreview)
}
var resolveFunc: ((res: CameraView) -> Unit)? = null
var rejectFunc: ((res: String) -> Unit)? = null
var maxAttempts: Number = 5
var currentAttempt: Number = 0
fun attemptGetCamera() {
var camera = CameraManager.getInstance().getCameraView()
if (camera != null) {
resolveFunc?.invoke(camera)
} else if (currentAttempt < maxAttempts) {
currentAttempt++
setTimeout(fun(){
attemptGetCamera()
}, 100)
} else {
rejectFunc?.invoke("Camera not found after multiple attempts")
}
}
return UTSPromise<CameraView>(fun(resolve, reject){
resolveFunc = resolve
rejectFunc = reject
attemptGetCamera()
}
)
}
open fun takePhoto(option: TakePhotoOption) {
this.getCamera().then(fun(camera: CameraView){
camera.takePhoto(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun setZoom(option: CameraContextSetZoomOption) {
this.getCamera().then(fun(camera: CameraView){
camera.setZoom(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun startRecord(option: CameraContextStartRecordOption) {
this.getCamera().then(fun(camera: CameraView){
camera.startRecord(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun stopRecord(option: CameraContextStopRecordOption) {
this.getCamera().then(fun(camera: CameraView){
camera.stopRecord(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun onCameraFrame(): CameraFrameListener {
return this.onCameraFrame(null)
}
open fun onCameraFrame(callback: OnCameraFrameCallback? = null): CameraFrameListener {
if (this.mCameraFrameListener == null) {
this.mCameraFrameListener = CameraFrameListener(this)
}
this.getCamera().then(fun(camera: CameraView){
camera.onCameraFrame(callback)
}
)
return this.mCameraFrameListener!!
}
open fun onCameraFrameListener(option: OnCameraFrameListenerOption) {
this.getCamera().then(fun(camera: CameraView){
camera.onCameraFrameListener(option)
}
).`catch`(fun(){
console.log("未找到相机")
}
)
}
open fun cameraFrameOnStart(option: CameraFrameListenerStartOption) {
this.getCamera().then(fun(camera: CameraView){
camera.cameraFrameOnStart(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun cameraFrameOnStop(option: StopOption) {
this.getCamera().then(fun(camera: CameraView){
camera.cameraFrameOnStop(option)
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
open fun switchCamera(option: SwitchOption) {
this.getCamera().then(fun(camera: CameraView){
camera.switchCamera(option.position)
option.success?.invoke(GeneralCallbackResult(errMsg = "ok"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "ok"))
}
).`catch`(fun(){
option.fail?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
option.complete?.invoke(GeneralCallbackResult(errMsg = "未找到相机"))
}
)
}
}
var context: CameraContext = CameraContext()
fun createCameraContext(): CameraContext {
return context
}
val takePhoto: TakePhoto = fun(options: TakePhotoOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.takePhoto(options)
}
, null)
}
val setZoom: SetZoom = fun(options: CameraContextSetZoomOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.setZoom(options)
}
, null)
}
val startRecord: StartRecord = fun(options: CameraContextStartRecordOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.startRecord(options)
}
, null)
}
val stopRecord: StopRecord = fun(options: CameraContextStopRecordOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.stopRecord(options)
}
, null)
}
fun onCameraFrameListener(options: OnCameraFrameListenerOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.onCameraFrameListener(options)
}
, null)
}
val startCameraFrame: StartCameraFrame = fun(options: CameraFrameListenerStartOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.cameraFrameOnStart(options)
}
, null)
}
val stopCameraFrame: StopCameraFrame = fun(options: StopOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.cameraFrameOnStop(options)
}
, null)
}
val switchCamera: SwitchCamera = fun(options: SwitchOption) {
UTSAndroid.getDispatcher("main").async(fun(_) {
context.switchCamera(options)
}
, null)
}