添加了初始化界面,修复了人脸数据更新后不能识别的问题

This commit is contained in:
zxj
2025-08-07 16:23:21 +08:00
parent 742b3a0775
commit 1f1c3804ac
18 changed files with 509 additions and 70 deletions
+5
View File
@@ -1,3 +1,5 @@
import org.gradle.kotlin.dsl.implementation
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
@@ -104,4 +106,7 @@ dependencies {
implementation(libs.androidx.fragment.ktx) implementation(libs.androidx.fragment.ktx)
// 图片加载 // 图片加载
implementation(libs.glide) implementation(libs.glide)
implementation(libs.core)
implementation(libs.android.core)
} }
+2 -1
View File
@@ -12,8 +12,9 @@ class MyApp : App() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
Timber.plant(Timber.DebugTree()) Timber.plant(Timber.DebugTree())
val deviceId = AppUtil.getUDID(this) var deviceId = AppUtil.getUDID(this)
Timber.d("UDID = ${AppUtil.getUDID(this)}") Timber.d("UDID = ${AppUtil.getUDID(this)}")
deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
GlobalData.deviceId = deviceId GlobalData.deviceId = deviceId
} }
} }
@@ -0,0 +1,84 @@
package com.sw.dualscreen.activity
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.sw.dualscreen.R
import com.sw.dualscreen.view.CustomDialog
import com.sw.dualscreen.viewmodel.BaseViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import timber.log.Timber
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
protected lateinit var binding: VB
protected lateinit var context: Context
private var mDialogWaiting: CustomDialog? = null
private lateinit var viewModel: BaseViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
context = this
//保持亮屏
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding = inflateViewBinding()
setContentView(binding.root)
viewModel = getViewModel()
initialize()
registerDataChange()
}
abstract fun getViewModel(): BaseViewModel
protected abstract fun inflateViewBinding(): VB
open fun initialize() {
}
open fun registerDataChange() {
lifecycleScope.launch {
viewModel.showLoading.collect {
Timber.d("registerDataChange 用户 showLoading = $it")
if (it) {
showWaitingDialog("")
} else {
hideWaitingDialog()
}
}
}
}
/**
* 显示等待提示框
*/
fun showWaitingDialog(tip: String?): Dialog? {
hideWaitingDialog()
val view = View.inflate(this, R.layout.dialog_waiting, null)
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
mDialogWaiting!!.show()
mDialogWaiting!!.setCancelable(true)
return mDialogWaiting
}
/**
* 隐藏等待提示框
*/
fun hideWaitingDialog() {
mDialogWaiting?.dismiss()
mDialogWaiting = null
}
}
@@ -5,35 +5,48 @@ import android.os.Bundle
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.databinding.ActivityInitBinding import com.sw.dualscreen.databinding.ActivityInitBinding
import com.sw.dualscreen.utils.QRCodeUtil
import com.sw.dualscreen.viewmodel.BaseViewModel
import com.sw.dualscreen.viewmodel.DeviceViewModel import com.sw.dualscreen.viewmodel.DeviceViewModel
import com.sw.plate.utils.AppUtil import com.sw.plate.utils.AppUtil
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class InitActivity : AppCompatActivity() { class InitActivity : BaseActivity<ActivityInitBinding>() {
private lateinit var binding: ActivityInitBinding
private val viewModel by viewModels<DeviceViewModel>() private val viewModel by viewModels<DeviceViewModel>()
override fun onCreate(savedInstanceState: Bundle?) { override fun getViewModel(): BaseViewModel {
super.onCreate(savedInstanceState) return viewModel
enableEdgeToEdge() }
binding = ActivityInitBinding.inflate(layoutInflater)
setContentView(binding.root) override fun inflateViewBinding(): ActivityInitBinding {
val deviceId = AppUtil.getUDID(this) return ActivityInitBinding.inflate(layoutInflater)
}
override fun initialize() {
super.initialize()
val isSuccess = viewModel.checkEquipmentInfo() val isSuccess = viewModel.checkEquipmentInfo()
if (isSuccess) { if (isSuccess) {
goMainActivity() goMainActivity()
return
} }
binding.tvDeviceId.text = deviceId binding.imgQr.setImageBitmap(
binding.btConfirm.setOnClickListener { QRCodeUtil.generateQRCode(
content = GlobalData.deviceId,
size = 200
)
)
binding.initButton.setOnClickListener {
viewModel.getDeviceToken() viewModel.getDeviceToken()
} }
registerDataChange()
} }
private fun registerDataChange() { override fun registerDataChange() {
super.registerDataChange()
lifecycleScope.launch { lifecycleScope.launch {
viewModel.deviceInfoResult.drop(1).collect { viewModel.deviceInfoResult.drop(1).collect {
if (it != true) return@collect if (it != true) return@collect
@@ -36,6 +36,8 @@ import com.sw.dualscreen.presentation.SecondaryScreenPresentation
import com.sw.dualscreen.sdk.SensorScaleUtils import com.sw.dualscreen.sdk.SensorScaleUtils
import com.sw.dualscreen.utils.GlideUtils import com.sw.dualscreen.utils.GlideUtils
import com.sw.dualscreen.view.CustomBottomSheetDialog import com.sw.dualscreen.view.CustomBottomSheetDialog
import com.sw.dualscreen.view.CustomDialog
import com.sw.dualscreen.viewmodel.BaseViewModel
import com.sw.dualscreen.viewmodel.UserViewModel import com.sw.dualscreen.viewmodel.UserViewModel
import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
@@ -44,8 +46,7 @@ import timber.log.Timber
import java.io.File import java.io.File
import java.util.concurrent.Executors import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() { class MainActivity : BaseActivity<ActivityMainBinding>() {
private lateinit var binding: ActivityMainBinding
private val viewModel by viewModels<UserViewModel>() private val viewModel by viewModels<UserViewModel>()
private var imageCapture: ImageCapture? = null private var imageCapture: ImageCapture? = null
private var isAnalyzing = true // 控制是否进行图像分析 private var isAnalyzing = true // 控制是否进行图像分析
@@ -59,12 +60,16 @@ class MainActivity : AppCompatActivity() {
private var bottomSheetDialog: CustomBottomSheetDialog? = null private var bottomSheetDialog: CustomBottomSheetDialog? = null
private var lastWeight: Double = 0.0 private var lastWeight: Double = 0.0
override fun onCreate(savedInstanceState: Bundle?) { override fun getViewModel(): BaseViewModel {
super.onCreate(savedInstanceState) return viewModel
enableEdgeToEdge() }
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.main)
override fun inflateViewBinding(): ActivityMainBinding {
return ActivityMainBinding.inflate(layoutInflater)
}
override fun initialize() {
super.initialize()
initView() initView()
setupSecondaryDisplay() setupSecondaryDisplay()
setupCamera() setupCamera()
@@ -94,7 +99,7 @@ class MainActivity : AppCompatActivity() {
val spinnerAdapter = ArrayAdapter<String>( val spinnerAdapter = ArrayAdapter<String>(
this, this,
R.layout.item_for_custom_spinner, R.layout.item_for_custom_spinner,
arrayOf("即放即取", "持续取餐") arrayOf("即放即取", "余量取餐")
) )
binding.spinner.adapter = spinnerAdapter binding.spinner.adapter = spinnerAdapter
binding.spinner.setSelection(0) binding.spinner.setSelection(0)
@@ -105,12 +110,10 @@ class MainActivity : AppCompatActivity() {
position: Int, position: Int,
id: Long id: Long
) { ) {
presentation.updateMealPickupMode(position)
} }
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {}
}
} }
adapter = createAdapter() adapter = createAdapter()
binding.recyclerview.layoutManager = GridLayoutManager(this, 2) binding.recyclerview.layoutManager = GridLayoutManager(this, 2)
@@ -126,7 +129,6 @@ class MainActivity : AppCompatActivity() {
binding.tvFoodName.setOnClickListener { binding.tvFoodName.setOnClickListener {
SensorScaleUtils.zero() SensorScaleUtils.zero()
} }
registerDataChange()
} }
fun updateCurrentFood(foodInfo: FoodInfo?) { fun updateCurrentFood(foodInfo: FoodInfo?) {
@@ -154,7 +156,8 @@ class MainActivity : AppCompatActivity() {
} }
} }
private fun registerDataChange() { override fun registerDataChange() {
super.registerDataChange()
lifecycleScope.launch { lifecycleScope.launch {
viewModel.identifiedFoodInfoList.collect { list -> viewModel.identifiedFoodInfoList.collect { list ->
binding.recyclerview binding.recyclerview
@@ -11,7 +11,6 @@ import android.hardware.Camera
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import android.view.Display import android.view.Display
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -69,19 +68,18 @@ class SecondaryScreenPresentation(
// 当前食物信息 // 当前食物信息
private var currentFood: FoodInfo? = null private var currentFood: FoodInfo? = null
private var lastFood: FoodInfo? = null
private var userNutritionData: UserNutritionData? = null private var userNutritionData: UserNutritionData? = null
private var dinnerTypeInfo: DinnerTypeInfo? = null private var dinnerTypeInfo: DinnerTypeInfo? = null
private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding
private lateinit var stepChangeCallback: (Int) -> Unit private lateinit var stepChangeCallback: (Int) -> Unit
// 上一次的计算热量结果 // 上一次的计算热量结果
private var lastCalcResultInfo: UserNutritionUtils.CalcResultInfo? = null
private var lastWeight = 0.0 private var lastWeight = 0.0
private val debouncer = Debouncer(500) private val debouncer = Debouncer(500)
private var faceTime: Long = 0L // 人脸识别时的时间 private var recognitionTime: Long = 0L // 人脸识别时的时间
private var recognitionWeight: Double = 0.0 // 人脸识别时的重量 private var recognitionWeight: Double = 0.0 // 人脸识别时的重量
private var lastFaceTrackId: Int = 0 // 上一次的人脸信息 private var lastFaceTrackId: Int = 0 // 上一次的人脸信息
private var mealPickupMode: Int = 0 // 取餐模式 0 即放即取 1 余量取餐
// 当前步骤 // 当前步骤
var currentStep: Int = 0 var currentStep: Int = 0
@@ -99,6 +97,13 @@ class SecondaryScreenPresentation(
} }
private fun registerDataChange() { private fun registerDataChange() {
activity.lifecycleScope.launch {
viewModel.loadFaceResult.collect { needUpdate ->
if (needUpdate){
recognizeViewModel.refreshFaceList()
}
}
}
activity.lifecycleScope.launch { activity.lifecycleScope.launch {
viewModel.nutritionData.collect { viewModel.nutritionData.collect {
Timber.d("registerDataChange nutritionData = $it") Timber.d("registerDataChange nutritionData = $it")
@@ -161,8 +166,6 @@ class SecondaryScreenPresentation(
dinnerTypeInfo = null dinnerTypeInfo = null
currentFood = null currentFood = null
userNutritionData = null userNutritionData = null
lastFood = null
lastCalcResultInfo = null
recognitionWeight = 0.0 recognitionWeight = 0.0
stepChangeCallback(currentStep) stepChangeCallback(currentStep)
@@ -182,6 +185,11 @@ class SecondaryScreenPresentation(
fun step2(foodInfo: FoodInfo) { fun step2(foodInfo: FoodInfo) {
Timber.d("step2") Timber.d("step2")
currentStep = 2 currentStep = 2
dinnerTypeInfo = null
userNutritionData = null
recognitionWeight = 0.0
stepChangeCallback(currentStep) stepChangeCallback(currentStep)
currentFood = foodInfo currentFood = foodInfo
viewModel.getDinnerType() viewModel.getDinnerType()
@@ -262,6 +270,14 @@ class SecondaryScreenPresentation(
calculateNutrition(recognitionWeight - lastWeight) calculateNutrition(recognitionWeight - lastWeight)
} }
/**
* 余量取餐
*/
fun updateMealPickupMode(mode: Int) {
Timber.d("updateMealPickupMode mode = $mode")
mealPickupMode = mode
}
private fun calculateNutrition(weight: Double) { private fun calculateNutrition(weight: Double) {
debouncer.debounce { debouncer.debounce {
Timber.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight") Timber.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
@@ -274,11 +290,6 @@ class SecondaryScreenPresentation(
dinnerType = dinnerType dinnerType = dinnerType
) )
Timber.d("calculateNutrition calcResultInfo = $calcResultInfo") Timber.d("calculateNutrition calcResultInfo = $calcResultInfo")
if (lastCalcResultInfo == calcResultInfo) {
Timber.d("calculateNutrition 与上次计算结果无变化")
return@debounce
}
lastCalcResultInfo = calcResultInfo
val columnMax = UserNutritionUtils.getMaxInt(calcResultInfo) val columnMax = UserNutritionUtils.getMaxInt(calcResultInfo)
activity.runOnUiThread { activity.runOnUiThread {
@@ -346,7 +357,7 @@ class SecondaryScreenPresentation(
} }
try { try {
val cameraCount = Camera.getNumberOfCameras() val cameraCount = Camera.getNumberOfCameras()
if (cameraCount < 3){ if (cameraCount < 3) {
ToastUtils.showToast("摄像头数量异常") ToastUtils.showToast("摄像头数量异常")
return return
} }
@@ -418,14 +429,14 @@ class SecondaryScreenPresentation(
Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}") Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
}) })
recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? -> recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? ->
// Timber.i("recognizeNotice observe notice = $notice") Timber.i("recognizeNotice observe notice = $notice")
}) })
recognizeViewModel.recognizeUserId.observe( recognizeViewModel.recognizeUserId.observe(
activity, activity,
Observer { compareResult: CompareResult -> Observer { compareResult: CompareResult ->
Timber.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}") Timber.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}")
faceTime = System.currentTimeMillis() recognitionTime = System.currentTimeMillis()
recognitionWeight = lastWeight recognitionWeight = lastWeight
lastFaceTrackId = compareResult.trackId lastFaceTrackId = compareResult.trackId
val faceEntity = compareResult.faceEntity val faceEntity = compareResult.faceEntity
@@ -701,7 +712,11 @@ class SecondaryScreenPresentation(
Timber.i("$lastFaceTrackId 用户离开") Timber.i("$lastFaceTrackId 用户离开")
lastFaceTrackId = 0 lastFaceTrackId = 0
postUserData() postUserData()
if (mealPickupMode == 0) {
step1() step1()
}else{
step2(currentFood!!)
}
} }
} }
} }
@@ -715,7 +730,7 @@ class SecondaryScreenPresentation(
val userNutritionParam = UserNutritionParam( val userNutritionParam = UserNutritionParam(
userId = userNutritionData?.userId!!, userId = userNutritionData?.userId!!,
foodId = currentFood?.id!!, foodId = currentFood?.id!!,
faceTime = faceTime, faceTime = recognitionTime,
faceEndTime = System.currentTimeMillis(), faceEndTime = System.currentTimeMillis(),
eatWeight = recognitionWeight - lastWeight, eatWeight = recognitionWeight - lastWeight,
foodWeight = lastWeight foodWeight = lastWeight
@@ -0,0 +1,99 @@
package com.sw.dualscreen.utils
import android.graphics.Bitmap
import android.graphics.Color
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
/**
* 二维码生成工具类
*/
object QRCodeUtil {
/**
* 生成二维码(默认大小)
* @param content 二维码内容
* @return 生成的二维码Bitmap
*/
@JvmOverloads
fun generateQRCode(content: String, size: Int = 500): Bitmap? {
return generateQRCode(content, size, Color.BLACK, Color.WHITE)
}
/**
* 生成二维码(自定义颜色)
* @param content 二维码内容
* @param size 二维码边长(像素)
* @param colorCode 二维码颜色
* @param backgroundColor 背景颜色
* @return 生成的二维码Bitmap
*/
fun generateQRCode(
content: String,
size: Int,
colorCode: Int,
backgroundColor: Int
): Bitmap? {
if (content.isEmpty()) {
return null
}
return try {
val hints = mutableMapOf<EncodeHintType, Any>().apply {
put(EncodeHintType.CHARACTER_SET, "UTF-8")
put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H) // 纠错级别
put(EncodeHintType.MARGIN, 1) // 边距
}
val bitMatrix = QRCodeWriter().encode(
content,
BarcodeFormat.QR_CODE,
size,
size,
hints
)
val pixels = IntArray(size * size).apply {
for (y in 0 until size) {
for (x in 0 until size) {
this[y * size + x] = if (bitMatrix.get(x, y)) colorCode else backgroundColor
}
}
}
Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888).apply {
setPixels(pixels, 0, size, 0, 0, size, size)
}
} catch (e: WriterException) {
e.printStackTrace()
null
}
}
/**
* 生成带Logo的二维码
* @param content 二维码内容
* @param size 二维码边长(像素)
* @param logo Logo Bitmap
* @return 带Logo的二维码Bitmap
*/
fun generateQRCodeWithLogo(content: String, size: Int, logo: Bitmap?): Bitmap? {
val qrCode = generateQRCode(content, size) ?: return null
logo ?: return qrCode
val logoSize = size / 5 // Logo大小约为二维码的1/5
val scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, false)
val offset = (size - logoSize) / 2
return Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888).apply {
val canvas = android.graphics.Canvas(this)
canvas.drawBitmap(qrCode, 0f, 0f, null)
canvas.drawBitmap(scaledLogo, offset.toFloat(), offset.toFloat(), null)
}
}
}
@@ -0,0 +1,88 @@
package com.sw.dualscreen.view;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
public class CustomDialog extends Dialog {
/**
* 宽高由布局文件中指定(但是最底层的宽度无效,可以多嵌套一层解决)
*/
public CustomDialog(Context context, View layout, int style) {
super(context, style);
setContentView(layout);
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.CENTER;
window.setAttributes(params);
}
/**
* 宽高由该方法的参数设置
*/
public CustomDialog(Context context, int width, int height, View layout,
int style) {
super(context, style);
// 设置内容
setContentView(layout);
// 设置窗口属性
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
// 设置宽度、高度、密度、对齐方式
float density = getDensity(context);
params.width = (int) (width * density);
params.height = (int) (height * density);
params.gravity = Gravity.CENTER;
window.setAttributes(params);
}
/**
* 获取显示密度
*
* @param context
* @return
*/
public float getDensity(Context context) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
return dm.density;
}
private void fullScreenImmersive(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN;
view.setSystemUiVisibility(uiOptions);
}
}
@Override
public void show() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
super.show();
// fullScreenImmersive(getWindow().getDecorView());
// this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
}
@@ -1,5 +1,6 @@
package com.sw.dualscreen.viewmodel package com.sw.dualscreen.viewmodel
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.model.response.EquipmentInfo import com.sw.dualscreen.model.response.EquipmentInfo
import com.sw.dualscreen.utils.GsonUtils import com.sw.dualscreen.utils.GsonUtils
@@ -18,7 +19,7 @@ class DeviceViewModel : BaseViewModel() {
/** /**
* 获取token * 获取token
*/ */
fun getDeviceToken(deviceId: String = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e") { fun getDeviceToken(deviceId: String = GlobalData.deviceId) {
launchWithLoading { launchWithLoading {
val response = repository.getDeviceToken(deviceId) val response = repository.getDeviceToken(deviceId)
if (parseResponse(response)) { if (parseResponse(response)) {
@@ -45,11 +45,17 @@ class UserViewModel : BaseViewModel() {
private val _dinnerTypeInfo = MutableStateFlow<DinnerTypeInfo?>(null) private val _dinnerTypeInfo = MutableStateFlow<DinnerTypeInfo?>(null)
val dinnerTypeInfo: StateFlow<DinnerTypeInfo?> = _dinnerTypeInfo val dinnerTypeInfo: StateFlow<DinnerTypeInfo?> = _dinnerTypeInfo
/**
* 人脸加载完成
*/
private val _loadFaceResult = MutableStateFlow<Boolean>(false)
val loadFaceResult : StateFlow<Boolean> = _loadFaceResult
/** /**
* 获取token * 获取token
*/ */
fun getEquipmentToken(qrcodeId: String = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e") { fun getEquipmentToken(qrcodeId: String = GlobalData.deviceId) {
Timber.d("getEquipmentToken") Timber.d("getEquipmentToken")
launchWithLoading { launchWithLoading {
val response = repository.getEquipmentToken(qrcodeId) val response = repository.getEquipmentToken(qrcodeId)
@@ -70,6 +76,7 @@ class UserViewModel : BaseViewModel() {
fun getUserFaceCache(index: Int = 0) { fun getUserFaceCache(index: Int = 0) {
Timber.d("getUserFaceCache index = $index") Timber.d("getUserFaceCache index = $index")
launch { launch {
_loadFaceResult.value = false
val response = repository.getUserFaceCache(index) val response = repository.getUserFaceCache(index)
if (parseResponse(response)) { if (parseResponse(response)) {
// 获取成功一次后缓存状态 // 获取成功一次后缓存状态
@@ -80,11 +87,12 @@ class UserViewModel : BaseViewModel() {
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString)) FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString))
} }
faceApi.updateFaceData(index, faceEntity) faceApi.updateFaceData(index, faceEntity)
activeEngine()
} }
val nextPageIndex = response.result?.nextPageIndex ?: -1 val nextPageIndex = response.result?.nextPageIndex ?: -1
if (nextPageIndex > 0) { if (nextPageIndex > 0) {
getUserFaceCache(nextPageIndex) getUserFaceCache(nextPageIndex)
} else{
_loadFaceResult.value = true
} }
} }
} }
@@ -129,13 +137,6 @@ class UserViewModel : BaseViewModel() {
}) })
} }
/**
* 重置用户信息
*/
fun resetUserInfo() {
Timber.d("resetUserInfo")
}
fun getIdentifiedFoodList() { fun getIdentifiedFoodList() {
Timber.d("identifiedFoodList") Timber.d("identifiedFoodList")
launchWithLoading { launchWithLoading {
@@ -180,7 +181,7 @@ class UserViewModel : BaseViewModel() {
fun getUserNutritionData(userId: String, foodId: String) { fun getUserNutritionData(userId: String, foodId: String) {
Timber.d("getUserNutritionData userId = ${userId}, foodId = $foodId") Timber.d("getUserNutritionData userId = ${userId}, foodId = $foodId")
_nutritionData.value = null _nutritionData.value = null
launchWithLoading { launch {
val response = repository.getUserNutritionData(userId = userId, foodId = foodId) val response = repository.getUserNutritionData(userId = userId, foodId = foodId)
if (parseResponse(response)) { if (parseResponse(response)) {
_nutritionData.value = response.result _nutritionData.value = response.result
@@ -191,7 +192,7 @@ class UserViewModel : BaseViewModel() {
fun getDinnerType() { fun getDinnerType() {
Timber.d("getDinnerType") Timber.d("getDinnerType")
_dinnerTypeInfo.value = null _dinnerTypeInfo.value = null
launchWithLoading { launch {
val response = repository.getDinnerType() val response = repository.getDinnerType()
if (parseResponse(response)) { if (parseResponse(response)) {
_dinnerTypeInfo.value = response.result _dinnerTypeInfo.value = response.result
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ff08C6DC" />
<corners android:radius="8dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp" />
<solid android:color="@color/black" />
</shape>
+78 -11
View File
@@ -1,23 +1,90 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical">
tools:context=".activity.InitActivity">
<LinearLayout
android:id="@+id/welcomeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
<RelativeLayout
android:id="@+id/initRelLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:padding="48dp">
<ImageView
android:id="@+id/mainImgView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="200dp"
android:src="@mipmap/img_init" />
<TextView <TextView
android:id="@+id/tv_deviceId" android:id="@+id/okButton"
android:layout_width="wrap_content" android:layout_width="200dp"
android:layout_height="wrap_content" android:layout_height="52dp"
tools:text="1111" /> android:layout_below="@+id/mainImgView"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:background="@drawable/bg_init_button"
android:gravity="center"
android:text="连接服务器"
android:textColor="@color/white"
android:textSize="22sp"
android:visibility="gone"
android:textStyle="bold" />
<Button <TextView
android:id="@+id/bt_confirm" android:id="@+id/initButton"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_below="@+id/mainImgView"
android:layout_centerHorizontal="true"
android:layout_marginTop="160dp"
android:padding="10dp"
android:background="@drawable/bg_init_button"
android:gravity="center"
android:text="设备初始化"
android:textColor="@color/white"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:id="@+id/activeArcsoft"
android:layout_width="300dp"
android:layout_height="68dp"
android:layout_below="@+id/okButton"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:background="@drawable/bg_init_button"
android:gravity="center"
android:text="虹软激活"
android:textColor="@color/white"
android:textSize="32sp"
android:textStyle="bold"
android:visibility="gone" />
<ImageView
android:id="@+id/imgQr"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_centerHorizontal="true"
android:text="获取" /> android:layout_alignParentBottom="true" />
</RelativeLayout>
</LinearLayout> </LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="240dp"
android:layout_height="80dp"
android:background="@drawable/dialog_waiting">
<TextView
android:id="@+id/tvTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/white"
android:text="请稍等"
android:textSize="22sp" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:layout_toLeftOf="@id/tvTip"
android:indeterminateTint="@color/teal_200"
android:indeterminateTintMode="src_atop" />
</RelativeLayout>
</FrameLayout>
Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

+1 -1
View File
@@ -7,7 +7,7 @@
<color name="beige_ECE7D0">#ECE7D0</color> <color name="beige_ECE7D0">#ECE7D0</color>
<color name="blue_6498DD">#6498DD</color> <color name="blue_6498DD">#6498DD</color>
<color name="black_031127">#031127</color> <color name="black_031127">#031127</color>
<color name="teal_200">#FF03DAC5</color>
<color name="identify_checked">#031127</color> <color name="identify_checked">#031127</color>
<color name="identify_normal">#6498DD</color> <color name="identify_normal">#6498DD</color>
<color name="search_checked">#FF9900</color> <color name="search_checked">#FF9900</color>
+14
View File
@@ -116,4 +116,18 @@
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
<item name="android:layout_centerHorizontal">true</item> <item name="android:layout_centerHorizontal">true</item>
</style> </style>
<!--圆角Dialog-->
<style name="MyDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.6</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
</resources> </resources>
+4
View File
@@ -1,5 +1,7 @@
[versions] [versions]
agp = "8.10.1" agp = "8.10.1"
core = "3.4.1"
androidCore = "3.3.0"
glide = "4.16.0" glide = "4.16.0"
kotlin = "2.0.21" kotlin = "2.0.21"
coreKtx = "1.10.1" coreKtx = "1.10.1"
@@ -25,6 +27,8 @@ lifecycleViewmodelKtx = "2.8.3"
lifecycleRuntimeKtx = "2.8.3" lifecycleRuntimeKtx = "2.8.3"
[libraries] [libraries]
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
core = { module = "com.google.zxing:core", version.ref = "core" }
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }