Android相机调用-libusbCamera【外接摄像头】【USB摄像头】 【多摄像头预览】

        有的自定义系统,对于自己外接的USB摄像头,android原生的camera和camera2都无法打开,CameraX也用不了。这时候就要用libusbCamera,这个库可以打开摄像头,还可以多摄像头同时预览。本文主要是同时打开3个USB摄像头的项目记录,详细的接口介绍请参见原博客。

        特别感谢(原博客):UVCAndroid,安卓UVC相机通用开发库(支持多预览和多摄像头)_android com.herohan.uvcapp-CSDN博客

0,测试效果:

1,new一个project
2,增加依赖
implementation 'com.herohan:UVCAndroid:1.0.5'
implementation 'com.github.getActivity:XXPermissions:13.5'

3,增加配置
android.enableJetifier = true

4,增加仓库
maven { url 'https://jitpack.io' }

5,存储权限(这个我觉得不是必须的)
android:requestLegacyExternalStorage="true"

6,布局源码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:orientation="vertical"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:orientation="vertical"><TextViewandroid:id="@+id/textViewLeft"android:text="左相机"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/><com.serenegiant.widget.AspectRatioSurfaceViewandroid:id="@+id/svCameraViewLeft"android:layout_gravity="center"android:layout_width="440dp"android:layout_height="220dp"/></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginLeft="10dp"android:orientation="vertical"><TextViewandroid:id="@+id/textViewRight"android:text="右相机"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/><com.serenegiant.widget.AspectRatioSurfaceViewandroid:id="@+id/svCameraViewRight"android:layout_gravity="center"android:layout_width="440dp"android:layout_height="220dp"/></LinearLayout></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="5dp"android:orientation="vertical"><TextViewandroid:id="@+id/textViewCenter"android:text="中间相机"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/><com.serenegiant.widget.AspectRatioSurfaceViewandroid:id="@+id/svCameraViewCenter"android:layout_gravity="center"android:layout_width="440dp"android:layout_height="220dp"/></LinearLayout></LinearLayout></androidx.coordinatorlayout.widget.CoordinatorLayout>
7,页面源码
package com.qz.camera;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;import android.Manifest;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.herohan.uvcapp.CameraHelper;
import com.herohan.uvcapp.ICameraHelper;
import com.hjq.permissions.XXPermissions;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.UVCCamera;
import com.serenegiant.usb.UVCParam;
import com.serenegiant.widget.AspectRatioSurfaceView;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;public class MainActivity extends AppCompatActivity {private static final boolean DEBUG = true;private static final String TAG = MainActivity.class.getSimpleName();private static final int DEFAULT_WIDTH = 640;private static final int DEFAULT_HEIGHT = 480;private TextView mCameraNameLeft,mCameraNameRight, mCameraNameCenter;private UsbDevice mUsbDeviceLeft,mUsbDeviceRight, mUsbDeviceCenter;private ICameraHelper mCameraHelperLeft, mCameraHelperRight, mCameraHelperCenter;private AspectRatioSurfaceView svCameraViewLeft, svCameraViewRight, svCameraViewCenter;private ConcurrentLinkedQueue<UsbDevice> mReadyUsbDeviceList = new ConcurrentLinkedQueue<>();private ConditionVariable mReadyDeviceConditionVariable = new ConditionVariable();private final Object mSync = new Object();private HandlerThread mHandlerThread;private Handler mAsyncHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//setTitle(R.string.entry_multi_camera_new);if (DEBUG) Log.d(TAG, "huahua--onCreate:");mCameraNameLeft = findViewById(R.id.textViewLeft);mCameraNameRight = findViewById(R.id.textViewRight);mCameraNameCenter = findViewById(R.id.textViewCenter);List<String> needPermissions = new ArrayList<>();needPermissions.add(Manifest.permission.CAMERA);XXPermissions.with(this).permission(needPermissions).request((permissions, all) -> {if (!all) {return;}initViews();mHandlerThread = new HandlerThread(TAG);mHandlerThread.start();mAsyncHandler = new Handler(mHandlerThread.getLooper());initCameraHelper();});}@Overrideprotected void onDestroy() {super.onDestroy();mHandlerThread.quitSafely();mAsyncHandler.removeCallbacksAndMessages(null);}private void initViews() {setCameraViewLeft();setCameraViewRight();setCameraViewCenter();}private void setCameraViewLeft() {svCameraViewLeft = findViewById(R.id.svCameraViewLeft);svCameraViewLeft.setAspectRatio(DEFAULT_WIDTH, DEFAULT_HEIGHT);svCameraViewLeft.getHolder().addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(@NonNull SurfaceHolder holder) {if (mCameraHelperLeft != null) {mCameraHelperLeft.addSurface(holder.getSurface(), false);}}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder holder) {if (mCameraHelperLeft != null) {mCameraHelperLeft.removeSurface(holder.getSurface());}}});}private void setCameraViewRight() {svCameraViewRight = findViewById(R.id.svCameraViewRight);svCameraViewRight.setAspectRatio(DEFAULT_WIDTH, DEFAULT_HEIGHT);svCameraViewRight.getHolder().addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(@NonNull SurfaceHolder holder) {if (mCameraHelperRight != null) {mCameraHelperRight.addSurface(holder.getSurface(), false);}}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder holder) {if (mCameraHelperRight != null) {mCameraHelperRight.removeSurface(holder.getSurface());}}});}private void setCameraViewCenter() {svCameraViewCenter = findViewById(R.id.svCameraViewCenter);svCameraViewCenter.setAspectRatio(DEFAULT_WIDTH, DEFAULT_HEIGHT);svCameraViewCenter.getHolder().addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(@NonNull SurfaceHolder holder) {if (mCameraHelperCenter != null) {mCameraHelperCenter.addSurface(holder.getSurface(), false);}}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder holder) {if (mCameraHelperCenter != null) {mCameraHelperCenter.removeSurface(holder.getSurface());}}});}@Overrideprotected void onStart() {if (DEBUG) Log.d(TAG, "huahua--onStart:");super.onStart();}@Overrideprotected void onStop() {if (DEBUG) Log.d(TAG, "onStop:");super.onStop();clearCameraHelper();}public void initCameraHelper() {if (DEBUG) Log.d(TAG, "initCameraHelper:");if (mCameraHelperLeft == null) {mCameraHelperLeft = new CameraHelper();mCameraHelperLeft.setStateCallback(mStateListenerLeft);}if (mCameraHelperRight == null) {mCameraHelperRight = new CameraHelper();mCameraHelperRight.setStateCallback(mStateListenerRight);}if (mCameraHelperCenter == null) {mCameraHelperCenter = new CameraHelper();mCameraHelperCenter.setStateCallback(mStateListenerCenter);}}private void clearCameraHelper() {if (DEBUG) Log.d(TAG, "clearCameraHelper:");if (mCameraHelperLeft != null) {mCameraHelperLeft.release();mCameraHelperLeft = null;}if (mCameraHelperRight != null) {mCameraHelperRight.release();mCameraHelperRight = null;}if (mCameraHelperCenter != null) {mCameraHelperCenter.release();mCameraHelperCenter = null;}}private void selectDeviceLeft(final UsbDevice device) {if (DEBUG) Log.v(TAG, "selectDeviceLeft:device=" + device.getDeviceName());mUsbDeviceLeft = device;mAsyncHandler.post(() -> {waitCanSelectDevice(device);if (mCameraHelperLeft != null) {mCameraHelperLeft.selectDevice(device);}});}private void selectDeviceRight(final UsbDevice device) {if (DEBUG) Log.v(TAG, "selectDeviceRight:device=" + device.getDeviceName());mUsbDeviceRight = device;mAsyncHandler.post(() -> {waitCanSelectDevice(device);if (mCameraHelperRight != null) {mCameraHelperRight.selectDevice(device);}});}private void selectDeviceCenter(final UsbDevice device) {if (DEBUG) Log.v(TAG, "selectDeviceCenter:device=" + device.getDeviceName());mUsbDeviceCenter = device;mAsyncHandler.post(() -> {waitCanSelectDevice(device);if (mCameraHelperCenter != null) {mCameraHelperCenter.selectDevice(device);}});}/*** wait for only one camera need request permission** @param device*/private void waitCanSelectDevice(UsbDevice device) {mReadyUsbDeviceList.add(device);while (mReadyUsbDeviceList.size() > 1) {mReadyDeviceConditionVariable.block();mReadyDeviceConditionVariable.close();}}/*** remove ready camera that wait  for select** @param device*/private void removeSelectedDevice(UsbDevice device) {mReadyUsbDeviceList.remove(device);mReadyDeviceConditionVariable.open();}private final ICameraHelper.StateCallback mStateListenerLeft = new ICameraHelper.StateCallback() {private final String LOG_PREFIX = "ListenerLeft#";@Overridepublic void onAttach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onAttach:");synchronized (mSync) {if (mUsbDeviceLeft == null && !device.equals(mUsbDeviceRight) && !device.equals(mUsbDeviceCenter)) {selectDeviceLeft(device);mCameraNameLeft.setText("左相机("+device.getDeviceName()+")");}}}@Overridepublic void onDeviceOpen(UsbDevice device, boolean isFirstOpen) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceOpen:");if (mCameraHelperLeft != null && device.equals(mUsbDeviceLeft)) {UVCParam param = new UVCParam();param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH);mCameraHelperLeft.openCamera(param);}removeSelectedDevice(device);}@Overridepublic void onCameraOpen(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraOpen:");if (mCameraHelperLeft != null && device.equals(mUsbDeviceLeft)) {mCameraHelperLeft.startPreview();Size size = mCameraHelperLeft.getPreviewSize();if (size != null) {int width = size.width;int height = size.height;//auto aspect ratiosvCameraViewLeft.setAspectRatio(width, height);}mCameraHelperLeft.addSurface(svCameraViewLeft.getHolder().getSurface(), false);}}@Overridepublic void onCameraClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraClose:");if (device.equals(mUsbDeviceLeft)) {if (mCameraHelperLeft != null) {mCameraHelperLeft.removeSurface(svCameraViewLeft.getHolder().getSurface());}}}@Overridepublic void onDeviceClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceClose:");}@Overridepublic void onDetach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDetach:");if (device.equals(mUsbDeviceLeft)) {mUsbDeviceLeft = null;}removeSelectedDevice(device);}@Overridepublic void onCancel(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCancel:");if (device.equals(mUsbDeviceLeft)) {mUsbDeviceLeft = null;}removeSelectedDevice(device);}};private final ICameraHelper.StateCallback mStateListenerRight = new ICameraHelper.StateCallback() {private final String LOG_PREFIX = "ListenerRight#";@Overridepublic void onAttach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onAttach:");synchronized (mSync) {if (mUsbDeviceRight == null && !device.equals(mUsbDeviceLeft) && !device.equals(mUsbDeviceCenter)) {selectDeviceRight(device);mCameraNameRight.setText("右相机("+device.getDeviceName()+")");}}}@Overridepublic void onDeviceOpen(UsbDevice device, boolean isFirstOpen) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceOpen:");if (mCameraHelperRight != null && device.equals(mUsbDeviceRight)) {UVCParam param = new UVCParam();param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH);mCameraHelperRight.openCamera(param);}removeSelectedDevice(device);}@Overridepublic void onCameraOpen(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraOpen:");if (mCameraHelperRight != null && device.equals(mUsbDeviceRight)) {mCameraHelperRight.startPreview();Size size = mCameraHelperRight.getPreviewSize();if (size != null) {int width = size.width;int height = size.height;//auto aspect ratiosvCameraViewRight.setAspectRatio(width, height);}mCameraHelperRight.addSurface(svCameraViewRight.getHolder().getSurface(), false);}}@Overridepublic void onCameraClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraClose:");if (device.equals(mUsbDeviceRight)) {if (mCameraHelperRight != null) {mCameraHelperRight.removeSurface(svCameraViewRight.getHolder().getSurface());}}}@Overridepublic void onDeviceClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceClose:");}@Overridepublic void onDetach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDetach:");if (device.equals(mUsbDeviceRight)) {mUsbDeviceRight = null;}removeSelectedDevice(device);}@Overridepublic void onCancel(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCancel:");if (device.equals(mUsbDeviceRight)) {mUsbDeviceRight = null;}removeSelectedDevice(device);}};private final ICameraHelper.StateCallback mStateListenerCenter = new ICameraHelper.StateCallback() {private final String LOG_PREFIX = "ListenerCenter#";@Overridepublic void onAttach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onAttach:");synchronized (mSync) {if (mUsbDeviceCenter == null && !device.equals(mUsbDeviceRight) && !device.equals(mUsbDeviceLeft)) {selectDeviceCenter(device);mCameraNameCenter.setText("中间相机("+device.getDeviceName()+")");}}}@Overridepublic void onDeviceOpen(UsbDevice device, boolean isFirstOpen) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceOpen:");if (mCameraHelperCenter != null && device.equals(mUsbDeviceCenter)) {UVCParam param = new UVCParam();param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH);mCameraHelperCenter.openCamera(param);}removeSelectedDevice(device);}@Overridepublic void onCameraOpen(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraOpen:");if (mCameraHelperCenter != null && device.equals(mUsbDeviceCenter)) {mCameraHelperCenter.startPreview();Size size = mCameraHelperCenter.getPreviewSize();if (size != null) {int width = size.width;int height = size.height;//auto aspect ratiosvCameraViewCenter.setAspectRatio(width, height);}mCameraHelperCenter.addSurface(svCameraViewCenter.getHolder().getSurface(), false);}}@Overridepublic void onCameraClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCameraClose:");if (device.equals(mUsbDeviceCenter)) {if (mCameraHelperCenter != null) {mCameraHelperCenter.removeSurface(svCameraViewCenter.getHolder().getSurface());}}}@Overridepublic void onDeviceClose(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDeviceClose:");}@Overridepublic void onDetach(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onDetach:");if (device.equals(mUsbDeviceCenter)) {mUsbDeviceCenter = null;}removeSelectedDevice(device);}@Overridepublic void onCancel(UsbDevice device) {if (DEBUG) Log.v(TAG, LOG_PREFIX + "onCancel:");if (device.equals(mUsbDeviceCenter)) {mUsbDeviceCenter = null;}removeSelectedDevice(device);}};}

对于较为标准的android系统调用,可以使用更加简洁的CameraX调用,博文链接:

Android相机调用-CameraX【外接摄像头】【USB摄像头】_安卓调取摄像头设备的方式-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/487365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习笔记2024/2/23

今日内容 多态 包 final 权限修饰符 代码块 教学目标 能够说出使用多态的前提条件理解多态的向上转型理解多态的向下转型能够知道多态的使用场景包的作用public和private权限修饰符的作用描述final修饰的类的特点描述final修饰的方法的特点描述final修饰的变量的特点 第…

使用 Visual Studio 断点调试 DLL

继上文说到使用 IDA 和 WinDbg 调试无 dmp 文件 那么在有源码的情况下可以直接断点调试 DLL&#xff0c;目的是查看 DLL 内部的函数调用 场景&#xff1a; 程序执行到某个 DLL 时突然崩溃&#xff0c;先确定 Debug 生成的 DLL 在程序中运行是否也会有闪退 如果有&#xff0c;则…

knife4j springboot3使用

简介 在日常开发中&#xff0c;写接口文档是我们必不可少的&#xff0c;而Knife4j就是一个接口文档工具&#xff0c;可以看作是Swagger的升级版&#xff0c;但是界面比Swagger更好看&#xff0c;功能更丰富 使用 我使用的是springboot3.2.3 knife4j 4.3.0,knife4j 4.4版本有…

fpga_cpu加速

一 cpu流水线执行指令 二 计算机体系结构 注&#xff1a;ARM就是典型的哈佛结构 三 cpu加速 同样采用流水线&#xff0c;哈佛结构的指令效率更高&#xff0c;通过指令预取&#xff0c;提高了流水线的并行度。

线程的同步(synchronized的原理和用法,解决线程同步时的通信问题)

线程的同步锁&#xff08;synchronized&#xff09; 为什么会出现线程的同步锁&#xff1f; 因为JVM虚拟机是抢占调度模型&#xff0c;当多个线程在同时访问一个资源时会发生两个线程争抢一个资源&#xff0c;在一个线程没有执行结束时&#xff0c;另一个线程抢到资源&#x…

如何在 Tomcat 中为 Web 应用程序启用和配置缓存?

在Tomcat中为Web应用程序启用和配置缓存通常涉及到对Tomcat的连接器&#xff08;Connector&#xff09;进行配置&#xff0c;以及可能的话&#xff0c;配置Web应用程序本身以支持缓存。 1. 配置Tomcat连接器以启用缓存 Tomcat的连接器可以通过其配置来启用各种…

怎么在wifi中实现手机和电脑文件互传

有时我们想手机电脑文件互传&#xff0c;数据线却不在身边&#xff0c;这时我们可以用MiXplorer来实现wifi中手机和电脑互相访问文件。 MiXplorer是一款来自著名安卓开发者论坛XDA的作品&#xff0c;免费且功能强大&#xff0c;被很多人誉为是“全能文件管理器”。 1.在手机上…

分布式系统 —— 分布式线性回归的应用

在本文中&#xff0c;你将学习如何在分布式环境中实现线性回归。 1. 题目背景 假设每个节点i都可以访问以下观测数据&#xff1a; 给定的公式 描述了每个节点观察到的线性关系&#xff0c;其中 是第 次观察的已知输入。 是第 次观察的已知输出。 和分别是未知的斜率系数和截距…

PostMan使用自带js库base64编码、sha256摘要、环境变量的使用

目录 1、环境变量的使用2、base64编码、sha256摘要、以及脚本的使用3、脚本代码 在请求调试接口的过程中&#xff0c;因为要使用大量相同的参数&#xff0c;使用变量的方式能很大程度上减轻接口调用的工作量 版本说明&#xff1a;Postman for Windows&#xff0c;Version&#…

uniapp_微信小程序自定义顶部导航栏和右侧胶囊对齐(不对齐来打我)

一、想要的效果 思路首先开启自定义导航栏&#xff0c;取消自带的导航栏&#xff0c;然后计算胶囊的高度和标题对齐 二、成品代码 1、首先再你需要居中的代码添加以下style <view class"header":style"{paddingTop:navBarTop px,height:navBarHeight px,…

Linux进一步研究权限-----------ACL使用

一、使用情况 1.1、场景: 某个大公司&#xff0c;在一个部门&#xff0c;有一个经理和手下有两个员工&#xff0c;在操控一个Linux项目,项目又分为三期做&#xff0c;然而一期比较重要&#xff0c;经理带着员工做完了&#xff0c;公司就觉得技术难点已经做完攻克了&#xff0…

多输入时序预测|GWO-CNN-LSTM|灰狼算法优化的卷积-长短期神经网络时序预测(Matlab)

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 灰狼优化算法&#xff1a; 卷积神经网络-长短期记忆网络&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容…