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">

    <TextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <Button
        android:id="@+id/btnSwitchCamera"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:textSize="50dp"
        android:text="切换相机"/>

</LinearLayout>

3.主界面代码

复制代码
package com.example.multiplecameras

import 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.XXPermissions


class MainActivity : AppCompatActivity() {


    private val TAG = MainActivity::class.java.simpleName
    private var cameraManager: CameraManager? = null
    private var cameraIds: Array<String>?=null
    private var currentCameraIdIndex = 0
    private var cameraDevice: CameraDevice? = null
    private var textureView: TextureView? = null

    private var captureRequestBuilder: CaptureRequest.Builder? = null
    private var cameraCaptureSession: CameraCaptureSession? = null
    private var surfaceTexture: SurfaceTexture? = null

    override 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 CameraManager
        textureView = 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 = surface
            Log.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 = camera
            Log.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!!.size
            val 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代码

效果:

相关推荐
来来走走9 分钟前
Flutter Form组件的基本使用
android·flutter
顾林海40 分钟前
Android MMKV 深度解析:原理、实践与源码剖析
android·面试·源码阅读
雨白1 小时前
TCP/IP 核心概念详解:从网络分层到连接管理
android
Wgllss2 小时前
雷电雨效果:Kotlin+Compose+协程+Flow 实现天气UI
android·架构·android jetpack
用户207038619494 小时前
Compose 可点击文本:ClickableText Compose 中的 ClickableSpan
android
常利兵4 小时前
Kotlin作用域函数全解:run/with/apply/let/also与this/it的魔法对决
android·开发语言·kotlin
幼稚园的山代王4 小时前
Kotlin-基础语法练习一
android·开发语言·kotlin
闻不多5 小时前
用llamaindex搭建GAR遇到400
android·运维·服务器
阿华的代码王国5 小时前
【Android】适配器与外部事件的交互
android·xml·java·前端·后端·交互
跨界混迹车辆网的Android工程师5 小时前
实现Android图片手势缩放功能的完整自定义View方案,结合了多种手势交互功能
android·交互