实现了双屏摄像头显示,添加了部分代码
This commit is contained in:
@@ -6,10 +6,14 @@ import android.hardware.display.DisplayManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
import android.widget.AdapterView
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.ImageCapture
|
||||
import androidx.camera.core.ImageCaptureException
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.core.content.ContextCompat
|
||||
@@ -17,14 +21,23 @@ 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.dualscreen.view.CustomBottomSheetDialog
|
||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||
import com.sw.plate.utils.AppUtil
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
|
||||
private val viewModel = MyViewModel()
|
||||
private val viewModel by viewModels<UserViewModel>()
|
||||
private lateinit var imageCapture: ImageCapture
|
||||
private var isAnalyzing = true // 控制是否进行图像分析
|
||||
private lateinit var presentation: SecondaryScreenPresentation
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -32,51 +45,136 @@ class MainActivity : AppCompatActivity() {
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.main)
|
||||
|
||||
Timber.d("UDID = ${AppUtil.getUDID(this)}")
|
||||
initView()
|
||||
startCamera()
|
||||
setupSecondaryDisplay()
|
||||
setupCamera()
|
||||
initData()
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
viewModel.getEquipmentToken()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
viewModel.activeEngine()
|
||||
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)
|
||||
outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
|
||||
}
|
||||
}
|
||||
binding.previewView.clipToOutline = true
|
||||
|
||||
binding.tvToSearch.setOnClickListener {
|
||||
val bottomSheetDialog = CustomBottomSheetDialog.newInstance()
|
||||
bottomSheetDialog.show(supportFragmentManager, "CustomBottomSheetDialog")
|
||||
}
|
||||
binding.spinner.setItems(arrayOf("即放即取", "持续取餐"))
|
||||
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>?,
|
||||
view: View?,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun startCamera() {
|
||||
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||
private fun setupCamera() {
|
||||
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||
cameraProviderFuture.addListener({
|
||||
val cameraProvider = cameraProviderFuture.get()
|
||||
|
||||
// 创建预览用例
|
||||
// 1. 创建预览用例
|
||||
val preview = Preview.Builder()
|
||||
.build()
|
||||
.also {
|
||||
it.setSurfaceProvider(binding.previewView.surfaceProvider)
|
||||
}
|
||||
|
||||
// 选择后置摄像头
|
||||
// 2. 创建图像分析用例(用于副屏显示)
|
||||
val imageAnalysis = ImageAnalysis.Builder()
|
||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||
// .setTargetResolution(Size(640, 480)) // 降低分辨率减轻负担
|
||||
.build()
|
||||
.also { analysis ->
|
||||
analysis.setAnalyzer(executor) { imageProxy ->
|
||||
if (isAnalyzing) {
|
||||
val bitmap = imageProxy.toBitmap()
|
||||
runOnUiThread {
|
||||
presentation.updateImage(bitmap) // 更新副屏
|
||||
}
|
||||
}
|
||||
imageProxy.close() // 必须关闭以释放资源
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 创建拍照用例
|
||||
imageCapture = ImageCapture.Builder()
|
||||
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
||||
// .setTargetResolution(Size(1920, 1080)) // 设置拍照分辨率
|
||||
.build()
|
||||
|
||||
// 4. 选择摄像头
|
||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
|
||||
try {
|
||||
// 解绑所有用例
|
||||
cameraProvider.unbindAll()
|
||||
|
||||
// 绑定到生命周期
|
||||
// 绑定三个用例到生命周期
|
||||
cameraProvider.bindToLifecycle(
|
||||
this, cameraSelector, preview
|
||||
this, cameraSelector, preview, imageAnalysis, imageCapture
|
||||
)
|
||||
} catch (exc: Exception) {
|
||||
Timber.e(exc, "Use case binding failed")
|
||||
Timber.e(exc.message)
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(this))
|
||||
}
|
||||
|
||||
// 拍照功能
|
||||
private fun takePhoto() {
|
||||
// 临时停止分析以避免干扰
|
||||
isAnalyzing = false
|
||||
|
||||
// 创建输出选项
|
||||
val outputFileOptions = ImageCapture.OutputFileOptions.Builder(
|
||||
File(
|
||||
cacheDir.path, "IMG_${System.currentTimeMillis()}.jpg"
|
||||
)
|
||||
).build()
|
||||
// 执行拍照
|
||||
imageCapture.takePicture(
|
||||
outputFileOptions,
|
||||
executor,
|
||||
object : ImageCapture.OnImageSavedCallback {
|
||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||
runOnUiThread {
|
||||
ToastUtils.showToast("照片保存成功: ${outputFileResults.savedUri}")
|
||||
}
|
||||
// 恢复图像分析
|
||||
isAnalyzing = true
|
||||
}
|
||||
|
||||
override fun onError(exception: ImageCaptureException) {
|
||||
Timber.e("拍照失败: ${exception.message}")
|
||||
runOnUiThread {
|
||||
ToastUtils.showToast("拍照失败: ${exception.message}")
|
||||
}
|
||||
// 恢复图像分析
|
||||
isAnalyzing = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupSecondaryDisplay() {
|
||||
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
val displays = displayManager.displays
|
||||
@@ -85,7 +183,7 @@ class MainActivity : AppCompatActivity() {
|
||||
if (displays.size > 1) {
|
||||
val secondaryDisplay = displays[1]
|
||||
// 创建副屏的Presentation
|
||||
val presentation =
|
||||
presentation =
|
||||
SecondaryScreenPresentation(
|
||||
activity = this,
|
||||
this,
|
||||
|
||||
Reference in New Issue
Block a user