save code

This commit is contained in:
xsl
2026-03-11 17:27:11 +08:00
parent 8249992bd3
commit 437bc6c6b2
16 changed files with 891 additions and 0 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,20 @@
{
"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"
]
}
@@ -0,0 +1,152 @@
<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>
Binary file not shown.
@@ -0,0 +1,3 @@
{
"deploymentTarget": "11"
}
Binary file not shown.
@@ -0,0 +1,167 @@
<template>
<view>
</view>
</template>
<script lang="uts">
import { UIView } from "UIKit"
import { CameraView } from "./camera";
import { CameraConfig } from '../interface'
import { CameraManager } from "./CameraManager";
//原生提供以下属性或方法的实现
export default {
data() {
return {
};
},
/**
* 组件名称,也就是开发者使用的标签
*/
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
}
},
/**
* 属性变化监听器实现
*/
watch: {
"position": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : String, _oldValue : String) {
CameraManager.getInstance().getCameraView()?.switchCamera(newValue)
},
/**
* 创建时是否通过此方法更新属性,默认值为false
*/
immediate: false
},
"flash": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : String, _oldValue : String) {
CameraManager.getInstance().getCameraView()?.setFlash(newValue)
},
/**
* 创建时是否通过此方法更新属性,默认值为false
*/
immediate: false
}
},
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
expose: [],
methods: {
},
/**
* 组件被创建,组件第一个生命周期,
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
* [可选实现]
*/
created() {
},
/**
* 对应平台的view载体即将被创建,对应前端beforeMount
* [可选实现]
*/
NVBeforeLoad() {
},
/**
* 创建原生View,必须定义返回值类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* [必须实现]
*/
NVLoad() : UIView {
let previewView = new UIView()
previewView.tag = 9527
return previewView
},
/**
* 原生View已创建
* [可选实现]
*/
NVLoaded() {
},
/**
* 原生View布局完成
* [可选实现]
*/
NVLayouted() {
let previewView = this.$el as UIView;
let cameraView = new CameraView(previewView, this, {
resolution: this.resolution,
frameSize: this.frameSize,
devicePosition: this.position,
flash: this.flash
} as CameraConfig)
CameraManager.getInstance().setCameraView(cameraView);
},
/**
* 原生View将释放
* [可选实现]
*/
NVBeforeUnload() {
let ret : Map<string, any> = new Map();
let detail : Map<string, any> = new Map();
detail.set("detail", ret)
this.$emit("stop", detail);
CameraManager.getInstance().getCameraView()?.unbindCamera()
},
/**
* 原生View已释放,这里可以做释放View之后的操作
* [可选实现]
*/
NVUnloaded() {
CameraManager.getInstance().dispose()
},
/**
* 组件销毁
* [可选实现]
*/
unmounted() {
}
}
</script>
<style>
</style>
@@ -0,0 +1,214 @@
export type GeneralCallbackResult = {
/** 错误信息 */
errMsg : string
}
export type TakePhotoSuccessCallbackResult = {
/** 照片文件的临时路径 (本地路径),安卓是jpg图片格式,ios是png */
tempImagePath : string
quality : string
errMsg : string
}
/** 接口调用失败的回调函数 */
export type TakePhotoFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用成功的回调函数 */
export type TakePhotoSuccessCallback = (
result : TakePhotoSuccessCallbackResult
) => void
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type TakePhotoCompleteCallback = (res : GeneralCallbackResult) => void
export type TakePhotoOption = {
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: TakePhotoCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: TakePhotoFailCallback
/** 成像质量
*
* 可选值:
* - 'high': 高质量;
* - 'normal': 普通质量;
* - 'low': 低质量;
* - 'original': 原图; */
quality ?: 'high' | 'normal' | 'low' | 'original'
/**
* 是否开启镜像 */
selfieMirror ?: boolean
/** 接口调用成功的回调函数 */
success ?: TakePhotoSuccessCallback
}
export type SetZoomSuccessCallbackResult = {
/** 实际设置的缩放级别。由于系统限制,某些机型可能无法设置成指定值,会改用最接近的可设值。 */
zoom : number
errMsg : string
}
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type SetZoomCompleteCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
export type SetZoomFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用成功的回调函数 */
export type CameraContextSetZoomSuccessCallback = (
result : SetZoomSuccessCallbackResult
) => void
export type CameraContextSetZoomOption = {
/** 缩放级别,范围[1, maxZoom]。zoom 可取小数,精确到小数后一位。maxZoom 可在 bindinitdone 返回值中获取。 */
zoom : number
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: SetZoomCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: SetZoomFailCallback
/** 接口调用成功的回调函数 */
success ?: CameraContextSetZoomSuccessCallback
}
export type StartRecordTimeoutCallbackResult = {
/** 视频的文件的临时路径 (本地路径) */
tempVideoPath : string
}
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type StartRecordCompleteCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
export type StartRecordFailCallback = (res : GeneralCallbackResult) => void
/** 超过录制时长上限时会结束录像并触发此回调,录像异常退出时也会触发此回调 */
export type StartRecordTimeoutCallback = (
result : StartRecordTimeoutCallbackResult
) => void
/** 接口调用成功的回调函数 */
export type CameraContextStartRecordSuccessCallback = (
res : GeneralCallbackResult
) => void
export type CameraContextStartRecordOption = {
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: StartRecordCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: StartRecordFailCallback
/**
* 是否开启镜像 */
selfieMirror ?: boolean
/** 接口调用成功的回调函数 */
success ?: CameraContextStartRecordSuccessCallback
/**
* 录制时长上限,单位为秒,最长不能超过 5 分钟 */
timeout ?: number
/** 超过录制时长上限时会结束录像并触发此回调,录像异常退出时也会触发此回调 */
timeoutCallback ?: StartRecordTimeoutCallback
}
export type StopRecordSuccessCallbackResult = {
/** 视频的文件的临时路径 (本地路径) */
tempVideoPath : string
errMsg : string
}
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type StopRecordCompleteCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
export type StopRecordFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用成功的回调函数 */
export type CameraContextStopRecordSuccessCallback = (
result : StopRecordSuccessCallbackResult
) => void
export type CameraContextStopRecordOption = {
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: StopRecordCompleteCallback
/** 启动视频压缩,压缩效果同`chooseVideo` */
compressed ?: boolean
/** 接口调用失败的回调函数 */
fail ?: StopRecordFailCallback
/** 接口调用成功的回调函数 */
success ?: CameraContextStopRecordSuccessCallback
}
/** 回调函数 */
export type OnCameraFrameCallback = (result : OnCameraFrameCallbackResult) => void
export type OnCameraFrameCallbackResult = {
/** 图像像素点数据,一维数组,每四项表示一个像素点的 rgba */
data : any
/** 图像数据矩形的高度 */
height : number
/** 图像数据矩形的宽度 */
width : number
}
/** 接口调用成功的回调函数 */
export type StartSuccessCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
type StartFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
type StartCompleteCallback = (res : GeneralCallbackResult) => void
export type CameraFrameListenerStartOption = {
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: StartCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: StartFailCallback
/** 接口调用成功的回调函数 */
success ?: StartSuccessCallback
/** [Worker](https://developers.weixin.qq.com/miniprogram/dev/api/worker/Worker.html)
*
* 可选参数。如果需要在 iOS ExperimentalWorker 内监听摄像头帧数据,则需要传入对应 Worker 对象。详情 [Worker.getCameraFrameData](https://developers.weixin.qq.com/miniprogram/dev/api/worker/Worker.getCameraFrameData.html) */
// worker ?: Worker
}
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type StopCompleteCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
export type StopFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用成功的回调函数 */
export type StopSuccessCallback = (res : GeneralCallbackResult) => void
export type StopOption = {
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: StopCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: StopFailCallback
/** 接口调用成功的回调函数 */
success ?: StopSuccessCallback
}
export type FlashMode = 'auto' | 'on' | 'off' | 'torch'
export type DevicePosition = 'back' | 'front'
export type Resolution = 'low' | 'medium' | 'high'
export type FrameSize = 'medium' | 'small' | 'large'
export type QualityType = 'high' | 'normal' | 'low' | 'original'
export type CameraConfig = {
flash ?: FlashMode
devicePosition ?: DevicePosition
resolution ?: Resolution
frameSize ?: FrameSize
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type SwitchCompleteCallback = (res : GeneralCallbackResult) => void
/** 接口调用失败的回调函数 */
export type SwitchFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用成功的回调函数 */
export type SwitchSuccessCallback = (res : GeneralCallbackResult) => void
export type SwitchOption = {
position : DevicePosition
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
complete ?: SwitchCompleteCallback
/** 接口调用失败的回调函数 */
fail ?: SwitchFailCallback
/** 接口调用成功的回调函数 */
success ?: SwitchSuccessCallback
}
//////////////////////////////////////////////////////////////////////////////////////////////////
export type OnCameraFrameListenerOption = {
success ?: OnCameraFrameCallback
}
export type TakePhoto = (options : TakePhotoOption) => void
export type SetZoom = (options : CameraContextSetZoomOption) => void
export type StartRecord = (options : CameraContextStartRecordOption) => void
export type StopRecord = (options : CameraContextStopRecordOption) => void
export type OnCameraFrameListener = (options : OnCameraFrameListenerOption) => void
export type StartCameraFrame = (options : CameraFrameListenerStartOption) => void
export type StopCameraFrame = (options : StopOption) => void
export type SwitchCamera = (options : SwitchOption) => void