refactor(glass): 移除相机预览功能并简化拍照流程

- 从 GlassMediaServiceHelper 中移除相机画面共享相关方法
- 从 InspectionActivity 中移除预览相关的变量、回调和监听器
- 简化拍照逻辑,直接调用拍照功能而不经过预览流程
- 隐藏预览容器和缩放文本控件
- 移除缩放调整和预览超时处理逻辑
- 在拍照完成时不再停止预览服务
这个提交包含在:
徐勤民 2026-04-23 10:09:16 +08:00
父节点 fbbd205386
当前提交 ade4513cdf
共有 2 个文件被更改,包括 6 次插入201 次删除

查看文件

@ -1,9 +1,9 @@
package com.nova.brain.glass.helper package com.nova.brain.glass.helper
import android.view.Surface import com.nova.brain.glass.helper.GlassMediaServiceHelper.addPhotoCallback
import com.nova.brain.glass.helper.GlassMediaServiceHelper.getMaxZoomLevel
import com.rokid.security.glass3.open.sdk.GlassSdk import com.rokid.security.glass3.open.sdk.GlassSdk
import com.rokid.security.system.server.media.IMediaServer import com.rokid.security.system.server.media.IMediaServer
import com.rokid.security.system.server.media.callback.ICameraSurfaceCallback
import com.rokid.security.system.server.media.callback.PhotoFileCallback import com.rokid.security.system.server.media.callback.PhotoFileCallback
/** /**
@ -49,16 +49,6 @@ object GlassMediaServiceHelper {
service()?.removePhotoCallback(callback) service()?.removePhotoCallback(callback)
} }
/** 开始将相机画面共享到指定 Surface用于预览。 */
fun startCameraShare(surface: Surface, callback: ICameraSurfaceCallback) {
service()?.startCameraShare(surface, callback)
}
/** 停止相机画面共享。 */
fun stopCameraShare(callback: ICameraSurfaceCallback) {
service()?.stopCameraShare(callback)
}
/** 获取当前硬件支持的最大变焦级别。 */ /** 获取当前硬件支持的最大变焦级别。 */
fun getMaxZoomLevel(): Int { fun getMaxZoomLevel(): Int {
return service()?.maxZoomLevel ?: 0 return service()?.maxZoomLevel ?: 0

查看文件

@ -2,12 +2,7 @@ package com.nova.brain.glass.ui
import android.content.Intent import android.content.Intent
import android.os.Environment import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.view.WindowManager import android.view.WindowManager
import android.view.Surface
import android.view.TextureView
import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.nova.brain.glass.R import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivityInspectionBinding import com.nova.brain.glass.databinding.ActivityInspectionBinding
@ -19,7 +14,6 @@ import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.viewmodel.InspectionValidateState import com.nova.brain.glass.viewmodel.InspectionValidateState
import com.nova.brain.glass.viewmodel.InspectionVM import com.nova.brain.glass.viewmodel.InspectionVM
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
import com.rokid.security.system.server.media.callback.ICameraSurfaceCallback
import com.rokid.security.system.server.media.callback.PhotoFileCallback import com.rokid.security.system.server.media.callback.PhotoFileCallback
import com.xuqm.base.adapter.BasePagedAdapter import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter import com.xuqm.base.adapter.CommonPagedAdapter
@ -39,20 +33,6 @@ class InspectionActivity :
private val glassTaskId: String by lazy { intent.getStringExtra("glassTaskId").orEmpty() } private val glassTaskId: String by lazy { intent.getStringExtra("glassTaskId").orEmpty() }
private var pendingPhotoPath: String? = null private var pendingPhotoPath: String? = null
private var isPreviewRequested = false
private var isPreviewActive = false
private var currentZoomLevel = 1
private var maxZoomLevel = 1
private var previewStartAttempted = false
private var previewSurface: Surface? = null
private val mainHandler = Handler(Looper.getMainLooper())
private val previewTimeoutRunnable = Runnable {
if (isPreviewActive || !isPreviewRequested) return@Runnable
LogHelper.d("Inspection preview timeout, fallback to direct takePhoto")
stopCameraPreview()
binding.hint.text = "预览不可用,直接拍照中,请稍后..."
takePhoto()
}
private val listener = object : OfflineCmdListener { private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) { override fun onOfflineCmd(cmd: String) {
@ -61,84 +41,18 @@ class InspectionActivity :
when (cmd) { when (cmd) {
"退出", "返回", "退回" -> finish() "退出", "返回", "退回" -> finish()
"开始", "开始任务" -> startCapture() "开始", "开始任务" -> startCapture()
"拍照", "拍摄" -> if (isPreviewActive) capturePhoto() else startCapture() "拍照", "拍摄" -> startCapture()
"放大", "拉近" -> adjustZoom(1)
"缩小", "拉远" -> adjustZoom(-1)
} }
} }
} }
} }
private val cameraSurfaceCallbackId = UUID.randomUUID().toString()
private val cameraSurfaceCallback = object : ICameraSurfaceCallback.Stub() {
override fun onCameraOpened(width: Int, height: Int) {
LogHelper.d("Inspection preview onCameraOpened: ${width}x$height")
isPreviewActive = true
mainHandler.removeCallbacks(previewTimeoutRunnable)
currentZoomLevel = GlassMediaServiceHelper.getZoomLevel().coerceAtLeast(1)
maxZoomLevel = GlassMediaServiceHelper.getMaxZoomLevel().coerceAtLeast(1)
runOnUiThread {
binding.cameraPreviewContainer.visibility = View.VISIBLE
binding.zoomText.visibility = View.VISIBLE
updateZoomText()
binding.hint.text = "预览中,单击预览或语音输入“拍照”完成拍摄"
}
}
override fun onCameraClosed() {
LogHelper.d("Inspection preview onCameraClosed")
isPreviewActive = false
mainHandler.removeCallbacks(previewTimeoutRunnable)
runOnUiThread {
binding.cameraPreviewContainer.visibility = View.GONE
binding.zoomText.visibility = View.GONE
}
}
override fun onError(code: Int, message: String?) {
LogHelper.d("Inspection preview onError: code=$code msg=$message")
isPreviewActive = false
mainHandler.removeCallbacks(previewTimeoutRunnable)
runOnUiThread {
binding.cameraPreviewContainer.visibility = View.GONE
binding.zoomText.visibility = View.GONE
binding.hint.text = "相机预览失败,请重试"
(message ?: "相机预览失败").showMessage()
}
}
override fun getCallbackId(): String = cameraSurfaceCallbackId
}
private val previewTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(surface: android.graphics.SurfaceTexture, width: Int, height: Int) {
LogHelper.d("Inspection preview surface available: ${width}x$height, requested=$isPreviewRequested")
if (isPreviewRequested) {
startCameraPreview()
}
}
override fun onSurfaceTextureSizeChanged(
surface: android.graphics.SurfaceTexture,
width: Int,
height: Int
) = Unit
override fun onSurfaceTextureDestroyed(surface: android.graphics.SurfaceTexture): Boolean = true
override fun onSurfaceTextureUpdated(surface: android.graphics.SurfaceTexture) = Unit
}
override fun initData() { override fun initData() {
super.initData() super.initData()
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
SprayingPhotoManager.clear() SprayingPhotoManager.clear()
binding.cameraPreview.surfaceTextureListener = previewTextureListener binding.cameraPreviewContainer.visibility = android.view.View.GONE
binding.cameraPreview.setOnClickListener { binding.zoomText.visibility = android.view.View.GONE
if (isPreviewActive) {
capturePhoto()
}
}
viewModel.taskInfo.observe(this) { item -> viewModel.taskInfo.observe(this) { item ->
if (item != null) { if (item != null) {
@ -186,109 +100,13 @@ class InspectionActivity :
} }
private fun startCapture() { private fun startCapture() {
if (viewModel.validateState.value == InspectionValidateState.LOADING) return
if (isPreviewActive) {
capturePhoto()
return
}
LogHelper.d("Inspection startCapture: previewActive=$isPreviewActive, textureAvailable=${binding.cameraPreview.isAvailable}")
binding.hint.text = "相机预览启动中,请稍后..."
isPreviewRequested = true
previewStartAttempted = false
SprayingPhotoManager.clear()
binding.cameraPreviewContainer.visibility = View.VISIBLE
binding.zoomText.visibility = View.VISIBLE
if (binding.cameraPreview.isAvailable) {
startCameraPreview()
} else {
binding.cameraPreview.post {
LogHelper.d("Inspection preview post check: textureAvailable=${binding.cameraPreview.isAvailable}, requested=$isPreviewRequested")
if (isPreviewRequested && binding.cameraPreview.isAvailable) {
startCameraPreview()
}
}
}
}
private fun startCameraPreview() {
if (!isPreviewRequested || previewStartAttempted) {
LogHelper.d("Inspection startCameraPreview skipped: requested=$isPreviewRequested attempted=$previewStartAttempted")
return
}
val surfaceTexture = binding.cameraPreview.surfaceTexture ?: return
val width = binding.cameraPreview.width.coerceAtLeast(1)
val height = binding.cameraPreview.height.coerceAtLeast(1)
surfaceTexture.setDefaultBufferSize(width, height)
previewStartAttempted = true
previewSurface?.release()
previewSurface = Surface(surfaceTexture)
LogHelper.d("Inspection startCameraPreview invoke startCameraShare, buffer=${width}x$height")
mainHandler.removeCallbacks(previewTimeoutRunnable)
mainHandler.postDelayed(previewTimeoutRunnable, 1000L)
runCatching {
GlassMediaServiceHelper.startCameraShare(previewSurface!!, cameraSurfaceCallback)
}.onFailure {
isPreviewRequested = false
previewStartAttempted = false
mainHandler.removeCallbacks(previewTimeoutRunnable)
previewSurface?.release()
previewSurface = null
binding.cameraPreviewContainer.visibility = View.GONE
binding.zoomText.visibility = View.GONE
binding.hint.text = "相机预览启动失败,请重试"
LogHelper.e("Inspection startCameraPreview failed: ${it.message}", it)
(it.message ?: "相机预览启动失败").showMessage()
}
}
private fun stopCameraPreview() {
isPreviewRequested = false
isPreviewActive = false
previewStartAttempted = false
mainHandler.removeCallbacks(previewTimeoutRunnable)
LogHelper.d("Inspection stopCameraPreview")
runCatching {
GlassMediaServiceHelper.stopCameraShare(cameraSurfaceCallback)
}.onFailure {
LogHelper.e("Inspection stopCameraPreview failed: ${it.message}", it)
}
previewSurface?.release()
previewSurface = null
binding.cameraPreviewContainer.visibility = View.GONE
binding.zoomText.visibility = View.GONE
}
private fun capturePhoto() {
if (viewModel.validateState.value == InspectionValidateState.LOADING) return if (viewModel.validateState.value == InspectionValidateState.LOADING) return
binding.hint.text = "拍照中,请稍后..." binding.hint.text = "拍照中,请稍后..."
SprayingPhotoManager.clear()
takePhoto() takePhoto()
} }
private fun adjustZoom(delta: Int) {
if (!isPreviewActive) return
maxZoomLevel = GlassMediaServiceHelper.getMaxZoomLevel().coerceAtLeast(1)
currentZoomLevel = (GlassMediaServiceHelper.getZoomLevel() + delta).coerceIn(1, maxZoomLevel)
runCatching {
GlassMediaServiceHelper.zoomCamera(currentZoomLevel)
}.onSuccess {
updateZoomText()
}.onFailure {
(it.message ?: "缩放失败").showMessage()
}
}
private fun updateZoomText() {
binding.zoomText.text = "缩放 ${currentZoomLevel}x"
}
private fun takePhoto() { private fun takePhoto() {
runCatching {
val maxZoom = GlassMediaServiceHelper.getMaxZoomLevel().coerceAtLeast(1)
GlassMediaServiceHelper.zoomCamera(maxZoom)
currentZoomLevel = maxZoom
}.onFailure {
LogHelper.e("Inspection takePhoto set max zoom failed: ${it.message}", it)
}
val fileName = "inspection_${System.currentTimeMillis()}.png" val fileName = "inspection_${System.currentTimeMillis()}.png"
val file = File( val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
@ -309,7 +127,6 @@ class InspectionActivity :
override fun onTakePhotoV2(path: String?, width: Int, height: Int) { override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
if (path == null) { if (path == null) {
runOnUiThread { runOnUiThread {
stopCameraPreview()
binding.hint.text = "单击或语音输入\"开始\",进入下一步" binding.hint.text = "单击或语音输入\"开始\",进入下一步"
} }
"相机异常".showMessage() "相机异常".showMessage()
@ -318,7 +135,6 @@ class InspectionActivity :
SprayingPhotoManager.addPhoto(path) SprayingPhotoManager.addPhoto(path)
pendingPhotoPath = path pendingPhotoPath = path
runOnUiThread { runOnUiThread {
stopCameraPreview()
viewModel.validateDocument(path) viewModel.validateDocument(path)
} }
} }
@ -347,7 +163,6 @@ class InspectionActivity :
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
stopCameraPreview()
GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback) GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
OfflineCmdServiceHelper.removeListenerInspectionCapture() OfflineCmdServiceHelper.removeListenerInspectionCapture()