init
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
package com.sw.dualscreen.activity
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.SurfaceTexture
|
||||
import android.hardware.camera2.CameraCaptureSession
|
||||
import android.hardware.camera2.CameraDevice
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.hardware.camera2.CaptureRequest
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Surface
|
||||
import android.view.TextureView
|
||||
import android.widget.Button
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.sw.dualscreen.R
|
||||
|
||||
class Camera2Activity : AppCompatActivity() {
|
||||
private lateinit var cameraManager: CameraManager
|
||||
private var cameraIdList: Array<String> = arrayOf()
|
||||
private var currentCameraIdIndex = 0
|
||||
private lateinit var textureView: TextureView
|
||||
private var cameraDevice: CameraDevice? = null
|
||||
private var cameraCaptureSession: CameraCaptureSession? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_camera2)
|
||||
|
||||
textureView = findViewById(R.id.textureView)
|
||||
cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
|
||||
// 获取摄像头列表
|
||||
cameraIdList = cameraManager.cameraIdList
|
||||
if (cameraIdList.isEmpty()) {
|
||||
Toast.makeText(this, "没有可用的摄像头", Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
|
||||
// 设置TextureView监听
|
||||
textureView.surfaceTextureListener = surfaceTextureListener
|
||||
|
||||
// 切换摄像头按钮
|
||||
findViewById<Button>(R.id.switchButton).setOnClickListener {
|
||||
switchCamera()
|
||||
}
|
||||
}
|
||||
|
||||
private val surfaceTextureListener = object : TextureView.SurfaceTextureListener {
|
||||
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
|
||||
openCamera(cameraIdList[currentCameraIdIndex])
|
||||
}
|
||||
|
||||
override fun onSurfaceTextureSizeChanged(
|
||||
surface: SurfaceTexture,
|
||||
width: Int,
|
||||
height: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = true
|
||||
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
|
||||
}
|
||||
|
||||
private fun openCamera(cameraId: String) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) !=
|
||||
PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
cameraManager.openCamera(cameraId, object : CameraDevice.StateCallback() {
|
||||
override fun onOpened(device: CameraDevice) {
|
||||
cameraDevice = device
|
||||
createCameraPreviewSession()
|
||||
}
|
||||
|
||||
override fun onDisconnected(device: CameraDevice) {
|
||||
device.close()
|
||||
cameraDevice = null
|
||||
}
|
||||
|
||||
override fun onError(device: CameraDevice, error: Int) {
|
||||
device.close()
|
||||
cameraDevice = null
|
||||
}
|
||||
}, null)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Camera2", "打开摄像头失败", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCameraPreviewSession() {
|
||||
val surfaceTexture = textureView.surfaceTexture
|
||||
surfaceTexture?.setDefaultBufferSize(textureView.width, textureView.height)
|
||||
val surface = Surface(surfaceTexture)
|
||||
|
||||
try {
|
||||
val previewRequestBuilder = cameraDevice?.createCaptureRequest(
|
||||
CameraDevice.TEMPLATE_PREVIEW
|
||||
)?.apply {
|
||||
addTarget(surface)
|
||||
}
|
||||
|
||||
cameraDevice?.createCaptureSession(
|
||||
listOf(surface),
|
||||
object : CameraCaptureSession.StateCallback() {
|
||||
override fun onConfigured(session: CameraCaptureSession) {
|
||||
cameraCaptureSession = session
|
||||
previewRequestBuilder?.let { builder ->
|
||||
builder.set(
|
||||
CaptureRequest.CONTROL_AF_MODE,
|
||||
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
|
||||
)
|
||||
session.setRepeatingRequest(builder.build(), null, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigureFailed(session: CameraCaptureSession) {
|
||||
Toast.makeText(this@Camera2Activity, "配置失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
null
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Camera2", "创建预览会话失败", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchCamera() {
|
||||
if (cameraIdList.size <= 1) {
|
||||
Toast.makeText(this, "只有一个摄像头", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
// 关闭当前摄像头
|
||||
cameraCaptureSession?.close()
|
||||
cameraCaptureSession = null
|
||||
cameraDevice?.close()
|
||||
cameraDevice = null
|
||||
|
||||
// 切换到下一个摄像头
|
||||
currentCameraIdIndex = (currentCameraIdIndex + 1) % cameraIdList.size
|
||||
openCamera(cameraIdList[currentCameraIdIndex])
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
cameraCaptureSession?.close()
|
||||
cameraDevice?.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.sw.dualscreen.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Outline
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.sw.dualscreen.databinding.ActivityMainBinding
|
||||
import com.sw.dualscreen.ext.dp
|
||||
import com.sw.dualscreen.presentation.SecondaryScreenPresentation
|
||||
import com.sw.dualscreen.viewmodel.MyViewModel
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
import timber.log.Timber
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
|
||||
private val viewModel = MyViewModel()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.main)
|
||||
|
||||
initView()
|
||||
startCamera()
|
||||
setupSecondaryDisplay()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
binding.previewView.outlineProvider = object : ViewOutlineProvider() {
|
||||
override fun getOutline(view: View, outline: Outline) {
|
||||
// outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
|
||||
outline.setRoundRect(0, 0, view.width, view.height, 280f.dp)
|
||||
}
|
||||
}
|
||||
binding.previewView.clipToOutline = true
|
||||
}
|
||||
|
||||
|
||||
private fun startCamera() {
|
||||
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||
cameraProviderFuture.addListener({
|
||||
val cameraProvider = cameraProviderFuture.get()
|
||||
|
||||
// 创建预览用例
|
||||
val preview = Preview.Builder()
|
||||
.build()
|
||||
.also {
|
||||
it.setSurfaceProvider(binding.previewView.surfaceProvider)
|
||||
}
|
||||
|
||||
// 选择后置摄像头
|
||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
|
||||
try {
|
||||
// 解绑所有用例
|
||||
cameraProvider.unbindAll()
|
||||
|
||||
// 绑定到生命周期
|
||||
cameraProvider.bindToLifecycle(
|
||||
this, cameraSelector, preview
|
||||
)
|
||||
} catch (exc: Exception) {
|
||||
Timber.e(exc, "Use case binding failed")
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(this))
|
||||
}
|
||||
|
||||
private fun setupSecondaryDisplay() {
|
||||
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
val displays = displayManager.displays
|
||||
|
||||
// 查找副屏(通常索引为1)
|
||||
if (displays.size > 1) {
|
||||
val secondaryDisplay = displays[1]
|
||||
// 创建副屏的Presentation
|
||||
val presentation =
|
||||
SecondaryScreenPresentation(
|
||||
activity = this,
|
||||
this,
|
||||
display = secondaryDisplay,
|
||||
viewModel = viewModel,
|
||||
recognizeViewModel = viewModels<RecognizeViewModel>().value
|
||||
)
|
||||
|
||||
presentation.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user