feat(ui): 添加喷洒结果页面功能
- 创建了 SprayingResultActivity 类用于显示喷洒结果界面 - 实现了语音控制功能,支持"退出"、"返回"、"拍照"等语音指令 - 集成了拍照功能,使用 GlassSdk 进行照片拍摄和处理 - 添加了照片回调处理逻辑,支持照片拍摄成功后的 OCR 识别跳转 - 实现了屏幕常亮和离线命令监听功能 - 创建了 activity_spraying_result.xml 布局文件 - 设计了包含任务标题、图片预览和操作按钮的用户界面 - 配置了 RecyclerView 用于显示拍照操作项列表
@ -0,0 +1,133 @@
|
||||
package com.nova.brain.glass.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Environment
|
||||
import android.view.WindowManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.nova.brain.glass.R
|
||||
import com.nova.brain.glass.databinding.ActivitySprayingBinding
|
||||
import com.nova.brain.glass.databinding.ActivitySprayingResultBinding
|
||||
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.SprayingVM
|
||||
import com.rokid.security.glass3.open.sdk.GlassSdk
|
||||
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
|
||||
|
||||
class SprayingResultActivity :
|
||||
BaseListFormLayoutNormalActivity<ItemItem, SprayingVM, ActivitySprayingResultBinding>() {
|
||||
override fun getLayoutId(): Int = R.layout.activity_spraying_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) {
|
||||
"退出", "返回", "退回" -> {
|
||||
finish()
|
||||
}
|
||||
|
||||
"开始", "拍照", "开始拍照", "开始任务" -> {
|
||||
runOnUiThread {
|
||||
binding.hint.text = "拍照中,请稍后..."
|
||||
}
|
||||
isPhoto = true
|
||||
takePhoto()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun takePhoto() {
|
||||
val fileName = "test_${System.currentTimeMillis()}.png"
|
||||
val publicPicturesDir =
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
||||
val file = File(publicPicturesDir, fileName)
|
||||
GlassSdk.getGlassMediaService()
|
||||
?.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 = $path")
|
||||
}
|
||||
|
||||
override fun getCallbackId(): String {
|
||||
return photoCallbackId
|
||||
}
|
||||
|
||||
override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
|
||||
LogHelper.d("width:$width--height:$height")
|
||||
if (path == null) {
|
||||
if (isPhoto) {
|
||||
isPhoto = false
|
||||
takePhoto()
|
||||
} else {
|
||||
runOnUiThread {
|
||||
binding.hint.text = "单击或语音输入“开始”,进入下一步"
|
||||
}
|
||||
"相机异常".showMessage()
|
||||
}
|
||||
} else {
|
||||
startActivity(Intent(this@SprayingResultActivity, SprayingOCRActivity::class.java).apply {
|
||||
putExtra("path", path)
|
||||
})
|
||||
finish()
|
||||
// runOnUiThread {
|
||||
// binding.hint.text = "单击或语音输入“开始”,进入下一步"
|
||||
// binding.iv.setImageBitmap(BitmapFactory.decodeFile(path))
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
OfflineCmdServiceHelper.addOnLineListener(listener)
|
||||
GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
OfflineCmdServiceHelper.removeOnLineListener(listener)
|
||||
GlassSdk.getGlassMediaService()?.removePhotoCallback(mPhotoFileCallback)
|
||||
}
|
||||
|
||||
private var isPhoto = false
|
||||
private val adapter = object : CommonPagedAdapter<ItemItem>(R.layout.item_photo) {
|
||||
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
|
||||
holder
|
||||
.setClickListener(R.id.photo) {
|
||||
when (item.text) {
|
||||
"拍照" -> {
|
||||
runOnUiThread {
|
||||
binding.hint.text = "拍照中,请稍后..."
|
||||
}
|
||||
isPhoto = true
|
||||
takePhoto()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
<?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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/app_color_black">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTaskHeader"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="67dp"
|
||||
android:background="@drawable/bg_item"
|
||||
android:text="OCR识别结果:合格"
|
||||
android:gravity="center"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvTaskHeader">
|
||||
|
||||
<LinearLayout
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="30dp"
|
||||
android:gravity="center|left"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_width="400dp"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/bg_task_title_selected"
|
||||
android:layout_height="183dp">
|
||||
<ImageView
|
||||
android:background="@drawable/bg_task_title_selected"
|
||||
android:layout_width="120dp"
|
||||
android:id="@+id/iv"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_height="150dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/hint"/>
|
||||
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_width="90dp"
|
||||
android:src="@mipmap/ocr_true"
|
||||
android:layout_height="90dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/baseRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="88dp"
|
||||
android:clipToPadding="false"
|
||||
android:layout_marginTop="12dp"
|
||||
android:overScrollMode="never"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/content" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginStart="15dp"
|
||||
android:id="@+id/hint"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:gravity="center"
|
||||
android:text="单击或语音输入“开始”,进入下一步"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
|
之后 宽度: | 高度: | 大小: 694 B |
|
之后 宽度: | 高度: | 大小: 7.0 KiB |
|
之后 宽度: | 高度: | 大小: 442 B |
|
之后 宽度: | 高度: | 大小: 1.1 KiB |
|
之后 宽度: | 高度: | 大小: 6.6 KiB |
|
之后 宽度: | 高度: | 大小: 458 B |
|
之后 宽度: | 高度: | 大小: 3.6 KiB |
|
之后 宽度: | 高度: | 大小: 274 B |
|
之后 宽度: | 高度: | 大小: 574 B |
|
之后 宽度: | 高度: | 大小: 3.4 KiB |
|
之后 宽度: | 高度: | 大小: 754 B |
|
之后 宽度: | 高度: | 大小: 9.1 KiB |
|
之后 宽度: | 高度: | 大小: 490 B |
|
之后 宽度: | 高度: | 大小: 1.4 KiB |
|
之后 宽度: | 高度: | 大小: 8.5 KiB |
|
之后 宽度: | 高度: | 大小: 1.4 KiB |
|
之后 宽度: | 高度: | 大小: 18 KiB |
|
之后 宽度: | 高度: | 大小: 830 B |
|
之后 宽度: | 高度: | 大小: 2.6 KiB |
|
之后 宽度: | 高度: | 大小: 17 KiB |
|
之后 宽度: | 高度: | 大小: 1.4 KiB |
|
之后 宽度: | 高度: | 大小: 22 KiB |
|
之后 宽度: | 高度: | 大小: 950 B |
|
之后 宽度: | 高度: | 大小: 3.3 KiB |
|
之后 宽度: | 高度: | 大小: 20 KiB |
|
之后 宽度: | 高度: | 大小: 2.1 KiB |