Android studio APK切换多个摄像头(Camera2)

1.先设置camera的权限

 <uses-permission android:name="android.permission.CAMERA" />

2.布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextureViewandroid:id="@+id/textureView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><Buttonandroid:id="@+id/btnSwitchCamera"android:layout_width="match_parent"android:layout_height="100dp"android:textSize="50dp"android:text="切换相机"/></LinearLayout>

3.主界面代码

package com.example.multiplecamerasimport android.Manifest
import android.content.pm.PackageManager
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.Surface
import android.view.TextureView
import android.view.TextureView.SurfaceTextureListener
import android.view.View
import androidx.annotation.NonNull
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.hjq.permissions.OnPermission
import com.hjq.permissions.XXPermissionsclass MainActivity : AppCompatActivity() {private val TAG = MainActivity::class.java.simpleNameprivate var cameraManager: CameraManager? = nullprivate var cameraIds: Array<String>?=nullprivate var currentCameraIdIndex = 0private var cameraDevice: CameraDevice? = nullprivate var textureView: TextureView? = nullprivate var captureRequestBuilder: CaptureRequest.Builder? = nullprivate var cameraCaptureSession: CameraCaptureSession? = nullprivate var surfaceTexture: SurfaceTexture? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)XXPermissions.with(this).request(object : OnPermission {@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun hasPermission(granted: List<String>, isAll: Boolean) {Log.e("TAG", "hasPermission=" + granted.size + "       " + isAll)initView()}override fun noPermission(denied: List<String>, quick: Boolean) {Log.e("TAG", "noPermission=" + denied.size + "       " + quick)}})}@RequiresApi(Build.VERSION_CODES.LOLLIPOP)fun initView(){cameraManager = getSystemService(CAMERA_SERVICE) as CameraManagertextureView = findViewById(R.id.textureView)// 设置 TextureView 的监听器,用于在 SurfaceTexture 准备好时打开相机textureView!!.surfaceTextureListener = surfaceTextureListener// 相机切换按钮的点击事件监听器findViewById<View>(R.id.btnSwitchCamera).setOnClickListener {Log.e("TAG", "switchCamera()=========")switchCamera()}}private val surfaceTextureListener: SurfaceTextureListener = object : SurfaceTextureListener {override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {surfaceTexture = surfaceLog.e("TAG", "onSurfaceTextureAvailable")openCamera()}override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture,width: Int,height: Int) {}override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {return false}override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}}@RequiresApi(Build.VERSION_CODES.LOLLIPOP)private fun openCamera() {Log.e("TAG", "openCamera============")try {cameraIds = cameraManager!!.cameraIdList} catch (e: Exception) {e.printStackTrace()}if (cameraIds != null && cameraIds!!.isNotEmpty()) {val cameraId = cameraIds!![currentCameraIdIndex]if (ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {// TODO: Consider calling//    ActivityCompat#requestPermissions// here to request the missing permissions, and then overriding//   public void onRequestPermissionsResult(int requestCode, String[] permissions,//                                          int[] grantResults)// to handle the case where the user grants the permission. See the documentation// for ActivityCompat#requestPermissions for more details.return}Log.e("TAG", "openCamera============$cameraId")cameraManager!!.openCamera(cameraId, cameraCallback, null)}}private val cameraCallback: CameraDevice.StateCallback = @RequiresApi(Build.VERSION_CODES.LOLLIPOP)object : CameraDevice.StateCallback() {@RequiresApi(Build.VERSION_CODES.O)override fun onOpened(@NonNull camera: CameraDevice) {cameraDevice = cameraLog.e("TAG", "onOpened============$cameraDevice")startPreview()}override fun onDisconnected(@NonNull camera: CameraDevice) {cameraDevice!!.close()}override fun onError(@NonNull camera: CameraDevice, error: Int) {cameraDevice!!.close()}}@RequiresApi(Build.VERSION_CODES.O)private fun startPreview() {if (cameraDevice == null) {return}Log.e("TAG", "startPreview=====1=======$cameraDevice")try {val surface = Surface(surfaceTexture)// 创建 CaptureRequest.Builder,并设置 Surface 作为目标captureRequestBuilder = cameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)captureRequestBuilder!!.addTarget(surface)Log.e("TAG", "startPreview===2=========${cameraDevice!!.id}")// 创建相机捕获会话cameraDevice!!.createCaptureSession(listOf(surface),captureSessionCallback,null)} catch (e: Exception) {Log.e("TAG", "e============${e.message}")}}private val captureSessionCallback: CameraCaptureSession.StateCallback =@RequiresApi(Build.VERSION_CODES.LOLLIPOP)object : CameraCaptureSession.StateCallback() {override fun onConfigured(@NonNull session: CameraCaptureSession) {cameraCaptureSession = session// 设置重复预览请求try {cameraCaptureSession!!.setRepeatingRequest(captureRequestBuilder!!.build(),null,null)} catch (e: CameraAccessException) {e.printStackTrace()}}override fun onConfigureFailed(@NonNull session: CameraCaptureSession) {Log.e(TAG, "Failed to configure camera capture session")}}private fun switchCamera() {if (cameraIds != null && cameraIds!!.size > 1) {cameraDevice!!.close()currentCameraIdIndex = (currentCameraIdIndex + 1) % cameraIds!!.sizeval cameraId = cameraIds!![currentCameraIdIndex]try {if (ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {// TODO: Consider calling//    ActivityCompat#requestPermissions// here to request the missing permissions, and then overriding//   public void onRequestPermissionsResult(int requestCode, String[] permissions,//                                          int[] grantResults)// to handle the case where the user grants the permission. See the documentation// for ActivityCompat#requestPermissions for more details.return}cameraManager!!.openCamera(cameraId, cameraCallback, null)} catch (e: CameraAccessException) {e.printStackTrace()}}}@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onPause() {super.onPause()cameraDevice?.close()}override fun onResume() {super.onResume()if (cameraDevice == null && surfaceTexture != null) {openCamera()}}}

XXPermissions.with(this).request(object : OnPermission {@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun hasPermission(granted: List<String>, isAll: Boolean) {Log.e("TAG", "hasPermission=" + granted.size + "       " + isAll)}override fun noPermission(denied: List<String>, quick: Boolean) {Log.e("TAG", "noPermission=" + denied.size + "       " + quick)}})

这部分代码是用来授权AndroidManifest.xml里面权限的第三方sdk代码

效果:

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

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

相关文章

vue中html引入使用<%= BASE_URL %>变量

首先使用src相对路径引入 注意&#xff1a; js 文件放在public文件下 不要放在assets静态资源文件下 否则 可能会报错 GET http://192.168.0.113:8080/src/assets/js/websockets.js net::ERR_ABORTED 500 (Internal Server Error) 正确使用如下&#xff1a;eg // html中引…

go gin 参数绑定常用验证器

https://pkg.go.dev/github.com/go-playground/validator/v10#readme-baked-in-validations min 最小max 最大len 长度限制gt 大于eq 等于ne 不等于eqfield 与某个字段值一样nefield 与某个字段值不一样 package mainimport ("net/http""github.com/gin-gonic…

7.react useReducer使用与常见问题

useReducer函数 1. useState的替代方案.接收一个(state, action)>newState的reducer, 并返回当前的state以及与其配套的dispatch方法2. 在某些场景下,useReducer会比useState更加适用,例如state逻辑较为复杂, 且**包含多个子值**,或者下一个state依赖于之前的state等清楚us…

【Leetcode】124.二叉树中的最大路径和(Hard)

一、题目 1、题目描述 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root ,返回其…

进行Stable Diffusion的ai训练怎么选择显卡?

Stable Diffusion主要用于从文本生成图像&#xff0c;是人工智能技术在内容创作行业中不断发展的应用。要在本地计算机上运行Stable Diffusion&#xff0c;您需要一个强大的 GPU 来满足其繁重的要求。强大的 GPU 可以让您更快地生成图像&#xff0c;而具有大量 VRAM 的更强大的…

2023年高教社杯 国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

微信小程序——van-field中的left-icon属性自定义

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【网络安全带你练爬虫-100练】第19练:使用python打开exe文件

目录 一、目标1&#xff1a;调用exe文件 二、目标2&#xff1a;调用exe打开文件 一、目标1&#xff1a;调用exe文件 1、subprocess 模块允许在 Python 中启动一个新的进程&#xff0c;并与其进行交互 2、subprocess.run() 函数来启动exe文件 3、subprocess.run(["文件路…

无涯教程-机器学习 - 箱形图函数

Box和Whisker图(也简称为boxplots)是另一种有用的技术&#xff0c;可用于检查每个属性的分布情况。以下是此技术的特点- 它本质上是单变量的&#xff0c;总结了每个属性的分布。它为中间值(即中位数)画一条线。它将在25&#xff05;和75&#xff05;周围绘制一个框。它还会绘制…

linux并发服务器 —— 文件IO相关函数(三)

文件IO 以内存为主体&#xff0c;看待输入输出&#xff1b; 标准C库IO函数带有缓冲区&#xff0c;效率较高&#xff1b; 虚拟地址空间 虚拟地址空间是不存在的&#xff0c;一个应用程序运行期间对应一个虚拟地址空间&#xff1b; 虚拟地址空间的大小由CPU决定&#xff0c;位…

对《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》的改进

《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》使用的Activex DLL公共对象是需要先注册的。https://blog.csdn.net/weixin_45707491/article/details/132437502?spm1001.2014.3001.5501 Activex DLL事前注册&#xff0c;一次多用说起来也不是啥大问题&#x…

R语言常用数学函数

目录 1. - * / ^ 2.%/%和%% 3.ceiling,floor,round 4.signif,trunc,zapsamll 5.max,min,mean,pmax,pmin 6.range和sum 7.prod 8.cumsum,cumprod,cummax,cummin 9.sort 10. approx 11.approx fun 12.diff 13.sign 14.var和sd 15.median 16.IQR 17.ave 18.five…

css元素定位:通过元素的标签或者元素的id、class属性定位,还不明白的伙计,看这个就行了!

前言 大部分人在使用selenium定位元素时&#xff0c;用的是xpath元素定位方式&#xff0c;因为xpath元素定位方式基本能解决定位的需求。xpath元素定位方式更直观&#xff0c;更好理解一些。 css元素定位方式往往被忽略掉了&#xff0c;其实css元素定位方式也有它的价值&…

WPF自定义命令及属性改变处理

1、项目建构 2、自定义命令 namespace WpfDemo.Base {public class MyCommand : ICommand{Action executeAction;public MyCommand(Action action){executeAction action;}public event EventHandler? CanExecuteChanged;public bool CanExecute(object? parameter){retu…

【从零开始学习JAVA | 第四十六篇】处理请求参数

前言&#xff1a; 在我们之前的学习中&#xff0c;我们已经基本学习完了JAVA的基础内容&#xff0c;从今天开始我们就逐渐进入到JAVA的时间&#xff0c;在这一大篇章&#xff0c;我们将对前后端有一个基本的认识&#xff0c;并要学习如何成为一名合格的后端工程师。今天我们介绍…

北京筑龙受邀出席中物联“采购供应链中国行—走进雄安”活动

日前&#xff0c;“采购供应链中国行—走进雄安”活动在河北雄安新区成功举办&#xff0c;来自30家相关单位的50余名领导和代表参加了本次活动。活动由中国物流与采购联合会公共采购分会主办&#xff0c;中国物流与采购联合会采购委、中国雄安集团有限公司、河北雄安新区招标投…

在 Python 中逐步构建 DCF(贴现流)估值

Building A DCF Valuation in Python, Step by Step | by Roi Polanitzer | Medium 说明 这是一个真实的&#xff0c;以色列国土内的公司业务评估案例。在本文中&#xff0c;我将演示如何使用python中的DCF方法对以色列系统和应用程序公司进行业务评估。因为存在许多业务术语&a…

Jmeter(二十八):beanshell的使用

Beanshell 是一种轻量级的 Java 脚本,纯 Java 编写的,能够动态的执行标准 java 语法及一些扩展脚本语法,类似于 javaScript,在工作中可能用的多的就是: Beanshell 取样器:跟Http取样器并列Beanshell前置处理器:一般放在Http请求下,在请求前处理一些数据Beanshell后置处…

万级数据优化EasyExcel+mybatis流式查询导出封装

文章目录 前言.千万级数据优化一. 直接上流式查询封装工具代码二. 传统分页导出查询三. 流式查询概念游标查询 前言.千万级数据优化 我们不妨先给大家讲一个概念&#xff0c;利用此概念我们正好给大家介绍一个数据库优化的小技巧&#xff1a; 需求如下&#xff1a;将一个地市表…

【conda install】网络慢导致报错CondaHTTPError: HTTP 000 CONNECTION FAILED for url

⭐⭐问题&#xff1a; 部署安装环境经常会出现由于网络慢问题&#xff0c;导致conda安装不了库&#xff0c;报错如下&#xff1a; Solving environment: failedCondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/…