Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3489ab9e6 | ||
|
|
1f1c3804ac |
@@ -1,3 +1,5 @@
|
||||
import org.gradle.kotlin.dsl.implementation
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
@@ -104,4 +106,7 @@ dependencies {
|
||||
implementation(libs.androidx.fragment.ktx)
|
||||
// 图片加载
|
||||
implementation(libs.glide)
|
||||
|
||||
implementation(libs.core)
|
||||
implementation(libs.android.core)
|
||||
}
|
||||
@@ -12,8 +12,9 @@ class MyApp : App() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Timber.plant(Timber.DebugTree())
|
||||
val deviceId = AppUtil.getUDID(this)
|
||||
var deviceId = AppUtil.getUDID(this)
|
||||
Timber.d("UDID = ${AppUtil.getUDID(this)}")
|
||||
deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
|
||||
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.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.sw.dualscreen.GlobalData
|
||||
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.plate.utils.AppUtil
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class InitActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityInitBinding
|
||||
class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
private val viewModel by viewModels<DeviceViewModel>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityInitBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
val deviceId = AppUtil.getUDID(this)
|
||||
override fun getViewModel(): BaseViewModel {
|
||||
return viewModel
|
||||
}
|
||||
|
||||
override fun inflateViewBinding(): ActivityInitBinding {
|
||||
return ActivityInitBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
super.initialize()
|
||||
val isSuccess = viewModel.checkEquipmentInfo()
|
||||
if (isSuccess) {
|
||||
goMainActivity()
|
||||
return
|
||||
}
|
||||
binding.tvDeviceId.text = deviceId
|
||||
binding.btConfirm.setOnClickListener {
|
||||
binding.imgQr.setImageBitmap(
|
||||
QRCodeUtil.generateQRCode(
|
||||
content = GlobalData.deviceId,
|
||||
size = 200
|
||||
)
|
||||
)
|
||||
binding.initButton.setOnClickListener {
|
||||
viewModel.getDeviceToken()
|
||||
}
|
||||
registerDataChange()
|
||||
}
|
||||
|
||||
private fun registerDataChange() {
|
||||
override fun registerDataChange() {
|
||||
super.registerDataChange()
|
||||
lifecycleScope.launch {
|
||||
viewModel.deviceInfoResult.drop(1).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.utils.GlideUtils
|
||||
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.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
@@ -44,8 +46,7 @@ import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
private val viewModel by viewModels<UserViewModel>()
|
||||
private var imageCapture: ImageCapture? = null
|
||||
private var isAnalyzing = true // 控制是否进行图像分析
|
||||
@@ -59,12 +60,16 @@ class MainActivity : AppCompatActivity() {
|
||||
private var bottomSheetDialog: CustomBottomSheetDialog? = null
|
||||
private var lastWeight: Double = 0.0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.main)
|
||||
override fun getViewModel(): BaseViewModel {
|
||||
return viewModel
|
||||
}
|
||||
|
||||
override fun inflateViewBinding(): ActivityMainBinding {
|
||||
return ActivityMainBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
super.initialize()
|
||||
initView()
|
||||
setupSecondaryDisplay()
|
||||
setupCamera()
|
||||
@@ -94,7 +99,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val spinnerAdapter = ArrayAdapter<String>(
|
||||
this,
|
||||
R.layout.item_for_custom_spinner,
|
||||
arrayOf("即放即取", "持续取餐")
|
||||
arrayOf("即放即取", "余量取餐")
|
||||
)
|
||||
binding.spinner.adapter = spinnerAdapter
|
||||
binding.spinner.setSelection(0)
|
||||
@@ -105,12 +110,10 @@ class MainActivity : AppCompatActivity() {
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
|
||||
presentation.updateMealPickupMode(position)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
|
||||
}
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
adapter = createAdapter()
|
||||
binding.recyclerview.layoutManager = GridLayoutManager(this, 2)
|
||||
@@ -126,7 +129,6 @@ class MainActivity : AppCompatActivity() {
|
||||
binding.tvFoodName.setOnClickListener {
|
||||
SensorScaleUtils.zero()
|
||||
}
|
||||
registerDataChange()
|
||||
}
|
||||
|
||||
fun updateCurrentFood(foodInfo: FoodInfo?) {
|
||||
@@ -154,7 +156,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerDataChange() {
|
||||
override fun registerDataChange() {
|
||||
super.registerDataChange()
|
||||
lifecycleScope.launch {
|
||||
viewModel.identifiedFoodInfoList.collect { list ->
|
||||
binding.recyclerview
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sw.dualscreen.presentation
|
||||
|
||||
import android.Manifest
|
||||
import android.R.attr.visibility
|
||||
import android.app.Presentation
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
@@ -11,7 +12,6 @@ import android.hardware.Camera
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.view.Display
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -69,19 +69,18 @@ class SecondaryScreenPresentation(
|
||||
|
||||
// 当前食物信息
|
||||
private var currentFood: FoodInfo? = null
|
||||
private var lastFood: FoodInfo? = null
|
||||
private var userNutritionData: UserNutritionData? = null
|
||||
private var dinnerTypeInfo: DinnerTypeInfo? = null
|
||||
private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding
|
||||
private lateinit var stepChangeCallback: (Int) -> Unit
|
||||
|
||||
// 上一次的计算热量结果
|
||||
private var lastCalcResultInfo: UserNutritionUtils.CalcResultInfo? = null
|
||||
private var lastWeight = 0.0
|
||||
private val debouncer = Debouncer(500)
|
||||
private var faceTime: Long = 0L // 人脸识别时的时间
|
||||
private var recognitionTime: Long = 0L // 人脸识别时的时间
|
||||
private var recognitionWeight: Double = 0.0 // 人脸识别时的重量
|
||||
private var lastFaceTrackId: Int = 0 // 上一次的人脸信息
|
||||
private var mealPickupMode: Int = 0 // 取餐模式 0 即放即取 1 余量取餐
|
||||
|
||||
// 当前步骤
|
||||
var currentStep: Int = 0
|
||||
@@ -99,6 +98,13 @@ class SecondaryScreenPresentation(
|
||||
}
|
||||
|
||||
private fun registerDataChange() {
|
||||
activity.lifecycleScope.launch {
|
||||
viewModel.loadFaceResult.collect { needUpdate ->
|
||||
if (needUpdate){
|
||||
recognizeViewModel.refreshFaceList()
|
||||
}
|
||||
}
|
||||
}
|
||||
activity.lifecycleScope.launch {
|
||||
viewModel.nutritionData.collect {
|
||||
Timber.d("registerDataChange nutritionData = $it")
|
||||
@@ -161,8 +167,6 @@ class SecondaryScreenPresentation(
|
||||
dinnerTypeInfo = null
|
||||
currentFood = null
|
||||
userNutritionData = null
|
||||
lastFood = null
|
||||
lastCalcResultInfo = null
|
||||
recognitionWeight = 0.0
|
||||
|
||||
stepChangeCallback(currentStep)
|
||||
@@ -182,6 +186,11 @@ class SecondaryScreenPresentation(
|
||||
fun step2(foodInfo: FoodInfo) {
|
||||
Timber.d("step2")
|
||||
currentStep = 2
|
||||
|
||||
dinnerTypeInfo = null
|
||||
userNutritionData = null
|
||||
recognitionWeight = 0.0
|
||||
|
||||
stepChangeCallback(currentStep)
|
||||
currentFood = foodInfo
|
||||
viewModel.getDinnerType()
|
||||
@@ -191,7 +200,10 @@ class SecondaryScreenPresentation(
|
||||
|
||||
binding.flPreview.visibility = View.GONE
|
||||
|
||||
binding.flFace.visibility = View.VISIBLE
|
||||
// binding.flFace.visibility = View.VISIBLE
|
||||
binding.flFace.post {
|
||||
binding.flFace.visibility = View.VISIBLE
|
||||
}
|
||||
binding.ivFaceBg.visibility = View.VISIBLE
|
||||
binding.tvFaceTip.visibility = View.VISIBLE
|
||||
binding.tvBottomTip.visibility = View.VISIBLE
|
||||
@@ -262,6 +274,14 @@ class SecondaryScreenPresentation(
|
||||
calculateNutrition(recognitionWeight - lastWeight)
|
||||
}
|
||||
|
||||
/**
|
||||
* 余量取餐
|
||||
*/
|
||||
fun updateMealPickupMode(mode: Int) {
|
||||
Timber.d("updateMealPickupMode mode = $mode")
|
||||
mealPickupMode = mode
|
||||
}
|
||||
|
||||
private fun calculateNutrition(weight: Double) {
|
||||
debouncer.debounce {
|
||||
Timber.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
||||
@@ -274,11 +294,6 @@ class SecondaryScreenPresentation(
|
||||
dinnerType = dinnerType
|
||||
)
|
||||
Timber.d("calculateNutrition calcResultInfo = $calcResultInfo")
|
||||
if (lastCalcResultInfo == calcResultInfo) {
|
||||
Timber.d("calculateNutrition 与上次计算结果无变化")
|
||||
return@debounce
|
||||
}
|
||||
lastCalcResultInfo = calcResultInfo
|
||||
val columnMax = UserNutritionUtils.getMaxInt(calcResultInfo)
|
||||
|
||||
activity.runOnUiThread {
|
||||
@@ -346,7 +361,7 @@ class SecondaryScreenPresentation(
|
||||
}
|
||||
try {
|
||||
val cameraCount = Camera.getNumberOfCameras()
|
||||
if (cameraCount < 3){
|
||||
if (cameraCount < 3) {
|
||||
ToastUtils.showToast("摄像头数量异常")
|
||||
return
|
||||
}
|
||||
@@ -418,14 +433,14 @@ class SecondaryScreenPresentation(
|
||||
Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
|
||||
})
|
||||
recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? ->
|
||||
// Timber.i("recognizeNotice observe notice = $notice")
|
||||
Timber.i("recognizeNotice observe notice = $notice")
|
||||
})
|
||||
|
||||
recognizeViewModel.recognizeUserId.observe(
|
||||
activity,
|
||||
Observer { compareResult: CompareResult ->
|
||||
Timber.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}")
|
||||
faceTime = System.currentTimeMillis()
|
||||
recognitionTime = System.currentTimeMillis()
|
||||
recognitionWeight = lastWeight
|
||||
lastFaceTrackId = compareResult.trackId
|
||||
val faceEntity = compareResult.faceEntity
|
||||
@@ -701,7 +716,11 @@ class SecondaryScreenPresentation(
|
||||
Timber.i("$lastFaceTrackId 用户离开")
|
||||
lastFaceTrackId = 0
|
||||
postUserData()
|
||||
step1()
|
||||
if (mealPickupMode == 0) {
|
||||
step1()
|
||||
}else{
|
||||
step2(currentFood!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -715,7 +734,7 @@ class SecondaryScreenPresentation(
|
||||
val userNutritionParam = UserNutritionParam(
|
||||
userId = userNutritionData?.userId!!,
|
||||
foodId = currentFood?.id!!,
|
||||
faceTime = faceTime,
|
||||
faceTime = recognitionTime,
|
||||
faceEndTime = System.currentTimeMillis(),
|
||||
eatWeight = recognitionWeight - 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
|
||||
|
||||
import com.sw.dualscreen.GlobalData
|
||||
import com.sw.dualscreen.GlobalKey
|
||||
import com.sw.dualscreen.model.response.EquipmentInfo
|
||||
import com.sw.dualscreen.utils.GsonUtils
|
||||
@@ -18,7 +19,7 @@ class DeviceViewModel : BaseViewModel() {
|
||||
/**
|
||||
* 获取token
|
||||
*/
|
||||
fun getDeviceToken(deviceId: String = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e") {
|
||||
fun getDeviceToken(deviceId: String = GlobalData.deviceId) {
|
||||
launchWithLoading {
|
||||
val response = repository.getDeviceToken(deviceId)
|
||||
if (parseResponse(response)) {
|
||||
|
||||
@@ -45,11 +45,17 @@ class UserViewModel : BaseViewModel() {
|
||||
private val _dinnerTypeInfo = MutableStateFlow<DinnerTypeInfo?>(null)
|
||||
val dinnerTypeInfo: StateFlow<DinnerTypeInfo?> = _dinnerTypeInfo
|
||||
|
||||
/**
|
||||
* 人脸加载完成
|
||||
*/
|
||||
private val _loadFaceResult = MutableStateFlow<Boolean>(false)
|
||||
val loadFaceResult : StateFlow<Boolean> = _loadFaceResult
|
||||
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
*/
|
||||
fun getEquipmentToken(qrcodeId: String = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e") {
|
||||
fun getEquipmentToken(qrcodeId: String = GlobalData.deviceId) {
|
||||
Timber.d("getEquipmentToken")
|
||||
launchWithLoading {
|
||||
val response = repository.getEquipmentToken(qrcodeId)
|
||||
@@ -70,6 +76,7 @@ class UserViewModel : BaseViewModel() {
|
||||
fun getUserFaceCache(index: Int = 0) {
|
||||
Timber.d("getUserFaceCache index = $index")
|
||||
launch {
|
||||
_loadFaceResult.value = false
|
||||
val response = repository.getUserFaceCache(index)
|
||||
if (parseResponse(response)) {
|
||||
// 获取成功一次后缓存状态
|
||||
@@ -80,11 +87,12 @@ class UserViewModel : BaseViewModel() {
|
||||
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString))
|
||||
}
|
||||
faceApi.updateFaceData(index, faceEntity)
|
||||
activeEngine()
|
||||
}
|
||||
val nextPageIndex = response.result?.nextPageIndex ?: -1
|
||||
if (nextPageIndex > 0) {
|
||||
getUserFaceCache(nextPageIndex)
|
||||
} else{
|
||||
_loadFaceResult.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,13 +137,6 @@ class UserViewModel : BaseViewModel() {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户信息
|
||||
*/
|
||||
fun resetUserInfo() {
|
||||
Timber.d("resetUserInfo")
|
||||
}
|
||||
|
||||
fun getIdentifiedFoodList() {
|
||||
Timber.d("identifiedFoodList")
|
||||
launchWithLoading {
|
||||
@@ -180,7 +181,7 @@ class UserViewModel : BaseViewModel() {
|
||||
fun getUserNutritionData(userId: String, foodId: String) {
|
||||
Timber.d("getUserNutritionData userId = ${userId}, foodId = $foodId")
|
||||
_nutritionData.value = null
|
||||
launchWithLoading {
|
||||
launch {
|
||||
val response = repository.getUserNutritionData(userId = userId, foodId = foodId)
|
||||
if (parseResponse(response)) {
|
||||
_nutritionData.value = response.result
|
||||
@@ -191,7 +192,7 @@ class UserViewModel : BaseViewModel() {
|
||||
fun getDinnerType() {
|
||||
Timber.d("getDinnerType")
|
||||
_dinnerTypeInfo.value = null
|
||||
launchWithLoading {
|
||||
launch {
|
||||
val response = repository.getDinnerType()
|
||||
if (parseResponse(response)) {
|
||||
_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>
|
||||
@@ -1,23 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activity.InitActivity">
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_deviceId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="1111" />
|
||||
<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">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="获取" />
|
||||
<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
|
||||
android:id="@+id/okButton"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="52dp"
|
||||
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" />
|
||||
|
||||
<TextView
|
||||
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_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true" />
|
||||
</RelativeLayout>
|
||||
</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 |
@@ -7,7 +7,7 @@
|
||||
<color name="beige_ECE7D0">#ECE7D0</color>
|
||||
<color name="blue_6498DD">#6498DD</color>
|
||||
<color name="black_031127">#031127</color>
|
||||
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="identify_checked">#031127</color>
|
||||
<color name="identify_normal">#6498DD</color>
|
||||
<color name="search_checked">#FF9900</color>
|
||||
|
||||
@@ -116,4 +116,18 @@
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:layout_centerHorizontal">true</item>
|
||||
</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>
|
||||
@@ -1,5 +1,7 @@
|
||||
[versions]
|
||||
agp = "8.10.1"
|
||||
core = "3.4.1"
|
||||
androidCore = "3.3.0"
|
||||
glide = "4.16.0"
|
||||
kotlin = "2.0.21"
|
||||
coreKtx = "1.10.1"
|
||||
@@ -25,6 +27,8 @@ lifecycleViewmodelKtx = "2.8.3"
|
||||
lifecycleRuntimeKtx = "2.8.3"
|
||||
|
||||
[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" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
|
||||
Reference in New Issue
Block a user