feat(glass): 添加喷洒检测手动结果修改功能

- 在OfflineCmdServiceHelper中新增合格/不合格相关语音命令
- 将SprayingResultActivity中的离线命令监听器生命周期从onDestroy移至onResume/onPause
- 新增SprayingManualResultActivity用于手动选择检测结果
- 新增SprayingManualResultVM作为手动结果页面的数据模型
- 添加activity_spraying_manual_result和item_manual_result_action布局文件
- 实现手动结果选择的Activity Result回调处理逻辑
- 在AndroidManifest.xml中注册新的手动结果Activity
这个提交包含在:
徐勤民 2026-04-14 22:33:52 +08:00
父节点 daa92ba0e1
当前提交 3270625e09
共有 12 个文件被更改,包括 249 次插入29 次删除

查看文件

@ -87,6 +87,9 @@
<activity <activity
android:name=".ui.SprayingResultActivity" android:name=".ui.SprayingResultActivity"
android:exported="false" /> android:exported="false" />
<activity
android:name=".ui.SprayingManualResultActivity"
android:exported="false" />
<activity <activity
android:name=".ui.WelcomeActivity" android:name=".ui.WelcomeActivity"
android:exported="true" android:exported="true"

查看文件

@ -34,6 +34,14 @@ object OfflineCmdServiceHelper {
add(OfflineCmdBean("不同意", "bu tong yi")) add(OfflineCmdBean("不同意", "bu tong yi"))
add(OfflineCmdBean("拒绝", "ju jue")) add(OfflineCmdBean("拒绝", "ju jue"))
add(OfflineCmdBean("通过", "tong guo")) add(OfflineCmdBean("通过", "tong guo"))
add(OfflineCmdBean("合格", "he ge"))
add(OfflineCmdBean("不合格", "bu he ge"))
add(OfflineCmdBean("改为合格", "gai wei he ge"))
add(OfflineCmdBean("改为不合格", "gai wei bu he ge"))
add(OfflineCmdBean("设置为合格", "she zhi wei he ge"))
add(OfflineCmdBean("设置为不合格", "she zhi wei bu he ge"))
add(OfflineCmdBean("取消修改", "qu xiao xiu gai"))
add(OfflineCmdBean("取消", "qu xiao"))
add(OfflineCmdBean("查看第一条任务", "cha kan di yi tiao ren wu")) add(OfflineCmdBean("查看第一条任务", "cha kan di yi tiao ren wu"))
add(OfflineCmdBean("查看第一项任务", "cha kan di yi xiang ren wu")) add(OfflineCmdBean("查看第一项任务", "cha kan di yi xiang ren wu"))

查看文件

@ -25,8 +25,9 @@ class FoActivity : BaseActivity<ActivityFoBinding>() {
OfflineCmdServiceHelper.addOnLineListener(listener) OfflineCmdServiceHelper.addOnLineListener(listener)
} }
override fun onDestroy() {
super.onDestroy() override fun onPause() {
super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
} }
} }

查看文件

@ -38,11 +38,15 @@ class InspectionActivity : BaseListFormLayoutNormalActivity<ItemItem, ItemListVM
override fun initData() { override fun initData() {
super.initData() super.initData()
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onResume() {
super.onResume()
OfflineCmdServiceHelper.addOnLineListener(listener) OfflineCmdServiceHelper.addOnLineListener(listener)
} }
override fun onDestroy() { override fun onPause() {
super.onDestroy() super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
} }

查看文件

@ -98,12 +98,16 @@ class SprayingActivity :
override fun initData() { override fun initData() {
super.initData() super.initData()
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
OfflineCmdServiceHelper.addOnLineListener(listener)
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
} }
override fun onDestroy() { override fun onResume() {
super.onDestroy() super.onResume()
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
OfflineCmdServiceHelper.addOnLineListener(listener)
}
override fun onPause() {
super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback) GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback)
} }

查看文件

@ -0,0 +1,74 @@
package com.nova.brain.glass.ui
import android.app.Activity
import android.content.Intent
import androidx.recyclerview.widget.RecyclerView
import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivitySprayingManualResultBinding
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.viewmodel.SprayingManualResultVM
import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter
import com.xuqm.base.adapter.ViewHolder
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
class SprayingManualResultActivity :
BaseListFormLayoutNormalActivity<ItemItem, SprayingManualResultVM, ActivitySprayingManualResultBinding>() {
override fun getLayoutId(): Int = R.layout.activity_spraying_manual_result
override fun fullscreen(): Boolean = true
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) {
runOnUiThread {
when (cmd) {
"合格", "改为合格", "设置为合格" -> chooseResult(RESULT_PASS)
"不合格", "改为不合格", "设置为不合格" -> chooseResult(RESULT_FAIL)
"取消", "取消修改", "返回", "退回", "退出" -> finish()
}
}
}
}
override fun initData() {
super.initData()
OfflineCmdServiceHelper.addOnLineListener(listener)
}
override fun onDestroy() {
super.onDestroy()
OfflineCmdServiceHelper.removeOnLineListener(listener)
}
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) {
"合格" -> chooseResult(RESULT_PASS)
"不合格" -> chooseResult(RESULT_FAIL)
"取消" -> finish()
}
}
}
}
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
private fun chooseResult(result: String) {
setResult(Activity.RESULT_OK, Intent().apply {
putExtra(EXTRA_MANUAL_RESULT, result)
})
finish()
}
companion object {
const val EXTRA_MANUAL_RESULT = "extra_manual_result"
const val RESULT_PASS = "pass"
const val RESULT_FAIL = "fail"
}
}

