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代码
效果: