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

2024-02-24 13:20

本文主要是介绍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博客

这篇关于Android相机调用-libusbCamera【外接摄像头】【USB摄像头】 【多摄像头预览】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/742229

相关文章

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

kkFileView在线预览office的常见问题以及解决方案

《kkFileView在线预览office的常见问题以及解决方案》kkFileView在线预览Office常见问题包括base64编码配置、Office组件安装、乱码处理及水印添加,解决方案涉及版本适... 目录kkFileView在线预览office的常见问题1.base642.提示找不到OFFICE组件

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

python如何调用java的jar包

《python如何调用java的jar包》这篇文章主要为大家详细介绍了python如何调用java的jar包,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录一、安装包二、使用步骤三、代码演示四、自己写一个jar包五、打包步骤六、方法补充一、安装包pip3 install

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局