|
|
@@ -0,0 +1,224 @@
|
|
|
+package com.nova.brain.glass.ui
|
|
|
+
|
|
|
+import android.app.Activity
|
|
|
+import android.content.Intent
|
|
|
+import android.os.CountDownTimer
|
|
|
+import android.os.Environment
|
|
|
+import android.view.WindowManager
|
|
|
+import androidx.activity.result.contract.ActivityResultContracts
|
|
|
+import androidx.core.view.doOnLayout
|
|
|
+import androidx.recyclerview.widget.RecyclerView
|
|
|
+import com.nova.brain.glass.R
|
|
|
+import com.nova.brain.glass.databinding.ActivityInspectionResultBinding
|
|
|
+import com.nova.brain.glass.helper.BitmapDecodeHelper
|
|
|
+import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
|
|
+import com.nova.brain.glass.helper.OfflineCmdListener
|
|
|
+import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
|
|
+import com.nova.brain.glass.helper.SprayingPhotoManager
|
|
|
+import com.nova.brain.glass.model.ItemItem
|
|
|
+import com.nova.brain.glass.viewmodel.InspectionResultVM
|
|
|
+import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
|
|
+import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
|
|
+import com.xuqm.base.adapter.BasePagedAdapter
|
|
|
+import com.xuqm.base.adapter.CommonPagedAdapter
|
|
|
+import com.xuqm.base.adapter.ViewHolder
|
|
|
+import com.xuqm.base.common.LogHelper
|
|
|
+import com.xuqm.base.extensions.showMessage
|
|
|
+import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
|
|
|
+import java.io.File
|
|
|
+import java.util.UUID
|
|
|
+import java.util.concurrent.Executors
|
|
|
+import kotlin.random.Random
|
|
|
+
|
|
|
+class InspectionResultActivity :
|
|
|
+ BaseListFormLayoutNormalActivity<ItemItem, InspectionResultVM, ActivityInspectionResultBinding>() {
|
|
|
+
|
|
|
+ override fun getLayoutId(): Int = R.layout.activity_inspection_result
|
|
|
+ override fun fullscreen(): Boolean = true
|
|
|
+ override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL
|
|
|
+
|
|
|
+ private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
|
|
+ private var status = true // true=合格, false=不合格
|
|
|
+ private var resultCountdown: CountDownTimer? = null
|
|
|
+
|
|
|
+ companion object {
|
|
|
+ const val EXTRA_PHOTO_PATH = "extra_photo_path"
|
|
|
+ }
|
|
|
+
|
|
|
+ private val missingLauncher =
|
|
|
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
|
|
+ if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
|
|
|
+ when (result.data?.getStringExtra(InspectionMissingActivity.EXTRA_ACTION)) {
|
|
|
+ InspectionMissingActivity.ACTION_SUPPLEMENT -> {
|
|
|
+ // 补充单证:重新拍照
|
|
|
+ binding.tvTaskHeader.text = "拍照中,请稍后..."
|
|
|
+ takePhoto()
|
|
|
+ }
|
|
|
+ InspectionMissingActivity.ACTION_SUBMIT -> {
|
|
|
+ goComplete()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private val listener = object : OfflineCmdListener {
|
|
|
+ override fun onOfflineCmd(cmd: String) {
|
|
|
+ runOnUiThread {
|
|
|
+ when (cmd) {
|
|
|
+ "退出", "返回", "退回" -> finish()
|
|
|
+ "重拍照" -> retake()
|
|
|
+ "继续任务" -> continueTask()
|
|
|
+ "结束任务" -> endTask()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun initData() {
|
|
|
+ super.initData()
|
|
|
+ window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
|
+ val path = intent.getStringExtra(EXTRA_PHOTO_PATH)
|
|
|
+ if (path != null) {
|
|
|
+ showPhoto(path)
|
|
|
+ }
|
|
|
+ // 拍完照等待5秒后显示结果
|
|
|
+ startResultCountdown()
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 等待 5 秒后随机显示合格/不合格结果 */
|
|
|
+ private fun startResultCountdown(seconds: Long = 5) {
|
|
|
+ binding.tvTaskHeader.text = "识别中,请稍后..."
|
|
|
+ resultCountdown?.cancel()
|
|
|
+ resultCountdown = object : CountDownTimer(seconds * 1000, 1000) {
|
|
|
+ override fun onTick(millisUntilFinished: Long) {}
|
|
|
+ override fun onFinish() {
|
|
|
+ status = Random.nextBoolean()
|
|
|
+ runOnUiThread { updateResultDisplay() }
|
|
|
+ }
|
|
|
+ }.start()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun updateResultDisplay() {
|
|
|
+ binding.tvTaskHeader.text = if (status) "检验结果:合格!" else "检验结果:不合格!"
|
|
|
+ binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun retake() {
|
|
|
+ binding.tvTaskHeader.text = "重新拍照中,请稍后..."
|
|
|
+ takePhoto()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun continueTask() {
|
|
|
+ binding.tvTaskHeader.text = "拍照中,请稍后..."
|
|
|
+ takePhoto()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun endTask() {
|
|
|
+ // 随机进入单证缺失或单证齐全
|
|
|
+ if (Random.nextBoolean()) {
|
|
|
+ missingLauncher.launch(Intent(this, InspectionMissingActivity::class.java))
|
|
|
+ } else {
|
|
|
+ goComplete()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun goComplete() {
|
|
|
+ val photoCount = SprayingPhotoManager.getPhotoCount()
|
|
|
+ SprayingPhotoManager.clear()
|
|
|
+ startActivity(Intent(this, InspectionCompleteActivity::class.java).apply {
|
|
|
+ putExtra(InspectionCompleteActivity.EXTRA_PHOTO_COUNT, photoCount)
|
|
|
+ })
|
|
|
+ finish()
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---- 拍照 ----
|
|
|
+
|
|
|
+ private fun takePhoto() {
|
|
|
+ val fileName = "inspection_${System.currentTimeMillis()}.png"
|
|
|
+ val file = File(
|
|
|
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
|
|
|
+ fileName
|
|
|
+ )
|
|
|
+ GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_480P, file.absolutePath)
|
|
|
+ }
|
|
|
+
|
|
|
+ private val photoCallbackId = UUID.randomUUID().toString()
|
|
|
+
|
|
|
+ private val mPhotoFileCallback = object : PhotoFileCallback.Stub() {
|
|
|
+ override fun onTakePhoto(path: String) {
|
|
|
+ LogHelper.d("onTakePhoto: $path")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun getCallbackId(): String = photoCallbackId
|
|
|
+
|
|
|
+ override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
|
|
|
+ if (path == null) {
|
|
|
+ runOnUiThread {
|
|
|
+ binding.tvTaskHeader.text = "相机异常,请重试"
|
|
|
+ }
|
|
|
+ "相机异常".showMessage()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ SprayingPhotoManager.addPhoto(path)
|
|
|
+ runOnUiThread {
|
|
|
+ showPhoto(path)
|
|
|
+ // 重拍/继续任务:等待3秒后刷新结果
|
|
|
+ startResultCountdown(3)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun showPhoto(path: String) {
|
|
|
+ binding.iv.doOnLayout {
|
|
|
+ val w = it.width.coerceAtLeast(1)
|
|
|
+ val h = it.height.coerceAtLeast(1)
|
|
|
+ imageDecodeExecutor.execute {
|
|
|
+ val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, w, h)
|
|
|
+ runOnUiThread {
|
|
|
+ if (!isFinishing && !isDestroyed) {
|
|
|
+ binding.iv.setImageBitmap(bitmap)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---- 生命周期 ----
|
|
|
+
|
|
|
+ override fun onResume() {
|
|
|
+ super.onResume()
|
|
|
+ OfflineCmdServiceHelper.addListenerInspectionResult()
|
|
|
+ OfflineCmdServiceHelper.addOnLineListener(listener)
|
|
|
+ GlassMediaServiceHelper.addPhotoCallback(mPhotoFileCallback)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onPause() {
|
|
|
+ super.onPause()
|
|
|
+ resultCountdown?.cancel()
|
|
|
+ OfflineCmdServiceHelper.removeListenerInspectionResult()
|
|
|
+ OfflineCmdServiceHelper.removeOnLineListener(listener)
|
|
|
+ GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDestroy() {
|
|
|
+ super.onDestroy()
|
|
|
+ binding.iv.setImageDrawable(null)
|
|
|
+ window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---- Adapter ----
|
|
|
+
|
|
|
+ private val adapter = object : CommonPagedAdapter<ItemItem>(R.layout.item_manual_result_action) {
|
|
|
+ override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
|
|
|
+ holder.setText(R.id.text, item.text)
|
|
|
+ .setClickListener(R.id.actionRoot) {
|
|
|
+ when (item.text) {
|
|
|
+ "重拍照" -> retake()
|
|
|
+ "结束任务" -> endTask()
|
|
|
+ "继续任务" -> continueTask()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun adapter(): BasePagedAdapter<ItemItem> = adapter
|
|
|
+}
|