Forráskód Böngészése

feat(spraying): 添加喷涂功能的拍照和OCR识别支持

- 在OfflineCmdServiceHelper中新增喷涂相关的语音命令
- 为InspectionActivity、ReviewActivity和SprayingActivity添加屏幕常亮功能
- 新增SprayingOCRActivity用于OCR识别和图像显示
- 实现拍照功能,包括语音控制拍照和手动点击拍照
- 集成GlassSdk媒体服务进行照片拍摄和回调处理
- 添加照片预览和重拍功能
- 更新布局文件以支持拍照提示和图像显示
- 移除MainActivity并将启动目标改为SprayingOCRActivity
- 清理WelcomeActivity中的调试日志输出
徐勤民 2 napja
szülő
commit
989ce90cff

+ 1 - 1
app/src/main/AndroidManifest.xml

@@ -82,7 +82,7 @@
             android:name=".ui.SprayingActivity"
             android:exported="false" />
         <activity
-            android:name=".ui.MainActivity"
+            android:name=".ui.SprayingOCRActivity"
             android:exported="false" />
         <activity
             android:name=".ui.WelcomeActivity"

+ 9 - 0
app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt

@@ -137,6 +137,15 @@ object OfflineCmdServiceHelper {
         add(OfflineCmdBean("打开第十项任务", "da kai di shi xiang ren wu"))
         add(OfflineCmdBean("处理第十条任务", "chu li di shi tiao ren wu"))
         add(OfflineCmdBean("处理第十项任务", "chu li di shi xiang ren wu"))
+
+        //喷涂
+        add(OfflineCmdBean("开始", "kai shi"))
+        add(OfflineCmdBean("开始拍照", "kai shi pai zhao"))
+        add(OfflineCmdBean("拍照", "pai zhao"))
+        add(OfflineCmdBean("开始任务", "kai shi ren wu"))
+        add(OfflineCmdBean("重拍", "chong pai"))
+        add(OfflineCmdBean("重新拍", "chong xin pai"))
+        add(OfflineCmdBean("再拍一次", "zai pai yi ci"))
     }
     fun init(){
         val service = GlassSdk.getGlassOfflineCmdService()

+ 1 - 0
app/src/main/java/com/nova/brain/glass/ui/InspectionActivity.kt

@@ -37,6 +37,7 @@ class InspectionActivity : BaseListFormLayoutNormalActivity<ItemItem, ItemListVM
     }
     override fun initData() {
         super.initData()
+        window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
         OfflineCmdServiceHelper.addOnLineListener(listener)
     }
 

+ 0 - 22
app/src/main/java/com/nova/brain/glass/ui/MainActivity.kt

@@ -1,22 +0,0 @@
-package com.nova.brain.glass.ui
-
-import android.os.Bundle
-import androidx.activity.viewModels
-import com.nova.brain.glass.R
-import com.nova.brain.glass.databinding.ActivityMainBinding
-import com.nova.brain.glass.viewmodel.MainVM
-import com.xuqm.base.ui.BaseActivity
-
-class MainActivity : BaseActivity<ActivityMainBinding>() {
-    override fun fullscreen(): Boolean = true
-    override fun getLayoutId(): Int = R.layout.activity_main
-
-    private val vm: MainVM by viewModels()
-
-    override fun initView(savedInstanceState: Bundle?) {
-        super.initView(savedInstanceState)
-
-
-    }
-
-}

+ 1 - 0
app/src/main/java/com/nova/brain/glass/ui/ReviewActivity.kt

@@ -37,6 +37,7 @@ class ReviewActivity : BaseListFormLayoutNormalActivity<ItemItem, ItemListVM, Ac
     }
     override fun initData() {
         super.initData()
+        window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
         OfflineCmdServiceHelper.addOnLineListener(listener)
     }
 

+ 76 - 3
app/src/main/java/com/nova/brain/glass/ui/SprayingActivity.kt

