save code

This commit is contained in:
xsl
2026-03-12 13:33:51 +08:00
parent 7da266c2ff
commit 172924dd6b
19 changed files with 96 additions and 396 deletions
@@ -1,14 +0,0 @@
<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>
@@ -1,26 +0,0 @@
import { CameraView } from "./camera";
export class CameraManager {
private cameraView : CameraView | null = null;
private static instance : CameraManager | null = null;
public static getInstance() : CameraManager {
if (CameraManager.instance == null) {
CameraManager.instance = new CameraManager();
}
return CameraManager.instance!;
}
public setCameraView(cameraView ?: CameraView) : void {
this.cameraView = cameraView!
}
public getCameraView() : CameraView | null {
return this.cameraView;
}
public dispose() : void {
this.cameraView = null;
}
}
@@ -1,474 +0,0 @@
import ProcessCameraProvider from 'androidx.camera.lifecycle.ProcessCameraProvider'
import Preview from 'androidx.camera.core.Preview'
import MirrorMode from 'androidx.camera.core.MirrorMode'
import PreviewView from 'androidx.camera.view.PreviewView'
import Context from 'android.content.Context'
import FrameLayout from 'android.widget.FrameLayout'
import ViewGroup from 'android.view.ViewGroup'
import CameraSelector from 'androidx.camera.core.CameraSelector'
import ImageAnalysis from 'androidx.camera.core.ImageAnalysis'
import UseCaseGroup from 'androidx.camera.core.UseCaseGroup'
import ContextCompat from 'androidx.core.content.ContextCompat'
import LifecycleOwner from 'androidx.lifecycle.LifecycleOwner'
import ImageCapture from 'androidx.camera.core.ImageCapture'
import Size from 'android.util.Size'
import ImageCaptureException from 'androidx.camera.core.ImageCaptureException'
import File from 'java.io.File'
import ImageProxy from 'androidx.camera.core.ImageProxy';
import CameraControl from 'androidx.camera.core.CameraControl';
import VideoCapture from 'androidx.camera.video.VideoCapture'
import Recorder from 'androidx.camera.video.Recorder'
import Recording from 'androidx.camera.video.Recording'
import FileOutputOptions from 'androidx.camera.video.FileOutputOptions'
import Quality from 'androidx.camera.video.Quality'
import QualitySelector from 'androidx.camera.video.QualitySelector'
import VideoRecordEvent from 'androidx.camera.video.VideoRecordEvent'
// import Bitmap from 'android.graphics.Bitmap';
// import FileOutputStream from 'java.io.FileOutputStream';
// import MediaMetadataRetriever from 'android.media.MediaMetadataRetriever';
import ExecutorService from 'java.util.concurrent.ExecutorService'
import Executors from 'java.util.concurrent.Executors'
import ImageFormat from 'android.graphics.ImageFormat';
import {
TakePhotoOption,
GeneralCallbackResult,
TakePhotoSuccessCallbackResult,
CameraContextSetZoomOption,
SetZoomSuccessCallbackResult,
CameraContextStopRecordOption,
CameraContextStartRecordOption,
StartRecordTimeoutCallbackResult,
StopRecordSuccessCallbackResult,
OnCameraFrameCallback,
OnCameraFrameCallbackResult,
CameraFrameListenerStartOption,
StopOption,
CameraConfig,
FlashMode,
DevicePosition,
Resolution,
//FrameSize,
QualityType,
OnCameraFrameListenerOption
} from '../interface'
import Bitmap from "android.graphics.Bitmap";
import FileOutputStream from "java.io.FileOutputStream";
const FLASH_MODE_MAP = new Map<string, Int>([
['auto', ImageCapture.FLASH_MODE_AUTO],
['on', ImageCapture.FLASH_MODE_ON],
['torch', ImageCapture.FLASH_MODE_ON],
['off', ImageCapture.FLASH_MODE_OFF],
])
const DEVICE_POSITION_MAP = new Map<string, Int>([
['back', CameraSelector.LENS_FACING_BACK],
['front', CameraSelector.LENS_FACING_FRONT],
])
const RESOLUTION_MAP = new Map<string, Quality>([
['low', Quality.LOWEST],
['medium', Quality.HD],
['high', Quality.HIGHEST],
])
const QUALITY_MAP = new Map<string, Int>([
["high", ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY],
["low", ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY],
])
const MIRROR_MODE = new Map<boolean, Int>([
[true, MirrorMode.MIRROR_MODE_ON],
[false, MirrorMode.MIRROR_MODE_OFF],
])
export class CameraView extends FrameLayout {
private previewView : PreviewView;
public cameraProvider : ProcessCameraProvider | null = null;
public cameraControl : CameraControl | null = null;
private imageCapture : ImageCapture | null = null
private videoCapture : VideoCapture<Recorder> | null = null
private recording : Recording | null = null
private comp : UTSComponent<CameraView>;
private flashMode : FlashMode = 'auto'
private devicePosition : DevicePosition = 'back'
private resolution : Resolution = 'medium'
// private frameSize : FrameSize = 'medium'
private quality : QualityType = 'normal'
private videoFile : File | null = null
maxZoom : Float = (1).toFloat()
minZoom : Float = (1).toFloat()
private initialized : boolean = false
private isListening : boolean = false
private videoSelfieMirror : boolean | null = null
private cameraContextStopRecordOption : CameraContextStopRecordOption | null = null
private onCameraFrameCallback : OnCameraFrameCallback | null = null
private cameraExecutor : ExecutorService | null = null
private onCameraFrameListenerOption : OnCameraFrameListenerOption | null = null;
constructor(context : Context, comp : UTSComponent<CameraView>, config : CameraConfig = {} as CameraConfig) {
super(context);
this.comp = comp
this.flashMode = config.flash ?? 'auto'
this.devicePosition = config.devicePosition ?? 'back'
this.resolution = config.resolution ?? 'medium'
// this.frameSize = config.frameSize ?? 'medium'
this.previewView = new PreviewView(context);
let layoutParam = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
this.addView(this.previewView, layoutParam);
this.setupCamera()
}
setupCamera() {
// this.checkSelfPermission().then(() => {
let cameraProviderFuture = ProcessCameraProvider.getInstance(UTSAndroid.getUniActivity()!)
cameraProviderFuture.addListener(() => {
try {
this.cameraProvider = cameraProviderFuture.get()
this.bindCamera();
} catch (e) {
let ret : Map<string, any> = new Map();
ret.set("errMsg", JSON.stringify(e))
this.comp.$emit('error', ret)
}
}, ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!))
// }).catch((err) => {
// let ret : Map<string, any> = new Map();
// ret.set("errMsg", err ?? '权限不足')
// this.comp.$emit('error', ret)
// })
}
bindCamera() {
let targetResolution = RESOLUTION_MAP.get(this.resolution) ?? Quality.HD;
let captureMode = QUALITY_MAP.get(this.quality) ?? ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY;
// 创建一个Preview对象,用于显示相机预览
let preview = new Preview.Builder()
.build();
preview.setSurfaceProvider(this.previewView.getSurfaceProvider());
// 创建一个ImageCapture对象,用于拍照
let imageCapture = new ImageCapture.Builder()
.setFlashMode(FLASH_MODE_MAP.get(this.flashMode)!)
.setCaptureMode(captureMode)
.build();
// 选择要使用的相机(后置或前置)
let cameraSelector = new CameraSelector.Builder()
.requireLensFacing(DEVICE_POSITION_MAP.get(this.devicePosition)!)
.build();
let recorder = Recorder.Builder()
.setQualitySelector(QualitySelector.from(targetResolution))
let mirrorMode = this.videoSelfieMirror == null ? MirrorMode.MIRROR_MODE_ON_FRONT_ONLY : MIRROR_MODE.get(this.videoSelfieMirror!);
let videoCapture = new VideoCapture.Builder(recorder.build())
.setMirrorMode(mirrorMode!)
.build();
this.videoCapture = videoCapture
// 将参数应用到 VideoCapture
this.imageCapture = imageCapture;
this.cameraProvider!.unbindAll();
let imageAnalysis = ImageAnalysis.Builder()
// .setTargetResolution(new Size(1280, 720))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
let viewPort = this.previewView.getViewPort()!
let useCaseGroup = new UseCaseGroup.Builder()
.addUseCase(preview)
.addUseCase(imageAnalysis)
.addUseCase(imageCapture)
.addUseCase(videoCapture)
.setViewPort(viewPort)
.build();
this.cameraExecutor = Executors.newSingleThreadExecutor()
let _this = this
class Analyzer implements ImageAnalysis.Analyzer {
constructor() {
}
override analyze(image : ImageProxy) {
if (_this.isListening) {
let imageFormat = image.getFormat();
// 获取图像的宽度和高度
let width = image.width
let height = image.height
if (imageFormat == ImageFormat.YUV_420_888) {
_this.onCameraFrameCallback?.({
width,
height,
data: image
} as OnCameraFrameCallbackResult)
_this.onCameraFrameListenerOption?.success?.({
width,
height,
data: image
} as OnCameraFrameCallbackResult)
}
}
image.close();
}
override getDefaultTargetResolution() : Size {
// 返回默认的目标分辨率
return Size(640, 480)
}
}
imageAnalysis.setAnalyzer(this.cameraExecutor!, new Analyzer() as ImageAnalysis.Analyzer)
let camera = this.cameraProvider!.bindToLifecycle(
UTSAndroid.getUniActivity()! as LifecycleOwner,
cameraSelector,
useCaseGroup
// preview,
// imageCapture,
// videoCapture
);
this.cameraControl = camera.getCameraControl();
if (!this.initialized) {
this.initialized = true
let zoomState = camera.getCameraInfo().getZoomState().getValue();
this.maxZoom = zoomState?.getMaxZoomRatio() ?? (1).toFloat();
this.minZoom = zoomState?.getMinZoomRatio() ?? (1).toFloat();
let maxZoom = this.maxZoom
let ret : Map<string, any> = new Map();
ret.set("maxZoom", maxZoom)
this.comp.$emit('ready', ret)
}
}
unbindCamera() {
this.cameraProvider?.unbindAll()
this.cameraExecutor?.shutdown()
}
// checkSelfPermission() : Promise<boolean> {
// let permissionNeed = ["android.permission.CAMERA", "android.permission.RECORD_AUDIO", "android.permission.READ_EXTERNAL_STORAGE"]
// return new Promise((resoleve, _) => {
// resoleve(true);
// UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight : boolean, list : string[]) {
// if (allRight) {
// resoleve(true);
// } else {
// reject(list);
// }
// }, function (_ : boolean, grantedList : string[]) {
// //grantedList
// reject(grantedList);
// })
// })
// }
setConfig(config : CameraConfig = {} as CameraConfig) {
this.flashMode = config.flash ?? 'auto'
this.devicePosition = config.devicePosition ?? 'back'
this.resolution = config.resolution ?? 'medium'
// this.frameSize = config.frameSize ?? 'medium'
}
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)!)
}
switchCamera(position : DevicePosition) {
this.devicePosition = position
if (DEVICE_POSITION_MAP.get(position) == null || this.cameraProvider == null) return
this.unbindCamera()
this.bindCamera()
}
isResolutionSupported(context : Context, cameraSelector : CameraSelector, targetResolution : Size) : boolean {
return true
}
takePhoto(option : TakePhotoOption) {
let quality = option.quality ?? "high";
this.quality = quality;
if (quality == 'low') {
this.unbindCamera()
this.bindCamera()
}
// 设置输出目录
let privateDir = UTSAndroid.getAppCachePath()!;
const tempFile = new File(privateDir);
if (!tempFile.exists()) {
tempFile.mkdirs()
}
// 设置文件名
const photoFile = new File(privateDir, Date.now() + '.png');
// 处理镜像
let metadata = new ImageCapture.Metadata();
metadata.setReversedHorizontal(option.selfieMirror ?? DEVICE_POSITION_MAP.get(this.devicePosition)! == CameraSelector.LENS_FACING_FRONT);
const outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).setMetadata(metadata).build()
class OnImageSavedCallback implements ImageCapture.OnImageSavedCallback {
override onImageSaved(outputFileResults : ImageCapture.OutputFileResults) {
option.success?.({
tempImagePath: photoFile.getAbsolutePath(),
quality: quality,
errMsg: 'ok'
} as TakePhotoSuccessCallbackResult)
option.complete?.({
errMsg: 'ok'
} as GeneralCallbackResult)
}
override onError(err : ImageCaptureException) {
const result : GeneralCallbackResult = {
errMsg: err.toString()
}
option.fail?.(result)
option.complete?.(result)
}
override onCaptureStarted() {
}
}
this.imageCapture!.takePicture(outputOptions, ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!), new OnImageSavedCallback() as ImageCapture.OnImageSavedCallback)
}
setZoom(option : CameraContextSetZoomOption) {
if (this.cameraControl != null) {
try {
this.cameraControl!.setZoomRatio(option.zoom.toFloat())
option.success?.({
zoom: option.zoom,
errMsg: 'ok'
} as SetZoomSuccessCallbackResult)
option.complete?.({
errMsg: 'ok'
} as GeneralCallbackResult)
} catch (e) {
const result : GeneralCallbackResult = {
errMsg: e.toString()
}
option.complete?.(result)
option.fail?.(result)
}
} else {
const result : GeneralCallbackResult = {
errMsg: '相机不存在'
}
option.complete?.(result)
option.fail?.(result)
}
}
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?.({
errMsg: '已经在录制或相机不存在'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '已经在录制或相机不存在'
} as GeneralCallbackResult)
return
}
// 设置输出目录
let privateDir = UTSAndroid.getAppCachePath()!;
// 设置文件名
this.videoFile = new File(privateDir, Date.now() + 'video.mp4');
let outputFileOptions = new FileOutputOptions.Builder(this.videoFile!).build();
this.recording = this.videoCapture!.output
.prepareRecording(UTSAndroid.getUniActivity()!, outputFileOptions)
.withAudioEnabled()
// .apply(()=>{
// })
.start(ContextCompat.getMainExecutor(UTSAndroid.getUniActivity()!), (recordEvent : VideoRecordEvent) => {
if (recordEvent instanceof VideoRecordEvent.Start) {
option.success?.({
errMsg: 'ok'
} as GeneralCallbackResult)
if (option.timeout != null && option.timeout! > 0) {
setTimeout(() => {
this.recording?.stop()
}, option.timeout!)
}
} else if (recordEvent instanceof VideoRecordEvent.Finalize) {
this.recording?.close()
this.recording = null
let tempVideoPath = this.videoFile?.getAbsolutePath()!
//let tempThumbPath = extractThumbnail(tempVideoPath) ?? ''
this.cameraContextStopRecordOption?.success?.({
tempVideoPath,
errMsg: 'ok'
} as StopRecordSuccessCallbackResult)
option.timeoutCallback?.({
tempVideoPath,
} as StartRecordTimeoutCallbackResult)
}
})
}
stopRecord(option : CameraContextStopRecordOption) {
if (this.recording == null) {
option.fail?.({
errMsg: '未开始录制'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未开始录制'
} as GeneralCallbackResult)
return
}
this.cameraContextStopRecordOption = option
this.recording?.stop()
}
onCameraFrame(callback : OnCameraFrameCallback | null = null) {
this.onCameraFrameCallback = callback
}
onCameraFrameListener(option : OnCameraFrameListenerOption) {
this.onCameraFrameListenerOption = option
}
cameraFrameOnStart(option ?: CameraFrameListenerStartOption) {
this.isListening = true
option?.success?.({
errMsg: 'ok'
} as GeneralCallbackResult)
}
cameraFrameOnStop(option ?: StopOption) {
this.isListening = false
option?.success?.({
errMsg: 'ok'
} as GeneralCallbackResult)
}
}
// // 从视频文件中提取封面的函数
// function extractThumbnail(videoUri : string) : string | null {
// let retriever = new MediaMetadataRetriever()
// retriever.setDataSource(videoUri)
// // 提取视频的某一帧作为封面
// let thumbnail = retriever.frameAtTime
// // 保存封面到文件
// if (thumbnail != null) {
// let privateDir = UTSAndroid.getAppCachePath();
// const thumbnailFile = new File(privateDir, Date.now() + '_thumbnail.jpg');
// let outputStream = FileOutputStream(thumbnailFile)
// thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
// outputStream.close()
// return thumbnailFile.getAbsolutePath()
// }
// retriever.release()
// return null
// }
@@ -1,20 +0,0 @@
{
"minSdkVersion": "19",
"dependencies": [
// 使用camera2实现的CameraX核心库
// 定义camerax_version为"1.4.0-alpha04"
// 下面的行是可选的,因为core库通过camera-camera2间接包含
"androidx.camera:camera-core:1.4.0-alpha04"
"androidx.camera:camera-camera2:1.4.0-alpha04"
// 如果你想要额外使用CameraX生命周期库
"androidx.camera:camera-lifecycle:1.4.0-alpha04"
// 如果你想要额外使用CameraX视频捕获库
"androidx.camera:camera-video:1.4.0-alpha04"
// 如果你想要额外使用CameraX视图类
"androidx.camera:camera-view:1.4.0-alpha04"
// 如果你想要额外添加CameraX ML Kit Vision集成
// "androidx.camera:camera-mlkit-vision:1.4.0-alpha04"
// 如果你想要额外使用CameraX扩展库
// "androidx.camera:camera-extensions:1.4.0-alpha04"
]
}
@@ -1,252 +0,0 @@
import { CameraView } from './camera'
import {
TakePhotoOption,
GeneralCallbackResult,
CameraContextSetZoomOption,
CameraContextStartRecordOption,
CameraContextStopRecordOption,
// CameraFrameListener,
OnCameraFrameCallback,
// OnCameraFrameCallbackResult,
CameraFrameListenerStartOption,
StopOption,
TakePhoto,
SetZoom,
StartRecord,
StopRecord,
StartCameraFrame,
StopCameraFrame,
OnCameraFrameListenerOption,
SwitchOption,
SwitchCamera
} from '../interface'
import { CameraManager } from "./CameraManager";
class CameraFrameListener {
context : CameraContext
constructor(context : CameraContext) {
this.context = context
}
start() : void
start(option ?: CameraFrameListenerStartOption) {
this.context.getCamera().then((camera : CameraView) => {
camera.cameraFrameOnStart(option)
})
}
stop() : void
stop(option ?: StopOption) {
this.context.getCamera().then((camera : CameraView) => {
camera.cameraFrameOnStop(option)
})
}
}
class CameraContext {
private mCameraFrameListener : CameraFrameListener | null = null
constructor() {
}
getCamera() : Promise<CameraView> {
let cameraPreview = CameraManager.getInstance().getCameraView()
if (cameraPreview != null) {
return Promise.resolve<CameraView>(cameraPreview);
}
let resolveFunc : ((res : CameraView) => void) | null = null
let rejectFunc : ((res : string) => void) | null = null
let maxAttempts : number = 5
let currentAttempt : number = 0
function attemptGetCamera() {
let camera = CameraManager.getInstance().getCameraView()
if (camera !== null) {
resolveFunc?.(camera)
} else if (currentAttempt < maxAttempts) {
currentAttempt++
setTimeout(() => {
attemptGetCamera()
}, 100)
} else {
rejectFunc?.('Camera not found after multiple attempts')
}
}
return new Promise<CameraView>((resolve, reject) => {
resolveFunc = resolve
rejectFunc = reject
attemptGetCamera()
})
}
takePhoto(option : TakePhotoOption) {
this.getCamera().then((camera : CameraView) => {
camera.takePhoto(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
setZoom(option : CameraContextSetZoomOption) {
this.getCamera().then((camera : CameraView) => {
camera.setZoom(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
startRecord(option : CameraContextStartRecordOption) {
this.getCamera().then((camera : CameraView) => {
camera.startRecord(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
stopRecord(option : CameraContextStopRecordOption) {
this.getCamera().then((camera : CameraView) => {
camera.stopRecord(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
onCameraFrame() : CameraFrameListener
onCameraFrame(callback : OnCameraFrameCallback | null = null) : CameraFrameListener {
if (this.mCameraFrameListener == null) {
this.mCameraFrameListener = new CameraFrameListener(this)
}
this.getCamera().then((camera : CameraView) => {
camera.onCameraFrame(callback)
})
return this.mCameraFrameListener!
}
//////////////////////////////////////////////////////
onCameraFrameListener(option : OnCameraFrameListenerOption) {
this.getCamera().then((camera : CameraView) => {
camera.onCameraFrameListener(option)
}).catch(() => {
console.log("未找到相机")
})
}
cameraFrameOnStart(option : CameraFrameListenerStartOption) {
this.getCamera().then((camera : CameraView) => {
camera.cameraFrameOnStart(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
cameraFrameOnStop(option : StopOption) {
this.getCamera().then((camera : CameraView) => {
camera.cameraFrameOnStop(option)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
switchCamera(option : SwitchOption) {
this.getCamera().then((camera : CameraView) => {
camera.switchCamera(option.position)
option.success?.({
errMsg: 'ok'
} as GeneralCallbackResult)
option.complete?.({
errMsg: 'ok'
} as GeneralCallbackResult)
}).catch(() => {
option.fail?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
option.complete?.({
errMsg: '未找到相机'
} as GeneralCallbackResult)
})
}
}
let context : CameraContext = new CameraContext();
export function createCameraContext() : CameraContext {
return context;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
export const takePhoto : TakePhoto = function (options : TakePhotoOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.takePhoto(options)
}, null)
}
export const setZoom : SetZoom = function (options : CameraContextSetZoomOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.setZoom(options)
}, null)
}
export const startRecord : StartRecord = function (options : CameraContextStartRecordOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.startRecord(options)
}, null)
}
export const stopRecord : StopRecord = function (options : CameraContextStopRecordOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.stopRecord(options)
}, null)
}
@UTSJS.keepAlive
export function onCameraFrameListener(options : OnCameraFrameListenerOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.onCameraFrameListener(options)
}, null)
}
export const startCameraFrame : StartCameraFrame = function (options : CameraFrameListenerStartOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.cameraFrameOnStart(options)
}, null)
}
export const stopCameraFrame : StopCameraFrame = function (options : StopOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.cameraFrameOnStop(options)
}, null)
}
export const switchCamera : SwitchCamera = function (options : SwitchOption) {
UTSAndroid.getDispatcher("main").async(function (_) {
context.switchCamera(options)
}, null)
}
@@ -1,152 +0,0 @@
<template>
<view>
</view>
</template>
<script lang="uts">
import { CameraView } from './camera';
import { CameraConfig } from '../interface'
import { CameraManager } from './CameraManager';
//原生提供以下属性或方法的实现
export default {
/**
* 组件名称,也就是开发者使用的标签
*/
name: "xf-camera",
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
emits: ['stop', 'error', 'ready'],
/**
* 属性声明,组件的使用者会传递这些属性值到组件
*/
props: {
"mode": {
type: String,
default: "normal"
},
"resolution": {
type: String,
default: "medium" // low | high
},
"position": {
type: String,
default: "back" // front前置 |back 后置
},
"flash": {
type: String,
default: "auto" // auto, on, off, torch
},
"frameSize": {
type: String,
default: "medium" // small|large
}
},
/**
* 组件内部变量声明
*/
data() {
return {}
},
/**
* 属性变化监听器实现
*/
watch: {
"position": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : string, _ : string) {
this.$el?.switchCamera(newValue)
},
immediate: false // 创建时是否通过此方法更新属性,默认值为false
},
"flash": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : string, _ : string) {
this.$el?.setFlash(newValue)
},
immediate: false // 创建时是否通过此方法更新属性,默认值为false
}
},
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
expose: [],
methods: {
},
/**
* [可选实现] 组件被创建,组件第一个生命周期,
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
*/
created() {
},
/**
* [可选实现] 对应平台的view载体即将被创建,对应前端beforeMount
*/
NVBeforeLoad() {
},
/**
* [必须实现] 创建原生View,必须定义返回值类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* Android需要明确知道View类型,需特殊校验)
*/
NVLoad() : CameraView {
let previewView = new CameraView(this.$androidContext!, this)
previewView.setTag("9527");
CameraManager.getInstance().setCameraView(previewView);
return previewView
},
/**
* [可选实现] 原生View已创建
*/
NVLoaded() {
},
/**
* [可选实现] 原生View布局完成
*/
NVLayouted() {
this.$el?.setConfig({
resolution: this.resolution,
frameSize: this.frameSize,
flash: this.flash
} as CameraConfig)
this.$el?.switchCamera(this.position)
},
/**
* [可选实现] 原生View将释放
*/
NVBeforeUnload() {
let ret : Map<string, any> = new Map();
this.$emit('stop', ret)
this.$el?.unbindCamera()
},
/**
* [可选实现] 原生View已释放,这里可以做释放View之后的操作
*/
NVUnloaded() {
CameraManager.getInstance().dispose();
},
/**
* [可选实现] 组件销毁
*/
unmounted() {
},
}
</script>
<style>
</style>