调整了餐盘在不同设备提示
This commit is contained in:
@@ -8,6 +8,12 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
|
||||
<application
|
||||
android:name=".MyApp"
|
||||
|
||||
@@ -14,7 +14,7 @@ object GlobalData {
|
||||
/**
|
||||
* 横排数量
|
||||
*/
|
||||
var arrayCross: Int = 2
|
||||
var arrayCross: Int = 3
|
||||
|
||||
/**
|
||||
* 竖排数量
|
||||
@@ -24,7 +24,7 @@ object GlobalData {
|
||||
/**
|
||||
* 排列方式 0 垂直 1 水平
|
||||
*/
|
||||
var arrayMode: Int = 1
|
||||
var arrayMode: Int = 0
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.widget.TextView
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.sw.inbound.utils.DateTimeUtils
|
||||
@@ -51,9 +50,9 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
context = this
|
||||
disableSystemUICompletely()
|
||||
// disableSystemUICompletely()
|
||||
// 确保内容延伸到导航栏区域
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
// WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
binding = inflateViewBinding()
|
||||
headerBinding = inflateTitleBinding()
|
||||
|
||||
@@ -60,8 +60,8 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
// 请求权限
|
||||
checkCameraPermission()
|
||||
|
||||
// viewModel.activeEngine()
|
||||
initArcViewModel()
|
||||
initArcView()
|
||||
openRectInfoDraw = true
|
||||
@@ -88,9 +88,11 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
|
||||
private fun checkCameraPermission() {
|
||||
Timber.i("checkCameraPermission")
|
||||
val permissionHelper =
|
||||
PermissionHelper.with(this, REQUIRED_PERMISSIONS, CAMERA_PERMISSION_REQUEST_CODE)
|
||||
.onGranted {
|
||||
Timber.d("checkCameraPermission 权限已允许")
|
||||
// 权限已授予
|
||||
recognizeViewModel.init()
|
||||
initRgbCamera()
|
||||
@@ -175,12 +177,14 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
|
||||
|
||||
/**
|
||||
* 调整View的宽高,使2个预览同时显示
|
||||
* 调整View的宽高,使预览显示正常且采集框固定为380x380
|
||||
*
|
||||
* @param rgbPreview RGB预览View
|
||||
* @param previewView 显示预览数据的view
|
||||
* @param faceRectView 画框的view
|
||||
* @param faceRectView 画框的view (380x380)
|
||||
* @param previewSize 预览大小
|
||||
* @param displayOrientation 相机旋转角度
|
||||
* @param scale 缩放比例
|
||||
* @return 调整后的LayoutParams
|
||||
*/
|
||||
private fun adjustPreviewViewSize(
|
||||
@@ -345,10 +349,8 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
|
||||
override fun onGlobalLayout() {
|
||||
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().removeOnGlobalLayoutListener(this)
|
||||
recognizeViewModel.init()
|
||||
initRgbCamera()
|
||||
resumeCamera()
|
||||
// countDownTimer.start();
|
||||
// 请求权限
|
||||
checkCameraPermission()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@ object DateTimeUtils {
|
||||
return SimpleDateFormat("yyyy年M月d日 EEEE", Locale.CHINA).format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标准时间格式
|
||||
*/
|
||||
fun getDateTimeString(date: Date = Date()): String {
|
||||
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取带时间的完整中文格式(示例:2025年6月11日 星期三 14:30)
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@ class PermissionHelper private constructor(
|
||||
/**
|
||||
* 检查是否已授予所有权限
|
||||
*/
|
||||
fun areAllPermissionsGranted(context: Context, permissions: Array<String>): Boolean {
|
||||
fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
|
||||
return permissions.all { permission ->
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
@@ -121,7 +121,7 @@ class PermissionHelper private constructor(
|
||||
* 检查并请求权限
|
||||
*/
|
||||
fun checkAndRequest() {
|
||||
if (areAllPermissionsGranted(context, permissions)) {
|
||||
if (checkPermissions(context, permissions)) {
|
||||
onGranted?.invoke()
|
||||
} else {
|
||||
requestPermissions()
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.sw.platecabinet.utils
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* 多功能线程工具类
|
||||
* 结合协程、Handler和线程池实现线程切换
|
||||
*/
|
||||
object ThreadUtils : CoroutineScope {
|
||||
// 主线程Handler
|
||||
private val mainHandler by lazy { Handler(Looper.getMainLooper()) }
|
||||
|
||||
// 后台线程池(IO密集型任务)
|
||||
private val ioThreadPool: ExecutorService by lazy {
|
||||
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2)
|
||||
}
|
||||
|
||||
// CPU密集型线程池
|
||||
private val cpuThreadPool: ExecutorService by lazy {
|
||||
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
|
||||
}
|
||||
|
||||
// 协程Job管理
|
||||
private val job = Job()
|
||||
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.Main + job
|
||||
|
||||
// ========== Handler相关方法 ==========
|
||||
|
||||
/**
|
||||
* 在主线程执行任务
|
||||
* @param delayMillis 延迟时间(毫秒)
|
||||
*/
|
||||
fun runOnUiThread(delayMillis: Long = 0, block: () -> Unit) {
|
||||
if (delayMillis > 0) {
|
||||
mainHandler.postDelayed(block, delayMillis)
|
||||
} else {
|
||||
if (isOnMainThread()) {
|
||||
block()
|
||||
} else {
|
||||
mainHandler.post(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除主线程任务
|
||||
*/
|
||||
fun removeUiThreadTask(block: () -> Unit) {
|
||||
mainHandler.removeCallbacks(block)
|
||||
}
|
||||
|
||||
// ========== 线程池相关方法 ==========
|
||||
|
||||
/**
|
||||
* 在IO线程执行任务
|
||||
*/
|
||||
fun runOnIoThread(block: () -> Unit) {
|
||||
ioThreadPool.execute(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* 在CPU计算线程执行任务
|
||||
*/
|
||||
fun runOnCpuThread(block: () -> Unit) {
|
||||
cpuThreadPool.execute(block)
|
||||
}
|
||||
|
||||
// ========== 协程相关方法 ==========
|
||||
|
||||
/**
|
||||
* 启动协程(默认在主线程)
|
||||
*/
|
||||
fun launch(block: suspend CoroutineScope.() -> Unit): Job {
|
||||
return launch(coroutineContext, block = block)
|
||||
}
|
||||
|
||||
/**
|
||||
* 在IO线程启动协程
|
||||
*/
|
||||
fun launchOnIo(block: suspend CoroutineScope.() -> Unit): Job {
|
||||
return launch(Dispatchers.IO, block = block)
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到主线程(协程环境)
|
||||
*/
|
||||
suspend fun <T> switchToMain(block: suspend CoroutineScope.() -> T): T {
|
||||
return withContext(Dispatchers.Main, block)
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到IO线程(协程环境)
|
||||
*/
|
||||
suspend fun <T> switchToIo(block: suspend CoroutineScope.() -> T): T {
|
||||
return withContext(Dispatchers.IO, block)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在主线程
|
||||
*/
|
||||
fun isOnMainThread(): Boolean {
|
||||
return Looper.myLooper() == Looper.getMainLooper()
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
fun release() {
|
||||
job.cancel()
|
||||
ioThreadPool.shutdown()
|
||||
cpuThreadPool.shutdown()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.sw.platecabinet.viewmodel
|
||||
|
||||
import com.sw.inbound.utils.DateTimeUtils
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.platecabinet.GlobalData
|
||||
import com.sw.platecabinet.GlobalData.globalEquipmentCode
|
||||
@@ -43,7 +44,7 @@ class SettingViewModel : BaseViewModel() {
|
||||
EquipmentParam(appVersion = GlobalData.appVersion, equipmentCode = equipmentCode)
|
||||
val response = repository.getEquipmentList(param)
|
||||
if (parseResponse(response)) {
|
||||
_equipmentList.value = response.data?.plus(response.data) ?: emptyList()
|
||||
_equipmentList.value = response.data ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +95,13 @@ class SettingViewModel : BaseViewModel() {
|
||||
)
|
||||
val response = repository.bindEquipment(bindParam)
|
||||
if (parseResponse(response)) {
|
||||
val userInfo = response.data
|
||||
userInfo?.let {
|
||||
if (it.isOtherEquipment()) {
|
||||
ToastUtils.showToast("餐盘已在${it.equipmentName}绑定")
|
||||
return@launchWithLoading
|
||||
}
|
||||
}
|
||||
_bindStateChange.value = true to ErrorInfo()
|
||||
} else {
|
||||
_bindStateChange.value = true to ErrorInfo(response.code, response.msg.toString())
|
||||
@@ -132,15 +140,20 @@ class SettingViewModel : BaseViewModel() {
|
||||
)
|
||||
val response = repository.findByPlateNumber(bindParam)
|
||||
if (response.code == 200) {
|
||||
if (response.data?.isOtherEquipment() == true) {
|
||||
ToastUtils.showToast("")
|
||||
return@launchWithLoading
|
||||
val userInfo = response.data
|
||||
userInfo?.let {
|
||||
if (it.isOtherEquipment()) {
|
||||
ToastUtils.showToast("餐盘已在${it.equipmentName}绑定")
|
||||
return@launchWithLoading
|
||||
}
|
||||
}
|
||||
|
||||
_currentUserInfo.value = response.data
|
||||
} else {
|
||||
_currentUserInfo.value = EquipmentUserInfo(
|
||||
plateNumber = plateNumber,
|
||||
equipmentCode = equipmentCode
|
||||
equipmentCode = equipmentCode,
|
||||
updateTime = DateTimeUtils.getDateTimeString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.sw.platecabinet.GlobalKey
|
||||
import com.sw.platecabinet.model.request.LoginParam
|
||||
import com.sw.platecabinet.model.response.EquipmentUserInfo
|
||||
import com.sw.platecabinet.model.response.UserFaceModel
|
||||
import com.sw.platecabinet.utils.ThreadUtils
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import timber.log.Timber
|
||||
@@ -63,7 +64,8 @@ class UserViewModel : BaseViewModel() {
|
||||
/**
|
||||
* 激活人脸识别引擎
|
||||
*/
|
||||
private fun activeEngine() {
|
||||
fun activeEngine() {
|
||||
Timber.d("activeEngine")
|
||||
var appId = "Hkz1rBk6PZXbS8KwKr67K2eZtsz8bRoMHLg64bUdgCZj"
|
||||
var sdkKey = "AabXs3sHM8UhhE7oCGf4LVMLrdkGb1nJNksbjjTdVt7k"
|
||||
var activeKey = "085F-118G-Q391-53YL"
|
||||
@@ -75,23 +77,27 @@ class UserViewModel : BaseViewModel() {
|
||||
object : FaceApi.ActiveCallback {
|
||||
override fun onSuccess(activeCode: Int) {
|
||||
Timber.d("activeEngine activeCode = $activeCode")
|
||||
when (activeCode) {
|
||||
ErrorInfo.MOK -> {
|
||||
ToastUtils.showToast("激活引擎成功")
|
||||
}
|
||||
ThreadUtils.launch {
|
||||
when (activeCode) {
|
||||
ErrorInfo.MOK -> {
|
||||
ToastUtils.showToast("激活引擎成功")
|
||||
}
|
||||
|
||||
ErrorInfo.MERR_ASF_ALREADY_ACTIVATED -> {
|
||||
ToastUtils.showToast("引擎已激活,无需再次激活")
|
||||
}
|
||||
ErrorInfo.MERR_ASF_ALREADY_ACTIVATED -> {
|
||||
// ToastUtils.showToast("引擎已激活,无需再次激活")
|
||||
}
|
||||
|
||||
else -> {
|
||||
ToastUtils.showToast("激活引擎失败($activeCode)")
|
||||
else -> {
|
||||
ToastUtils.showToast("激活引擎失败($activeCode)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFail(e: Exception?) {
|
||||
ToastUtils.showToast("激活引擎异常,${e?.message}")
|
||||
ThreadUtils.launch {
|
||||
ToastUtils.showToast("激活引擎异常,${e?.message}")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#14141E"
|
||||
android:orientation="vertical"
|
||||
android:fitsSystemWindows="false"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activity.LoginByFaceActivity">
|
||||
|
||||
<include
|
||||
@@ -44,7 +44,8 @@
|
||||
<TextureView
|
||||
android:id="@+id/dual_camera_texture_preview_rgb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="10dp" />
|
||||
|
||||
<com.sw.plate.utils.arcface.FaceRectView
|
||||
android:id="@+id/dual_camera_face_rect_view"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:textColor="@color/white"
|
||||
android:text="请稍等"
|
||||
android:textSize="22sp" />
|
||||
|
||||
<ProgressBar
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="80dp"
|
||||
tools:context=".fragment.PlateCabinetFullFragment">
|
||||
|
||||
<ImageView
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="80dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mainRecyclerView"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class FaceRectTransformer {
|
||||
rect.bottom *= verticalRatio;
|
||||
|
||||
Rect newRect = new Rect();
|
||||
L.e("cameraDisplayOrientation" + cameraDisplayOrientation + "===" + cameraId);
|
||||
L.e("cameraDisplayOrientation " + cameraDisplayOrientation + " === " + cameraId);
|
||||
switch (cameraDisplayOrientation) {
|
||||
case 0:
|
||||
if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
|
||||
@@ -610,6 +610,7 @@ public class FaceHelper implements FaceListener {
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
Log.e(TAG, "retryRecognizeDelayed e = " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
@@ -584,7 +584,7 @@ public class FaceServer {
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException exception) {
|
||||
Log.i(TAG, "exception:" + exception.getMessage());
|
||||
Log.i(TAG, "searchFaceFeature exception:" + exception.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user