Skip to content

使用方法

安卓UVC摄像头UTS原生插件集成了同一个组件可在一个页面多次加载不同摄像头,插件支持自定义摄像头排版,同时集成了录像、拍照、设置镜像、亮度调节,摄像头设备按钮监听等功能,拍照可自定义水印,插件支持uniapp和uniapp x,支持vue2和vue3的选项式和组合式

使用建议

在app启动的时候可以先调用API的清除缓存功能,因为插件中使用了持久性缓存,有可能在app异常退出的时候加载的摄像头在缓存中导致摄像头再次加载时失败

联系作者

关注微信公众号可联系作者

插件地址

权限

  • android.permission.CAMERA
  • android.hardware.camera
  • android.hardware.camera.autofocus
  • android.permission.WRITE_EXTERNAL_STORAGE
  • android.permission.READ_EXTERNAL_STORAGE
  • android.hardware.usb.host

API用法

在使用插件的地方引入以下代码:

js
import * as module from "@/uni_modules/leven-uts-uvc"
js
import * as module from "@/uni_modules/leven-uts-uvc"

组件用法

在使用插件的地方引入以下代码:

vue
<leven-uts-uvc ref="refLevenUvc" style="flex:1; height: 300px;" :configX="config" @onError="onError"
  @onEvent="onEvent" @onEventMethod="onEventMethod">
</leven-uts-uvc>

//组件的引用
const refLevenUvc = ref<LevenUtsUvcElement | null>(null)
vue
<leven-uts-uvc ref="refLevenUvcCamera" style="flex:1; height: 500px; margin-bottom: 20px;" :config="config"
@onError="onError" @onEvent="onEvent" @onEventMethod="onEventMethod"></leven-uts-uvc>

页面内容

API页面

vue
<template>
  <view>
    <button type="primary" @click="ApiClearCache">清除缓存</button>
    <button type="primary" @click="requestPermissions">申请插件所需权限</button>
    <button type="primary" @click="getDeviceList">获取摄像头列表</button>
    <!-- <button type="primary" @click="requestUsbPermission">获取摄像头权限</button> -->
    <button type="primary" @click="ApiUsbStatusListener">监听usb状态</button>
  </view>
</template>

<script setup>
  import * as module from "@/uni_modules/leven-uts-uvc"

  //监听usb状态
  function ApiUsbStatusListener() {
    module.usbStatusListener({
      success: (res : any) => {
        console.log(res)
      },
      fail: (res : any) => {
        console.log(res)
      },
      complete: (res : any) => {
        console.log(res)
      }
    })
  }

  // //获取摄像头权限
  // function requestUsbPermission() {
  //   module.requestUsbPermission(res => {
  //     console.log(res)
  //   })
  // }

  //获取摄像头列表
  function getDeviceList() {
    module.getDeviceList({
      success: (res : any) => {
        console.log(res)
      },
      fail: (res : any) => {
        console.log(res)
      },
      complete: (res : any) => {
        console.log(res)
      }
    })
  }

  //申请插件所需权限
  function requestPermissions() {
    module.requestPermissions({
      success: (res : any) => {
        console.log(res)
      },
      fail: (res : any) => {
        console.log(res)
      },
      complete: (res : any) => {
        console.log(res)
      }
    })
  }

  //清除缓存
  function ApiClearCache() {
    module.clearCache({
      success: (res : any) => {
        console.log(res)
      },
      fail: (res : any) => {
        console.log(res)
      },
      complete: (res : any) => {
        console.log(res)
      }
    })
  }
</script>

<style>

</style>
vue
<template>
  <view>
    <button type="primary" @click="clearCache">清除缓存</button>
    <button type="primary" @click="requestPermissions">申请插件所需权限</button>
    <button type="primary" @click="getDeviceList">获取摄像头列表</button>
    <button type="primary" @click="requestUsbPermission">获取摄像头权限</button>
    <button type="primary" @click="usbStatusListener">监听usb状态</button>
  </view>
</template>

