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

效果:

相关推荐
黄林晴3 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我4 小时前
flutter 之真手势冲突处理
android·flutter
法的空间4 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止4 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭4 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech4 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户2018792831674 小时前
为何Handler的postDelayed不适合精准定时任务?
android
叽哥5 小时前
Kotlin学习第 8 课:Kotlin 进阶特性:简化代码与提升效率
android·java·kotlin
Cui晨5 小时前
Android RecyclerView展示List<View> Adapter的数据源使用View
android
氦客5 小时前
Android Doze低电耗休眠模式 与 WorkManager
android·suspend·休眠模式·workmanager·doze·低功耗模式·state_doze