feat(api): 新增V2版本接口支持并集成至网络请求客户端
- 新增 ApiServiceV2 接口,支持人脸缓存、增量数据、设备配置等接口 - ApiClient 中新增 apiServiceV2 对象,复用 Retrofit 实例,调整超时时间至60秒 - DeviceInitActivity 改用 netViewModelV2 进行人脸缓存全量拉取及设备配置读取 - BaseActivity 新增对人脸增量同步接口调用,调用成功后刷新本地识别缓存 - BaseActivity 新增清空本地人脸库功能,异步清理数据库并刷新识别缓存 - FaceApi 增加清空本地人脸库接口,重写数据库操作逻辑 - 升级 lib_face 模块 Room 数据库版本,新增字段以支持多标识人脸实体扩展 - FaceEntity 实体扩展会员编号、用户ID、人脸ID、会员标识、更新时间等字段 - FaceDao 新增按人脸ID查询和删除接口,支持多重人脸数据操作 - 优化网络层 OkHttpClient 配置,简化拦截器写法及日志级别判断 - 升级 lib_face 模块支持 arm64-v8a 架构,增强兼容性 - 规范模块间依赖关系,统一版本管理及包路径声明 - 完善 CLAUDE.md 文档,补充项目架构、模块划分与开发流程说明
This commit is contained in:
@@ -17,11 +17,9 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.sw.inbound.utils.DateTimeUtils
|
||||
import com.sw.plate.utils.Base64
|
||||
import com.sw.plate.utils.ScanGunKeyEventHelper
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
||||
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
import com.sw.plate.utils.comn.SerialApi
|
||||
import com.sw.plate.utils.comn.SerialPortManager
|
||||
@@ -30,17 +28,18 @@ import com.sw.platecabinet.member.databinding.ItemTitleTimeBinding
|
||||
import com.sw.platecabinet.dialog.BalanceNotEnoughDialog
|
||||
import com.sw.platecabinet.ext.setClickListeners
|
||||
import com.sw.platecabinet.model.response.EquipmentUserInfo
|
||||
import com.sw.platecabinet.model.response.UserFaceModel
|
||||
import com.sw.platecabinet.utils.IntervalExecutor
|
||||
import com.sw.platecabinet.utils.PermissionHelper
|
||||
import com.sw.platecabinet.utils.SpTool
|
||||
import com.sw.platecabinet.view.CustomLoadingDialog
|
||||
import com.sw.platecabinet.viewmodel.NetViewModelV2
|
||||
import com.sw.platecabinet.viewmodel.SettingViewModel
|
||||
import com.sw.platecabinet.viewmodel.UserViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
@@ -61,6 +60,9 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
// 用户对应的viewModel
|
||||
protected val viewModel by viewModels<UserViewModel>()
|
||||
|
||||
// V2 网络请求 viewModel(人脸缓存/增量同步/设备配置)
|
||||
val netViewModelV2 by viewModels<NetViewModelV2>()
|
||||
|
||||
private var startTime: Long = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -84,8 +86,6 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
registerKeyEvent()
|
||||
val durationTime = System.currentTimeMillis() - startTime
|
||||
Timber.d("启动时间:$durationTime")
|
||||
|
||||
startFaceTask()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,6 +396,9 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
// private val dealyMillis = 10 * 60 * 1000L
|
||||
private val initialDelay = 5 * 60 * 1000L
|
||||
private val dealyMillis = 5 * 60 * 1000L
|
||||
|
||||
val recognizeViewModel by viewModels<RecognizeViewModel>()
|
||||
|
||||
fun startFaceTask() {
|
||||
faceTaskJob =
|
||||
intervalExecutor.startIntervalTaskWithInitialDelay(initialDelay, dealyMillis) {
|
||||
@@ -403,70 +406,33 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private var faceTimestamp = 0L
|
||||
|
||||
/**
|
||||
* 人脸增量同步(V2,同步逻辑在 NetViewModelV2 内部处理)
|
||||
*/
|
||||
private fun getFaceIncrementList(pageNo: Int = 1) {
|
||||
val timestamp = SpTool.getLastFaceTimestamp()
|
||||
if (timestamp == 0L) {
|
||||
return
|
||||
}
|
||||
settingViewModel.getFaceIncrementList(
|
||||
netViewModelV2.getFaceIncrementList(
|
||||
pageNo = pageNo,
|
||||
timestamp = timestamp
|
||||
) { list ->
|
||||
runOnUiThread {
|
||||
if (pageNo == 1 && list.isEmpty()) {
|
||||
//未查询到增量数据
|
||||
return@runOnUiThread
|
||||
}
|
||||
updateFaceData(list)
|
||||
// if (list.size >= settingViewModel.PAGE_SIZE) {
|
||||
// faceTimestamp = list.last().faceUpdateTimestamp?:0
|
||||
// taskPageNo++
|
||||
// getFaceIncrementList()
|
||||
// return@runOnUiThread
|
||||
// }
|
||||
if (list.isNotEmpty()) {
|
||||
faceTimestamp = list.last().faceUpdateTimestamp?:0
|
||||
}
|
||||
SpTool.setLastFaceTimestamp(faceTimestamp)
|
||||
}
|
||||
) {
|
||||
recognizeViewModel.refreshFaceList()
|
||||
}
|
||||
}
|
||||
|
||||
private val recognizeViewModel by viewModels<RecognizeViewModel>()
|
||||
private fun updateFaceData(list: List<UserFaceModel>) {
|
||||
Thread {
|
||||
val faceList = mutableListOf<FaceEntity>()
|
||||
try {
|
||||
list.forEach { model ->
|
||||
if (model.faceDeleted == true) {
|
||||
//删除数据
|
||||
FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId)
|
||||
} else {
|
||||
//保存数据
|
||||
val faceEntity = FaceEntity(
|
||||
model.userId,
|
||||
null,
|
||||
Base64.decode(model.faceFeatureStr)
|
||||
).also {
|
||||
it.userType = "1"
|
||||
}
|
||||
faceList.add(faceEntity)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
try {
|
||||
if (faceList.isNotEmpty()) {
|
||||
FaceDatabase.getInstance(this).faceDao().insert(faceList)
|
||||
}
|
||||
recognizeViewModel.refreshFaceList()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}.start()
|
||||
/**
|
||||
* 清空本地人脸库
|
||||
*/
|
||||
fun clearAllFace(block: () -> Unit) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val faceDao = FaceDatabase.getInstance(this@BaseActivity).faceDao()
|
||||
faceDao.deleteAll()
|
||||
faceDao.resetId()
|
||||
recognizeViewModel.refreshFaceList()
|
||||
withContext(Dispatchers.Main) { block() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user