<script>
  import * as module from "@/uni_modules/leven-uts-uvc"
  export default {
    data() {
      return {
        deviceName: ""
      }
    },
    methods: {
      requestUsbPermission() {
        // module.requestUsbPermission({
        //   deviceName: this.deviceName
        // }, res => {
        //   console.log(res);
        // })
      },
      getDeviceList() {
        // module.getDeviceList(res => {
        //   console.log(res)
        //   if (res && res.data) {
        //     let deviceList = res.data.deviceList;
        //     if (Array.isArray(deviceList) && deviceList.length > 0) {
        //       this.deviceName = deviceList[0].deviceName;
        //     }
        //   }
        // })
        module.getDeviceList({
          success: (res) => {
            console.log(res)
          },
          fail: (res) => {
            console.log(res)
          },
          complete: (res) => {
            console.log(res)
          }
        })
      },
      requestPermissions() {
        module.requestPermissions({
          success: (res) => {
            console.log(res)
          },
          fail: (res) => {
            console.log(res)
          },
          complete: (res) => {
            console.log(res)
          }
        })
      },
      clearCache() {
        module.clearCache({
          success: (res) => {
            console.log(res)
          },
          fail: (res) => {
            console.log(res)
          },
          complete: (res) => {
            console.log(res)
          }
        })
      },
      usbStatusListener() {
        module.usbStatusListener({
          success: (res) => {
            console.log(res)
          },
          fail: (res) => {
            console.log(res)
          },
          complete: (res) => {
            console.log(res)
          }
        })
      }
    }
  }
</script>

<style>

</style>

组件页面