@@ -1,19 +1,29 @@
 package com.nova.brain.glass.ui
 
+import android.content.Intent
+import android.graphics.BitmapFactory
+import android.os.Environment
 import androidx.recyclerview.widget.RecyclerView
 import com.nova.brain.glass.R
 import com.nova.brain.glass.databinding.ActivitySprayingBinding
 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.ItemListVM
 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 SprayingActivity : BaseListFormLayoutNormalActivity<ItemItem, SprayingVM, ActivitySprayingBinding>() {
+class SprayingActivity :
+    BaseListFormLayoutNormalActivity<ItemItem, SprayingVM, ActivitySprayingBinding>() {
     override fun getLayoutId(): Int = R.layout.activity_spraying
     override fun fullscreen(): Boolean = true
 
@@ -26,28 +36,91 @@ class SprayingActivity : BaseListFormLayoutNormalActivity<ItemItem, SprayingVM,
                     "退出", "返回", "退回" -> {
                         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@SprayingActivity, 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(android.view.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()
                         }
                     }
                 }

+ 129 - 0
app/src/main/java/com/nova/brain/glass/ui/SprayingOCRActivity.kt

@@ -0,0 +1,129 @@
+package com.nova.brain.glass.ui
+
+import android.R.attr.path
+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.ActivitySprayingOcrBinding
+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.FileHelper
+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 SprayingOCRActivity :
+    BaseListFormLayoutNormalActivity<ItemItem, SprayingVM, ActivitySprayingOcrBinding>() {
+    override fun getLayoutId(): Int = R.layout.activity_spraying_ocr
+    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 {
+                runOnUiThread {
+                    binding.hint.text = "单击或语音输入“重拍”,可重新拍摄"
+                    binding.content.setImageBitmap(BitmapFactory.decodeFile(path))
+                }
+            }
+        }
+    }
+
+
+    override fun initData() {
+        super.initData()
+        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+        OfflineCmdServiceHelper.addOnLineListener(listener)
+        GlassSdk.getGlassMediaService()?.addPhotoCallback(mPhotoFileCallback)
+        intent.getStringExtra("path")?.apply {
+            binding.content.setImageBitmap(BitmapFactory.decodeFile(this))
+        }
+    }
+
+    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 - 2
app/src/main/java/com/nova/brain/glass/ui/WelcomeActivity.kt

@@ -39,13 +39,11 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
 
     override fun onResume() {
         super.onResume()
-        LogHelper.d(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
         OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
     }
 
     override fun onPause() {
         super.onPause()
-        LogHelper.d("---------------------------")
         OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener)
     }
 

+ 8 - 0
app/src/main/res/layout/activity_spraying.xml

@@ -94,6 +94,7 @@
         <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"
@@ -102,6 +103,13 @@
             android:text="单击或语音输入“开始”,进入下一步"
             android:textColor="#ff40FF5E"
             android:textSize="14sp"/>
+        <ImageView
+            android:layout_width="120dp"
+            android:id="@+id/iv"
+            android:layout_height="150dp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/hint"/>
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>

+ 58 - 0
app/src/main/res/layout/activity_spraying_ocr.xml

@@ -0,0 +1,58 @@
+<?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" />
+
+        <ImageView
+            android:layout_width="120dp"
+            android:id="@+id/content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="12dp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/tvTaskHeader"/>
+
+        <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>

+ 0 - 5
app/src/main/res/layout/activity_welcome.xml

@@ -8,18 +8,13 @@
             android:id="@+id/tv"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:background="@color/app_color_black"
-            android:layout_alignParentTop="true"
             android:textColor="#ff3FFF5F"
             android:textSize="19sp"
             android:text="您可以说:Nova,我的任务有哪些?"
-            android:fontFamily="Source Han Sans"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            android:gravity="left|top"
-            android:alpha="1"
             />
 
     </androidx.constraintlayout.widget.ConstraintLayout>