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代码

效果:

相关推荐
Kapaseker5 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴5 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭15 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab16 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe21 小时前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
三少爷的鞋1 天前
Android 协程时代,Handler 应该退休了吗?
android
火柴就是我2 天前
让我们实现一个更好看的内部阴影按钮
android·flutter