vue
<template>
  <!-- #ifdef APP -->
  <scroll-view style="flex:1">
  <!-- #endif -->
    <view>
      <view style="width: 750rpx; height: 300px; position: relative;">
        <leven-uts-uvc ref="refLevenUvc" style="flex:1; height: 300px;" :configX="config" @onError="onError"
          @onEvent="onEvent" @onEventMethod="onEventMethod">
        </leven-uts-uvc>
      </view>
      <view>
        <button type="primary" @click="open">开启摄像头</button>
        <button type="primary" @click="close">关闭摄像头</button>
        <button type="primary" @click="startPreview">开启预览</button>
        <button type="primary" @click="stopPreview">关闭预览</button>
        <button type="primary" @click="startRecording">开始录像</button>
        <button type="primary" @click="stopRecording">结束录像</button>
        <button type="primary" @click="takePicture">拍照</button>
        <button type="primary" @click="getDeviceList">获取摄像头列表</button>
        <button type="primary" @click="switchCamera">切换摄像头</button>
        <button type="primary" @click="fullScreen">全屏</button>
        <button type="primary" @click="getBrightnessPercent">获取摄像头亮度百分比</button>
        <button type="primary" @click="setBrightnessPercent">设置摄像头亮度百分比</button>
        <button type="primary" @click="getContrastPercent">获取摄像头的对比度百分比</button>
        <button type="primary" @click="setContrastPercent">设置摄像头对比度百分比</button>
        <button type="primary" @click="setMirror">设置镜像</button>
        <button type="primary" @click="getPreviewSize">获取预览分辨率</button>
        <button type="primary" @click="getSupportedSizeList">获取支持的分辨率</button>
        <button type="primary" @click="setButtonCallback">监听按钮</button>
      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script lang="uts" setup>
  import JSONObject from 'com.alibaba.fastjson.JSONObject'
  //组件引用
  const refLevenUvc = ref<LevenUtsUvcElement | null>(null)
  //组件初始化配置
  const config : UTSJSONObject = {
    //视图的圆角值
    "radius": 10,
    //摄像头旋转角度
    "rotation": 90,
    //图片文件保存目录
    "pictureDir": "/storage/emulated/0/Pictures/LevenUvcCamera/",
    //视频保存目录
    "videoDir": "/storage/emulated/0/Movies/LevenUvcCamera/",
    //默认打开的摄像头deviceName,如果不是通过这个打开默认摄像头请不需要此参数
    // "deviceName": "/dev/bus/usb/003/003",
    //默认打开的摄像头产品名称
    // "productName": "RXGD-CAMERA",
    //默认分辨率
    // size: {
    //   width: 800,
    //   height: 600,
    //   fps: 30
    // }
  }

  //摄像头列表
  const deviceList = ref<JSONObject[] | null>(null)
  //当前摄像头索引
  const deviceIndex = ref<Number>(0)
  //镜像模式
  const mirror = ref<Number>(0)
  //**********************************方法*********************************
  //监听按钮
  function setButtonCallback() {
    refLevenUvc.value?.setButtonCallback()
  }
  //获取支持的分辨率
  function getSupportedSizeList() {
    refLevenUvc.value?.getSupportedSizeList()
  }
  //获取预览分辨率
  function getPreviewSize() {
    refLevenUvc.value?.getPreviewSize()
  }
  //设置镜像
  function setMirror() {
    mirror.value++;
    if (mirror.value > 4) {
      mirror.value = 0;
    }
    let options : UTSJSONObject = {
      //参数
      "mirror": mirror.value
    };
    let params : JSONObject = JSONObject.parse(JSON.stringify(options)) as JSONObject
    refLevenUvc.value?.setMirror(params)
  }
  //设置摄像头对比度百分比
  function setContrastPercent() {
    let options : UTSJSONObject = {
      //参数
      "percent": 30
    };
    let params : JSONObject = JSONObject.parse(JSON.stringify(options)) as JSONObject
    refLevenUvc.value?.setContrastPercent(params)
  }
  //获取摄像头的对比度百分比
  function getContrastPercent() {
    refLevenUvc.value?.getContrastPercent()
  }
  //设置摄像头亮度百分比
  function setBrightnessPercent() {
    let options : UTSJSONObject = {
      //参数
      "percent": 30
    };
    let params : JSONObject = JSONObject.parse(JSON.stringify(options)) as JSONObject
    refLevenUvc.value?.setBrightnessPercent(params)
  }
  //获取摄像头亮度百分比
  function getBrightnessPercent() {
    refLevenUvc.value?.getBrightnessPercent()
  }
  //全屏
  function fullScreen() {
    refLevenUvc.value?.fullScreen()
  }
  //切换摄像头
  function switchCamera() {
    if (deviceList.value == null || deviceList.value.length == 0) {
      uni.showToast({
        title: "请先获取摄像头列表",
        icon: "none"
      })
      return;
    }
    deviceIndex.value++;
    if (deviceIndex.value >= deviceList.value.length) {
      deviceIndex.value = 0;
    }
    let deviceName = deviceList.value[deviceIndex.value].getString("deviceName")
    let options : UTSJSONObject = {
      //参数
      "deviceName": deviceName
    };
    let params : JSONObject = JSONObject.parse(JSON.stringify(options)) as JSONObject
    refLevenUvc.value?.switchCamera(params)
  }
  //获取摄像头列表
  function getDeviceList() {
    refLevenUvc.value?.getDeviceList()
  }
  //拍照
  function takePicture() {
    //拍照参数
    let options : UTSJSONObject = {
      //是否返回base64数据,默认:false
      "base64": false,
      //水印
      "water": [{
        //水印内容
        "text": "这是一条测试水印",
        //文本颜色,默认:白色
        "color": "#FFFFFF",
        //文本大小,默认:20
        "textSize": 40,
        //文本样式,NORMAL:常规(默认),BOLD:加粗,ITALIC:斜体,BOLD_ITALIC:斜体加粗
        "typeFace": "NORMAL",
        //是否使用抗锯齿功能,默认:true
        "antiAlia": true,
        //透明度(0~255),默认:128
        "alpha": 128,
        //水印位置,0:左上角(默认),1.右上角,2.左下角,3.右下角
        "position": 2,
        //水印左边距,默认:40
        "leftMargin": 40,
        //水印右边距,默认:40
        "rightMargin": 40,
        //水印上边距,默认:40
        "topMargin": 40,
        //水印下边距,默认:40
        "bottomMargin": 40
      }]
    };
    let params : JSONObject = JSONObject.parse(JSON.stringify(options)) as JSONObject
    refLevenUvc.value?.takePicture(params);
  }
  //结束录像
  function stopRecording() {
    refLevenUvc.value?.stopRecording();
  }
  //开始录像
  function startRecording() {
    refLevenUvc.value?.startRecording();
  }
  //关闭预览
  function stopPreview() {
    refLevenUvc.value?.stopPreview();
  }
  //开启预览
  function startPreview() {
    refLevenUvc.value?.startPreview();
  }
  //关闭摄像头
  function close() {
    refLevenUvc.value?.close();
  }
  //开启摄像头
  function open() {
    refLevenUvc.value?.open();
  }
  //**********************************事件*********************************
  //其他事件回调
  function onEvent(e : JSONObject) {
    console.log("onEvent:" + e.toJSONString())
  }
  //方法事件回调
  function onEventMethod(e : JSONObject) {
    console.log("onEventMethod:" + e.toJSONString())
  }
  //错误事件
  function onError(e : JSONObject) {
    console.log("onError:" + e)
  }