查看文件

@ -97,15 +97,19 @@ class SprayingOCRActivity :
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)
OfflineCmdServiceHelper.addOnLineListener(listener)
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
intent.getStringExtra("path")?.apply { intent.getStringExtra("path")?.apply {
showPhoto(this) showPhoto(this)
} }
} }
override fun onDestroy() { override fun onResume() {
super.onDestroy() super.onResume()
OfflineCmdServiceHelper.addOnLineListener(listener)
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
}
override fun onPause() {
super.onPause()
resultCountdown?.cancel() resultCountdown?.cancel()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback) GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback)

查看文件

@ -1,10 +1,12 @@
package com.nova.brain.glass.ui package com.nova.brain.glass.ui
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Paint import android.graphics.Paint
import android.os.Environment import android.os.Environment
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.result.contract.ActivityResultContracts
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.ActivitySprayingResultBinding import com.nova.brain.glass.databinding.ActivitySprayingResultBinding
@ -31,6 +33,24 @@ class SprayingResultActivity :
override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL
private var status = true private var status = true
private val manualResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) {
return@registerForActivityResult
}
when (result.data?.getStringExtra(SprayingManualResultActivity.EXTRA_MANUAL_RESULT)) {
SprayingManualResultActivity.RESULT_PASS -> {
status = true
setStatusImage()
}
SprayingManualResultActivity.RESULT_FAIL -> {
status = false
setStatusImage()
}
}
}
private val listener = object : OfflineCmdListener { private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) { override fun onOfflineCmd(cmd: String) {
runOnUiThread { runOnUiThread {
@ -66,7 +86,7 @@ class SprayingResultActivity :
} }
fun rest() { fun rest() {
manualResultLauncher.launch(Intent(this, SprayingManualResultActivity::class.java))
} }
private val photoCallbackId = UUID.randomUUID().toString() private val photoCallbackId = UUID.randomUUID().toString()
@ -108,31 +128,42 @@ class SprayingResultActivity :
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)
OfflineCmdServiceHelper.addOnLineListener(listener)
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
intent.getStringExtra("path")?.apply { intent.getStringExtra("path")?.apply {
binding.iv.setImageBitmap(BitmapFactory.decodeFile(this)) binding.iv.setImageBitmap(BitmapFactory.decodeFile(this))
setStatusImage() setStatusImage()
} }
} }
fun setStatusImage(){
binding.tvTaskHeader.text = if (status) "OCR识别结果合格" else "OCR识别结果不合格" fun setStatusImage() {
binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false) binding.tvTaskHeader.text = if (status) "OCR识别结果合格" else "OCR识别结果不合格"
if (status){ binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false)
binding.value1.paintFlags = binding.value1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() if (status) {
binding.value2.paintFlags = binding.value2.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() binding.value1.paintFlags =
binding.value3.paintFlags = binding.value3.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() binding.value1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}else{ binding.value2.paintFlags =
binding.value1.paintFlags = binding.value1.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG binding.value2.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
binding.value2.paintFlags = binding.value2.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG binding.value3.paintFlags =
binding.value3.paintFlags = binding.value3.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG binding.value3.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
} else {
binding.value1.paintFlags = binding.value1.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
binding.value2.paintFlags = binding.value2.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
binding.value3.paintFlags = binding.value3.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
}
} }
}
override fun onDestroy() { override fun onResume() {
super.onDestroy() super.onResume()
OfflineCmdServiceHelper.addOnLineListener(listener)
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
}
override fun onPause() {
super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback) GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback)
} }
override fun onDestroy() {
super.onDestroy()
}
private var isPhoto = false private var isPhoto = false
private val adapter = object : CommonPagedAdapter<ItemItem>(R.layout.item_menu) { private val adapter = object : CommonPagedAdapter<ItemItem>(R.layout.item_menu) {

查看文件

@ -172,6 +172,7 @@ class TaskListActivity :
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
LogHelper.d(">>>>>>>>>>>>--------------------")
OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener) OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
} }

查看文件

@ -0,0 +1,20 @@
package com.nova.brain.glass.viewmodel
import com.nova.brain.glass.model.ItemItem
import com.xuqm.base.viewmodel.BaseListViewModel
import com.xuqm.base.viewmodel.callback.Response
class SprayingManualResultVM : BaseListViewModel<ItemItem>() {
override fun loadData(
page: Int,
onResponse: Response<ItemItem>
) {
onResponse.onResponse(
arrayListOf<ItemItem>().apply {
add(ItemItem("合格"))
add(ItemItem("不合格"))
add(ItemItem("取消"))
}
)
}
}

查看文件

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_color_black">
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:gravity="center"
android:text="手动更改结果"
android:textColor="#4AFE59"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/baseRecyclerView"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:clipToPadding="false"
android:overScrollMode="never"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
<TextView
android:id="@+id/hint"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginEnd="28dp"
android:layout_marginBottom="56dp"
android:gravity="center"
android:lineSpacingExtra="6dp"
android:text="单击或语音输入“合格”,检测结果改为合格&#10;单击或语音输入“不合格”,检测结果改为不合格&#10;单击或语音输入“取消”返回上级页面"
android:textColor="#4AFE59"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

查看文件

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actionRoot"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_marginBottom="18dp"
android:background="@drawable/bg_item"
android:foreground="?attr/selectableItemBackground"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="#4AFE59"
android:textSize="20sp" />
</FrameLayout>