feat(ocr): 添加喷涂任务OCR识别功能
- 新增BatchUploadResponse、RecognizeByPathRequest、OcrResultData和RecognizeByPathResponse数据类 - 在Service中添加batchUpload接口返回类型修改和recognizeByPath新接口 - 修改SprayingOCRActivity从观察uploadSuccessPath改为观察ocrResult并传递识别结果参数 - 移除SprayingResultActivity中图片解码相关代码和依赖,新增OCR结果显示逻辑 - 修改SprayingOCRVM中上传成功后的处理流程,增加OCR识别步骤和结果处理 - 在MyApplication中新增appComponent3用于OCR服务组件管理
这个提交包含在:
父节点
3dfd8494e9
当前提交
931dd43fe5
@ -22,6 +22,7 @@ public class MyApplication extends App {
|
||||
public static AppComponent appComponent1;
|
||||
// 喷涂
|
||||
public static AppComponent appComponent2;
|
||||
public static AppComponent appComponent3;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@ -29,9 +30,11 @@ public class MyApplication extends App {
|
||||
appComponent = HttpManager.getAppComponent(baseUrl, new HeaderInterceptor(getApplicationContext()));
|
||||
appComponent1 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||
appComponent2 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||
appComponent3 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||
|
||||
// appComponent1 = HttpManager.getAppComponent("http://192.168.6.20:12119", new HeaderInterceptor(getApplicationContext()));
|
||||
// appComponent2 = HttpManager.getAppComponent("http://192.168.6.156:10085", new HeaderInterceptor(getApplicationContext()));
|
||||
// appComponent3 = HttpManager.getAppComponent("http://192.168.22.125:8820/", new HeaderInterceptor(getApplicationContext()));
|
||||
|
||||
initSdk();
|
||||
|
||||
|
||||
@ -10,3 +10,25 @@ data class SubmitTaskResponse(
|
||||
val data: Any? = null
|
||||
)
|
||||
|
||||
data class BatchUploadResponse(
|
||||
val code: Int,
|
||||
val message: String,
|
||||
val data: String? = null
|
||||
)
|
||||
|
||||
data class RecognizeByPathRequest(
|
||||
val filePath: String
|
||||
)
|
||||
|
||||
data class OcrResultData(
|
||||
val judgment: String = "",
|
||||
val one: String = "",
|
||||
val two: String = ""
|
||||
)
|
||||
|
||||
data class RecognizeByPathResponse(
|
||||
val code: Int,
|
||||
val message: String,
|
||||
val data: OcrResultData? = null
|
||||
)
|
||||
|
||||
|
||||
@ -8,6 +8,10 @@ import com.nova.brain.glass.model.data.BackToRequest
|
||||
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
||||
import com.nova.brain.glass.model.data.GetTaskInfoResponse
|
||||
import com.nova.brain.glass.model.data.RecognizeData
|
||||
import com.nova.brain.glass.model.data.BatchUploadResponse
|
||||
import com.nova.brain.glass.model.data.OcrResultData
|
||||
import com.nova.brain.glass.model.data.RecognizeByPathRequest
|
||||
import com.nova.brain.glass.model.data.RecognizeByPathResponse
|
||||
import com.nova.brain.glass.model.data.SubmitTaskRequest
|
||||
import com.nova.brain.glass.model.data.SubmitTaskResponse
|
||||
import com.nova.brain.glass.model.data.PushToNextData
|
||||
@ -70,7 +74,10 @@ interface Service {
|
||||
|
||||
@Multipart
|
||||
@POST("/skyscopicsecond-api/api/aiGlasses/batchUpload")
|
||||
fun batchUpload(@Part multipartFile: MultipartBody.Part): Observable<ResponseBody>
|
||||
fun batchUpload(@Part multipartFile: MultipartBody.Part): Observable<BatchUploadResponse>
|
||||
|
||||
@POST("/skyscopicsecond-api/api/aiGlasses/recognizeByPath")
|
||||
fun recognizeByPath(@Body body: RecognizeByPathRequest): Observable<RecognizeByPathResponse>
|
||||
|
||||
@POST("/skyscopicsecond-api/api/aiGlasses/submitTask")
|
||||
fun submitTask(@Body body: SubmitTaskRequest): Observable<SubmitTaskResponse>
|
||||
|
||||
@ -115,12 +115,14 @@ class SprayingOCRActivity :
|
||||
message.showMessage()
|
||||
}
|
||||
}
|
||||
viewModel.uploadSuccessPath.observe(this) { path ->
|
||||
if (path.isNullOrBlank()) return@observe
|
||||
viewModel.clearUploadSuccessPath()
|
||||
viewModel.ocrResult.observe(this) { result ->
|
||||
if (result == null) return@observe
|
||||
viewModel.clearOcrResult()
|
||||
startActivity(Intent(this@SprayingOCRActivity, SprayingResultActivity::class.java).apply {
|
||||
putExtra("path", path)
|
||||
putExtra("taskId", taskId)
|
||||
putExtra("judgment", result.judgment)
|
||||
putExtra("one", result.one)
|
||||
putExtra("two", result.two)
|
||||
})
|
||||
finish()
|
||||
}
|
||||
|
||||
@ -10,11 +10,9 @@ import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
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.ActivitySprayingResultBinding
|
||||
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
|
||||
@ -31,7 +29,6 @@ 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.concurrent.Executors
|
||||
import java.util.UUID
|
||||
|
||||
class SprayingResultActivity :
|
||||
@ -45,7 +42,8 @@ class SprayingResultActivity :
|
||||
.orEmpty()
|
||||
.ifBlank { "1493291302287048704" }
|
||||
}
|
||||
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
||||
private var ocrOne: String = ""
|
||||
private var ocrTwo: String = ""
|
||||
private var status = true
|
||||
private var successDialog: AlertDialog? = null
|
||||
private val uiHandler = Handler(Looper.getMainLooper())
|
||||
@ -191,15 +189,19 @@ class SprayingResultActivity :
|
||||
message.showMessage()
|
||||
}
|
||||
}
|
||||
intent.getStringExtra("path")?.apply {
|
||||
showResultImage(this)
|
||||
val judgment = intent.getStringExtra("judgment").orEmpty()
|
||||
ocrOne = intent.getStringExtra("one").orEmpty()
|
||||
ocrTwo = intent.getStringExtra("two").orEmpty()
|
||||
status = judgment != "不合格"
|
||||
setStatusImage()
|
||||
}
|
||||
}
|
||||
|
||||
fun setStatusImage() {
|
||||
binding.tvTaskHeader.text = if (status) "OCR识别结果:合格" else "OCR识别结果:不合格"
|
||||
binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false)
|
||||
binding.value1.text = "识码一:$ocrOne"
|
||||
binding.value2.text = "识码二:$ocrTwo"
|
||||
binding.value3.text = if (status) "两码一致,符合要求!" else "两码不一致,不符合要求!"
|
||||
if (status) {
|
||||
binding.value1.paintFlags =
|
||||
binding.value1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||
@ -272,21 +274,7 @@ class SprayingResultActivity :
|
||||
|
||||
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
|
||||
|
||||
private fun showResultImage(path: String) {
|
||||
binding.iv.doOnLayout {
|
||||
val targetWidth = it.width.coerceAtLeast(1)
|
||||
val targetHeight = it.height.coerceAtLeast(1)
|
||||
imageDecodeExecutor.execute {
|
||||
val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, targetWidth, targetHeight)
|
||||
runOnUiThread {
|
||||
if (isFinishing || isDestroyed) {
|
||||
return@runOnUiThread
|
||||
}
|
||||
binding.iv.setImageBitmap(bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun showSuccessDialogThenBackToTaskList() {
|
||||
successDialog?.dismiss()
|
||||
|
||||
@ -3,6 +3,8 @@ package com.nova.brain.glass.viewmodel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.nova.brain.glass.MyApplication
|
||||
import com.nova.brain.glass.model.ItemItem
|
||||
import com.nova.brain.glass.model.data.OcrResultData
|
||||
import com.nova.brain.glass.model.data.RecognizeByPathRequest
|
||||
import com.nova.brain.glass.repository.Service
|
||||
import com.xuqm.base.di.manager.HttpManager
|
||||
import com.xuqm.base.viewmodel.BaseListViewModel
|
||||
@ -25,7 +27,7 @@ enum class UploadState {
|
||||
class SprayingOCRVM : BaseListViewModel<ItemItem>() {
|
||||
val uploadState = MutableLiveData(UploadState.IDLE)
|
||||
val uploadError = MutableLiveData<String>()
|
||||
val uploadSuccessPath = MutableLiveData<String?>()
|
||||
val ocrResult = MutableLiveData<OcrResultData?>()
|
||||
private var uploadingPath: String? = null
|
||||
private var uploadDisposable: Disposable? = null
|
||||
|
||||
@ -55,10 +57,15 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
||||
.batchUpload(multipartFile)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
.subscribe({ response ->
|
||||
if (uploadingPath != path) return@subscribe
|
||||
uploadState.value = UploadState.SUCCESS
|
||||
uploadSuccessPath.value = path
|
||||
if (response.code == 200 && !response.data.isNullOrBlank()) {
|
||||
uploadState.value = UploadState.IDLE
|
||||
startRecognize(path, response.data)
|
||||
} else {
|
||||
uploadState.value = UploadState.FAILED
|
||||
uploadError.value = if (response.message.isBlank()) "附件上传失败" else response.message
|
||||
}
|
||||
}, { e ->
|
||||
if (uploadingPath != path) return@subscribe
|
||||
uploadState.value = UploadState.FAILED
|
||||
@ -68,6 +75,28 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
||||
add(disposable)
|
||||
}
|
||||
|
||||
private fun startRecognize(localPath: String, serverPath: String) {
|
||||
val disposable = HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||
.recognizeByPath(RecognizeByPathRequest(filePath = serverPath))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
if (uploadingPath != localPath) return@subscribe
|
||||
if (response.code == 200) {
|
||||
uploadState.value = UploadState.SUCCESS
|
||||
ocrResult.value = response.data ?: OcrResultData()
|
||||
} else {
|
||||
uploadState.value = UploadState.FAILED
|
||||
uploadError.value = if (response.message.isBlank()) "OCR识别失败" else response.message
|
||||
}
|
||||
}, { e ->
|
||||
if (uploadingPath != localPath) return@subscribe
|
||||
uploadState.value = UploadState.FAILED
|
||||
uploadError.value = e.message ?: "OCR识别失败"
|
||||
})
|
||||
add(disposable)
|
||||
}
|
||||
|
||||
fun cancelUpload() {
|
||||
uploadingPath = null
|
||||
uploadDisposable?.dispose()
|
||||
@ -77,7 +106,7 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
||||
}
|
||||
}
|
||||
|
||||
fun clearUploadSuccessPath() {
|
||||
uploadSuccessPath.value = null
|
||||
fun clearOcrResult() {
|
||||
ocrResult.value = null
|
||||
}
|
||||
}
|
||||
正在加载...
在新工单中引用
屏蔽一个用户