</script>

<style>

</style>
vue
<template>
  <view>
    <leven-uts-uvc ref="refLevenUvcCamera" style="flex:1; height: 500px; margin-bottom: 20px;" :config="config"
      @onError="onError" @onEvent="onEvent" @onEventMethod="onEventMethod"></leven-uts-uvc>
    <view>
      <button type="primary" @click="open">开启摄像头</button>
      <button type="primary" @click="close">关闭摄像头</button>
      <button type="primary" @click="startPreview">开启预览</button>
      <button type="primary" @click="stopPreview">关闭预览</button>
      <button type="primary" @click="startRecording">开始录像</button>
      <button type="primary" @click="stopRecording">结束录像</button>
      <button type="primary" @click="takePicture">拍照</button>
      <button type="primary" @click="getDeviceList">获取摄像头列表</button>
      <button type="primary" @click="switchCamera">切换摄像头</button>
      <button type="primary" @click="fullScreen">全屏</button>
      <button type="primary" @click="getBrightnessPercent">获取摄像头亮度百分比</button>
      <button type="primary" @click="setBrightnessPercent">设置摄像头亮度百分比</button>
      <button type="primary" @click="getContrastPercent">获取摄像头的对比度百分比</button>
      <button type="primary" @click="setContrastPercent">设置摄像头对比度百分比</button>
      <button type="primary" @click="setMirror">设置镜像</button>
      <button type="primary" @click="getPreviewSize">获取预览分辨率</button>
      <button type="primary" @click="getSupportedSizeList">获取支持的分辨率</button>
      <button type="primary" @click="setButtonCallback">监听按钮</button>
    </view>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        config: {
          //视图的圆角值
          radius: 10,
          //摄像头旋转角度
          rotation: 90,
          //图片文件保存目录
          pictureDir: "/storage/emulated/0/Pictures/LevenUvcCamera/",
          //视频保存目录
          videoDir: "/storage/emulated/0/Movies/LevenUvcCamera/",
          //默认打开的摄像头deviceName,如果不是通过这个打开默认摄像头请留空
          // deviceName: "/dev/bus/usb/001/003",
          //默认打开的摄像头产品名称
          // productName: "RXGD-CAMERA",
          //默认分辨率
          // size: {
          //   width: 800,
          //   height: 600,
          //   fps: 30
          // }
        },
        //摄像头列表
        deviceList: [],
        //当前摄像头的索引
        deviceIndex: 0,
        //镜像模式
        mirror: 0
      }
    },
    methods: {
      //事件
      onEventMethod(e) {
        console.log(e)
      },
      onEvent(e) {
        console.log(e)
      },
      onError(e) {
        console.log(e)
      },
      //按钮点击事件
      setButtonCallback() {
        this.$refs.refLevenUvcCamera.setButtonCallback()
      },
      //获取支持的分辨率
      getSupportedSizeList() {
        this.$refs.refLevenUvcCamera.getSupportedSizeList()
      },
      //获取摄像头的对比度百分比
      getPreviewSize() {
        this.$refs.refLevenUvcCamera.getPreviewSize()
      },
      //设置镜像
      setMirror() {
        if (this.$refs.refLevenUvcCamera) {
          this.mirror++;
          if (this.mirror > 4) {
            this.mirror = 0;
          }
          this.$refs.refLevenUvcCamera.setMirror({
            //镜像,0.正常,1.垂直,2.水平,3.垂直+水平
            mirror: this.mirror
          })
        }
      },
      //设置摄像头对比度百分比
      setContrastPercent() {
        this.$refs.refLevenUvcCamera.setContrastPercent({
          percent: 30
        })
      },
      //获取摄像头的对比度百分比
      getContrastPercent() {
        this.$refs.refLevenUvcCamera.getContrastPercent()
      },
      //设置当前摄像头亮度百分比
      setBrightnessPercent() {
        this.$refs.refLevenUvcCamera.setBrightnessPercent({
          percent: 30
        })
      },
      //获取当前摄像头亮度百分比
      getBrightnessPercent() {
        this.$refs.refLevenUvcCamera.getBrightnessPercent()
      },
      //全屏
      fullScreen() {
        this.$refs.refLevenUvcCamera.fullScreen()
      },
      //切换摄像头
      switchCamera() {
        if (this.$refs.refLevenUvcCamera) {
          if (this.deviceList.length == 0) {
            this.showToast("请先获取摄像头列表")
            return;
          }
          if (this.deviceIndex >= this.deviceList.length) {
            this.deviceIndex = 0;
          } else {
            this.deviceIndex++;
          }
          this.$refs.refLevenUvcCamera.switchCamera({
            //摄像头名称
            deviceName: this.deviceList[this.deviceIndex].deviceName
          })
        }
      },
      //获取摄像头列表
      getDeviceList() {
        this.$refs.refLevenUvcCamera.getDeviceList()
      },
      //拍照
      takePicture() {
        if (this.$refs.refLevenUvcCamera) {
          this.$refs.refLevenUvcCamera.takePicture({
            //是否返回base64数据,默认:false
            base64: true,
            //水印列表,不传或为空不添加水印
            water: [{
              //水印内容
              text: "这是一条测试水印",
              //文本颜色,默认:白色
              color: "#FFFFFF",
              //文本大小,默认:20
              textSize: 40,
              //文本样式,NORMAL:常规(默认),BOLD:加粗,ITALIC:斜体,BOLD_ITALIC:斜体加粗
              typeFace: "NORMAL",
              //是否使用抗锯齿功能,默认:true
              antiAlia: true,
              //透明度(0~255),默认:128
              alpha: 128,
              //水印位置,0:左上角(默认),1.右上角,2.左下角,3.右下角
              position: 0,
              //水印左边距,默认:40
              leftMargin: 40,
              //水印右边距,默认:40
              rightMargin: 40,
              //水印上边距,默认:40
              topMargin: 40,
              //水印下边距,默认:40
              bottomMargin: 40
            }]
          })
        }
      },
      //结束录像
      stopRecording() {
        this.$refs.refLevenUvcCamera.stopRecording()
      },
      //开始录像
      startRecording() {
        this.$refs.refLevenUvcCamera.startRecording()
      },
      //关闭预览
      stopPreview() {
        this.$refs.refLevenUvcCamera.stopPreview()
      },
      //开启预览
      startPreview() {
        this.$refs.refLevenUvcCamera.startPreview()
      },
      //关闭摄像头
      close() {
        this.$refs.refLevenUvcCamera.close()
      },
      //开启摄像头
      open() {
        this.$refs.refLevenUvcCamera.open()
      },
      showToast(title) {
        uni.showToast({
          icon: "none",
          title: title
        })
      }
    }
  }
</script>

<style>

</style>