21 Commits
Author SHA1 Message Date
马增飞 3366fc02e5 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	app/src/main/java/com/shuwei/intelligent/shelves/InitActivity.kt
#	app/src/main/java/com/shuwei/intelligent/shelves/net/ApiService.kt
#	app/src/main/java/com/shuwei/intelligent/shelves/net/NetViewModel.kt
2025-11-06 19:32:30 +08:00
马增飞 647ec0dcb7 设备联调优化 2025-11-06 19:29:18 +08:00
lvmeng 61c9452295 开机启动页面修改 2025-09-26 15:58:40 +08:00
lvmeng a0737ebbc3 接口header配置修改 2025-09-18 19:22:20 +08:00
lvmeng a811d296d9 高度修改 2025-09-17 15:18:55 +08:00
lvmeng 9c2c5f073e 初始化功能调试,启动页面优化 2025-09-17 15:16:11 +08:00
lvmeng a355828bab 增加初始化功能 2025-09-11 16:09:07 +08:00
lvmeng e153f3e3b9 增加开机启动 2025-08-22 17:34:56 +08:00
lvmeng ca2041fe76 参数优化 2025-08-18 14:17:58 +08:00
lvmeng f8453c7d76 增加过期逻辑 2025-08-15 17:59:40 +08:00
lvmeng 2162ba0c9e 页面优化 2025-08-11 17:48:34 +08:00
马增飞 5b26e7e711 设备联调优化 2025-08-11 17:15:02 +08:00
lvmeng 0d99c4f22a 调试通过获取设备信息实时更新二级页面重量,首页和二级页面列表页增加空数据展示 2025-08-11 14:22:34 +08:00
马增飞 9e5ede4a8e 设备联调,接口参数优化 2025-08-08 17:48:07 +08:00
lvmeng 0b52dad0fe 串口数据长度优化 2025-08-08 15:08:26 +08:00
lvmeng 383c354f29 接口联调2 2025-08-08 14:54:11 +08:00
lvmeng 65199f4c70 接口联调 2025-08-08 13:34:18 +08:00
lvmeng eb66c2d2ff 优化数据读取异常问题 2025-08-07 19:32:04 +08:00
马增飞 e7e062ebcb 功能联调 2025-08-07 18:58:17 +08:00
lvmeng 4d91b9d338 适配优化 2025-08-07 13:01:26 +08:00
lvmeng c409621e28 功能优化,增加心跳数据处理 2025-08-07 11:07:04 +08:00
72 changed files with 3668 additions and 358 deletions
+35 -12
View File
@@ -4,14 +4,22 @@ plugins {
} }
android { android {
signingConfigs {
getByName("debug") {
storeFile = file("../app/swkey.jks")
storePassword = "123456"
keyPassword = "123456"
keyAlias = "android"
}
}
namespace = "com.shuwei.intelligent.shelves" namespace = "com.shuwei.intelligent.shelves"
compileSdk = 34 compileSdk = 34
defaultConfig { defaultConfig {
applicationId = "com.shuwei.intelligent.shelves" applicationId = "com.shuwei.intelligent.shelves"
minSdk = 25 minSdk = 25
//noinspection ExpiredTargetSdkVersion //noinspection EditedTargetSdkVersion,ExpiredTargetSdkVersion
targetSdk = 25 targetSdk = 30
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"
@@ -41,28 +49,43 @@ android {
ndkVersion = "29.0.13846066" ndkVersion = "29.0.13846066"
} }
//noinspection UseTomlInstead
dependencies { dependencies {
//implementation(fileTree("libs") { include("*.jar", "*.aar") }) //implementation(fileTree("libs") { include("*.jar", "*.aar") })
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.material) implementation(libs.material)
implementation(libs.android.core)
implementation(libs.core)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
implementation("androidx.activity:activity-ktx:1.8.0") implementation("androidx.activity:activity-ktx:1.8.0")
implementation("androidx.work:work-runtime-ktx:2.8.1")
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.2") implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.2")
implementation("com.squareup.okhttp3:okhttp:4.9.1")
implementation("com.google.code.gson:gson:2.10.1")
// implementation("io.github.jeremyliao:live-event-bus-x:1.8.0")
// implementation("com.hoho:android-usb-serial:1.3.0")
implementation("io.github.jeadyx:kmp-serialport:1.0.0") implementation("io.github.jeadyx:kmp-serialport:1.0.0")
// implementation("io.github.jeadyx:jserialport:1.5") // 基础依赖包,必须要依赖
implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
// kotlin扩展(可选)
implementation("com.geyifeng.immersionbar:immersionbar-ktx:3.2.2")
implementation("androidx.work:work-runtime-ktx:2.8.1") implementation("com.squareup.okhttp3:okhttp:4.9.1")
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha")
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
implementation("io.github.scwang90:refresh-footer-classics:3.0.0-alpha")
implementation("org.greenrobot:eventbus:3.3.1")
// implementation("io.github.jeremyliao:live-event-bus-x:1.8.0")
// implementation("com.hoho:android-usb-serial:1.3.0")
// implementation("io.github.jeadyx:jserialport:1.5")
} }
+27 -6
View File
@@ -2,22 +2,31 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.USB_PERMISSION" /> <uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application <application
android:name=".App" android:name=".App"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_logo512"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_logo512"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.IntelligentShelves"> android:theme="@style/Theme.IntelligentShelves"
android:usesCleartextTraffic="true">
<activity <activity
android:name=".HomeActivity" android:name=".InitActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity"> tools:ignore="DiscouragedApi,LockedOrientationActivity">
@@ -27,10 +36,22 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".HomeActivity"
android:screenOrientation="portrait"/>
<activity <activity
android:name=".ShelfActivity" android:name=".ShelfActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<receiver
android:name=".utils.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application> </application>
</manifest> </manifest>
@@ -1,23 +1,48 @@
package com.shuwei.intelligent.shelves package com.shuwei.intelligent.shelves
import android.app.Application import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import com.shuwei.intelligent.shelves.utils.BootReceiver
/** /**
* @author: star * @author: star
* @date: 2022-04-26 * @date: 2022-04-26
*/ */
class App : Application() { class App : Application() {
//"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjYW50ZWVuSWQiOiIiLCJ0eXBlIjoiNiIsInVzZXJJZCI6IjE2NzgyMjY1NTI5MzE1NDkxODYifQ.CQmbELpqT6QzvVCgCeirwvSvPp8Mhft_h6b1Af574Co"
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
app = this app = this
val filter = IntentFilter(Intent.ACTION_BOOT_COMPLETED)
registerReceiver(BootReceiver(), filter)
} }
companion object { companion object {
private lateinit var app: App private lateinit var app: App
var canteenId = "0"
var appVersion = "1"
var configUrl = ""
fun get(): App { //从接口获取
var accessToken: String = ""
var deviceId: String = ""
@Volatile
private var sharedPref: SharedPreferences? = null
fun getInstance(): App {
return app return app
} }
fun getSharedPref(): SharedPreferences? {
if (sharedPref != null) {
return sharedPref
}
sharedPref = app.getSharedPreferences("sp_intelligent_shelves", Context.MODE_PRIVATE)
return sharedPref
}
} }
} }
@@ -2,23 +2,52 @@ package com.shuwei.intelligent.shelves
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.provider.Settings
import android.util.Log import android.util.Log
import android.util.SparseIntArray import android.util.SparseArray
import android.view.View
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter4.util.setOnDebouncedItemClick import com.chad.library.adapter4.util.setOnDebouncedItemClick
import com.shuwei.intelligent.shelves.adapter.ShelfAdapter import com.shuwei.intelligent.shelves.adapter.ShelfAdapter
import com.shuwei.intelligent.shelves.base.BaseActivity import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityHomeBinding import com.shuwei.intelligent.shelves.databinding.ActivityHomeBinding
import com.shuwei.intelligent.shelves.model.ClearShelfEvent
import com.shuwei.intelligent.shelves.model.SendWeightEvent
import com.shuwei.intelligent.shelves.model.ShelfBody
import com.shuwei.intelligent.shelves.model.ShelfModel import com.shuwei.intelligent.shelves.model.ShelfModel
import com.shuwei.intelligent.shelves.model.ShelfResult
import com.shuwei.intelligent.shelves.model.WeightEvent
import com.shuwei.intelligent.shelves.net.Loading
import com.shuwei.intelligent.shelves.net.NetViewModel
import com.shuwei.intelligent.shelves.net.RespData
import com.shuwei.intelligent.shelves.net.UiState
import com.shuwei.intelligent.shelves.net.apiService
import com.shuwei.intelligent.shelves.serial.SerialPortManager import com.shuwei.intelligent.shelves.serial.SerialPortManager
import com.shuwei.intelligent.shelves.task.SyncTask
import com.shuwei.intelligent.shelves.task.TaskManager import com.shuwei.intelligent.shelves.task.TaskManager
import com.shuwei.intelligent.shelves.utils.UIUtils import com.shuwei.intelligent.shelves.utils.binaryToHex
import com.shuwei.intelligent.shelves.utils.ext.gone
import com.shuwei.intelligent.shelves.utils.ext.toJsonString
import com.shuwei.intelligent.shelves.utils.ext.toast
import com.shuwei.intelligent.shelves.utils.ext.visible
import com.shuwei.intelligent.shelves.utils.f2C
import com.shuwei.intelligent.shelves.utils.hexToBinary
import com.shuwei.intelligent.shelves.utils.hexToDec import com.shuwei.intelligent.shelves.utils.hexToDec
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -28,13 +57,15 @@ class HomeActivity : BaseActivity() {
companion object { companion object {
private const val TAG = "HomeActivity" private const val TAG = "HomeActivity"
private const val MM_DD_EEEE__HH_MM_SS = "MM月dd日 EEEE HH:mm:ss"
//协议头 //协议头
const val HEADER = "D6DADEDB" const val HEADER = "D6DADEDB"
//协议尾 //协议尾
const val FOOTER = "FFFF" const val FOOTER = "FFFF"
const val ACTIVE_CMD = // const val ACTIVE_CMD =
"${HEADER}000281C5D70A7D428A4FA67B50F7DACA241938938B4B9CBD73673E9C8E7F2E15062D${FOOTER}" // "${HEADER}000281C5D70A7D428A4FA67B50F7DACA241938938B4B9CBD73673E9C8E7F2E15062D${FOOTER}"
const val LEFT_SHELF_OPEN_CMD = const val LEFT_SHELF_OPEN_CMD =
"${HEADER}020101000000000000000000000000000000000000${FOOTER}" "${HEADER}020101000000000000000000000000000000000000${FOOTER}"
@@ -45,20 +76,46 @@ class HomeActivity : BaseActivity() {
const val DEVICE_INFO_CMD = "${HEADER}0301000000000000000000000000${FOOTER}" const val DEVICE_INFO_CMD = "${HEADER}0301000000000000000000000000${FOOTER}"
const val ACTIVE_CMD =
"${HEADER}000281C5D70A7D428948AD7254FADBB1516738938B4B9CBD73673E9D8E7F2E15062D${FOOTER}"
//开灯(开 继电器1
const val LIGHT_CLOSE = "${HEADER}020102020102020000000000000000000000000000${FOOTER}"
const val LIGHT_OPEN = "${HEADER}020102020002020000000000000000000000000000${FOOTER}"
// const val LIGHT_CLOSE = "${HEADER}020102020101010000000000000000000000000000${FOOTER}"
// const val LIGHT_OPEN = "${HEADER}020102020000000000000000000000000000000000${FOOTER}"
// const val LIGHT_CLOSE2 = "${HEADER}020102020102020000000000000000000000000000${FOOTER}"
// const val LIGHT_OPEN2 = "${HEADER}020102020002020000000000000000000000000000${FOOTER}"
// const val LIGHT_CLOSE3 = "${HEADER}020102020102020000000000000000000000000000${FOOTER}"
// const val LIGHT_OPEN3 = "${HEADER}020102020002020000000000000000000000000000${FOOTER}"
val list: MutableList<ShelfModel> = mutableListOf() val list: MutableList<ShelfModel> = mutableListOf()
val weightArray = SparseArray<Double?>()
var shelfIndex = 0
// public fun getRealWeight():Double = weightArray[shelfIndex]?:0.0
// 温度
var showTemperatureC = "0"
// 湿度
var showHumidity = "0"
} }
private lateinit var binding: ActivityHomeBinding private lateinit var binding: ActivityHomeBinding
@SuppressLint("NotifyDataSetChanged") private val viewModel: NetViewModel by viewModels()
@SuppressLint("NotifyDataSetChanged", "HardwareIds")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater) binding = ActivityHomeBinding.inflate(layoutInflater)
EventBus.getDefault().register(this)
setBackground()
setContentView(binding.root) setContentView(binding.root)
updateLeftStatus("1-1冷藏柜 -2°C / 87%") updateLeftStatus("1-1冷藏柜 -°C / -%")
initList()
initRecyclerView() initRecyclerView()
lifecycleScope.launch { lifecycleScope.launch {
@@ -68,39 +125,268 @@ class HomeActivity : BaseActivity() {
SerialPortManager.startReceive { data -> SerialPortManager.startReceive { data ->
runOnUiThread { runOnUiThread {
// 更新UI显示接收数据 // 更新UI显示接收数据
runCatching {
receiveSerialPortData(data) receiveSerialPortData(data)
}.onFailure {
it.printStackTrace()
}
} }
} }
SerialPortManager.send(ACTIVE_CMD) SerialPortManager.send(ACTIVE_CMD)
SerialPortManager.send(DEVICE_INFO_CMD) //SerialPortManager.send(DEVICE_INFO_CMD)
}
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.getAccessTokenUiState.collect { state ->
when (state) {
is UiState.Loading -> {}
is UiState.Success<*> -> getTokenSuccess(state.data)
is UiState.Error -> toast(state.msg)
else -> {}
}
}
}
launch {
viewModel.getShelfListUiState.collect { state ->
when (state) {
is UiState.Loading -> showProgress()
is UiState.Success<*> -> updateUI(state.data)
is UiState.Error -> showError(state.msg)
else -> {}
}
}
}
} }
} }
TaskManager.startTask() TaskManager.startTask()
// var androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
//// androidId = "d0e7a2d5f25c775c"
// Log.d(TAG, "onCreate: androidId=${androidId}")
// if (androidId == "65e1012638f78260" || androidId == "40f89e91ee40611d") {
// androidId = "d0e7a2d5f25c775c"
// }
// App.deviceId = androidId
// //"53babf69-0d2f-3875-a649-f2e12f80ad4c1"
//
// val swDpValue = resources?.configuration?.smallestScreenWidthDp
// Log.d(TAG, "onCreate: swDpValue=$swDpValue")
// viewModel.getAccessToken(App.deviceId)
viewModel.getShelfList(deviceId = App.deviceId)
// repeat(100) {
// lifecycleScope.launch {
// val data = "D6DADEDB01010C6102000000000000010000000500008000000000060000000500000004000080060000000100000010190080701800800000000000000000000000000000000000000000000000005037414645333633333334333731373056322E313069FFFF"
// receiveSerialPortData(data)
// delay(500)
// }
// }
// lifecycleScope.launch {
// repeat(100) {
// val sb = StringBuilder().apply {
//// 610200000000000001000000050000800000000006000000050000000400008006000000010000001019008070180080
// repeat(12) {
// val num = (0..99).random()
// val num2 = (0..99).random()
// val num3 = (0..99).random()
// val num4 = (0..1).random()
// val numStr = if (num <= 9) "0${num}" else "" + num
// val numStr2 = if (num2 <= 9) "0${num2}" else "" + num2
// val numStr3 = if (num3 <= 9) "0${num3}" else "" + num3
// val numStr4 = if (num4 == 1) "80" else "00"
// append(numStr).append(numStr2).append(numStr3).append(numStr4)
// }
// }
// val data =
// "${HEADER}0302000000000C${sb}5037414645333633333334333731373056322E313069${FOOTER}"
// receiveSerialPortData(data)
// delay(500)
// }
// }
lightSwitchClick()
} }
private fun receiveSerialPortData(data: String) { fun switchLight(isOpen: Boolean) {
Log.d(TAG, "receiveSerialPortData: $data") val tag = getLeftView().tag?.toString()?.toBoolean() ?: true
if (data.startsWith(HEADER).not()) { if(tag == isOpen) {
return return
} }
val cmd = data.substring(HEADER.length, HEADER.length + 2) lifecycleScope.launch {
when (cmd) { SerialPortManager.send(if (isOpen) LIGHT_OPEN else LIGHT_CLOSE)
"03" -> { }
//获取设备状态 getLeftView().tag = isOpen
val weightStartIndex = HEADER.length + 4 + 10 }
val temperatureStartIndex = weightStartIndex + 10 * 8
val temperatureHex = data.substring(temperatureStartIndex, 2)
val temperature = hexToDec(temperatureHex)
updateLeftStatus("1-1冷藏柜 $temperature°C / 87%")
private fun lightSwitchClick() {
switchLight(true)
addLeftClick {
val tag = getLeftView().tag?.toString()?.toBoolean() ?: true
switchLight(tag.not())
}
}
private fun getTokenSuccess(data: RespData<*>) {
Log.d(TAG, "getTokenSuccess: $data")
data.data?.let {
App.accessToken = it.toString()
//UIUtils.toast(it.toString())
viewModel.getShelfList(deviceId = App.deviceId)
}
}
private fun showProgress() {
Loading.show(this)
}
@SuppressLint("NotifyDataSetChanged")
private fun updateUI(data: RespData<*>) {
binding.include?.root?.gone()
window?.decorView?.postDelayed({ Loading.dismiss() }, 500)
if (data.data !is ShelfResult) {
loadEmptyView()
return
}
App.canteenId = data.data.placeId
val tempList = data.data.containerGoodsList
if (tempList.isNullOrEmpty()) {
loadEmptyView()
return
}
// if (tempList.size < 10) {
// toast("数据错误")
// return
// }
list.clear()
val subList01 = tempList.subList(0, tempList.size / 2)
val subList02 = tempList.subList(tempList.size / 2, tempList.size)
repeat(tempList.size / 2) { index ->
list.add(subList01[index].also { it.deviceId = App.deviceId })
list.add(subList02[index].also { it.deviceId = App.deviceId })
}
shelfAdapter.notifyDataSetChanged()
}
private fun showError(message: String) {
Loading.dismiss()
toast(message)
loadEmptyView()
}
private val serialReader by lazy { StringBuilder() }
private fun receiveSerialPortData(srcData: String) {
Log.d(TAG, "receiveSerialPortData: $srcData")
var data = ""
if (srcData.startsWith(HEADER) && srcData.contains(FOOTER)) {
serialReader.clear()
val endIndex = srcData.indexOf(FOOTER) + FOOTER.length
serialReader.append(srcData.substring(0, endIndex))
data = serialReader.toString()
} else if (srcData.startsWith(HEADER) && srcData.contains(FOOTER).not()) {
serialReader.clear()
serialReader.append(srcData).append(",")
return
} else if (srcData.startsWith(HEADER).not() && srcData.contains(FOOTER).not()) {
serialReader.append(srcData).append(",")
return
} else {
val endIndex = srcData.indexOf(FOOTER) + FOOTER.length
serialReader.append(srcData.substring(0, endIndex))
Log.d(TAG, "receiveSerialPortData:serialReader: $serialReader")
data = serialReader.toString().replace(",", "")
}
val cmd = data.substring(HEADER.length, HEADER.length + 4)
when (cmd) {
"0001" -> {
}
"0101" -> {
//心跳-01
Log.d(TAG, "receiveSerialPortData:心跳01: $data")
heartBeat(data)
}
// "8101" -> {
// //心跳-81
// Log.d(TAG, "receiveSerialPortData:心跳08: $data")
// heartBeat(data)
// }
// "0202" -> {
// //开关锁反馈
// lockFeedback(data)
// }
"0302" -> {
//获取设备状态
getDeviceInfo(data)
}
else -> {}
}
}
private var fixedDataBody = ""
private fun lockFeedback(data: String) {
runCatching {
val fixedDataBodyEndIndex = data.length - FOOTER.length
val fixedDataBodyStartIndex = HEADER.length + "0202".length + 42
fixedDataBody = data.substring(fixedDataBodyStartIndex, fixedDataBodyEndIndex)
val lockNo = if (list[shelfIndex].deviceNo in 1..5) "01" else "02"
val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6)
if (lockOneState == "00") {
//锁1关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
}
}
val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8)
if (lockTwoState == "00") {
//锁2关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
}
}
}.onFailure {
it.printStackTrace()
}
}
private fun heartBeat(data: String) {
runCatching {
if (data.length < 200) {
return
}
val weightStartIndex = 14
val weightEndIndex = weightStartIndex + 12 * 8
getWeightInfo(
start = weightStartIndex,
end = weightEndIndex,
data = data
)
val temperatureStartIndex = 158
val temperatureEndIndex = temperatureStartIndex + 2
val temperatureHex = data.substring(temperatureStartIndex, temperatureEndIndex)
val temperature = hexToDec(temperatureHex)
val tempC = f2C(temperature.toDouble())
showTemperatureC = "%.1f".format(tempC)
val percent = 10 * list.count { it.goodsName.isNullOrBlank().not() }
updateLeftStatus("1-1冷藏柜 [$temperatureHex] ${showTemperatureC}°C / ${percent}%")
}.onFailure {
it.printStackTrace()
}
}
private fun getWeightInfo(start: Int, end: Int, data: String) {
var index = 1 var index = 1
var count = weightStartIndex var count = start
while (count < temperatureStartIndex) { while (count < end) {
val weightInfo = data.substring(count, count + 8) val weightInfo = data.substring(count, count + 8)
var weightHex = "" var weightHex = ""
weightInfo.run { weightInfo.run {
@@ -108,56 +394,86 @@ class HomeActivity : BaseActivity() {
substring(6, 8) + substring(4, 6) + substring(2, 4) + substring(0, 2) substring(6, 8) + substring(4, 6) + substring(2, 4) + substring(0, 2)
} }
var realWeight = 0 var realWeight = 0
if (weightHex.first() in '8'..'F') { var firstByteBinary = hexToBinary(weightHex.substring(0, 2))
//负数 if (firstByteBinary.startsWith("0")) {
val weightHex2 = "0${weightHex.substring(1)}" //正数
realWeight = hexToDec(weightHex2) realWeight = weightHex.toInt()
} else { } else {
// //
realWeight = hexToDec(weightHex) firstByteBinary = "0${firstByteBinary.substring(1)}"
val firstByteHex = binaryToHex(firstByteBinary)
weightHex = firstByteHex + weightHex.substring(2)
realWeight = -1 * weightHex.toInt()
} }
weightArray.put(count, realWeight) val realWeightDouble = realWeight / 1000.0
weightArray.put(index, realWeightDouble)
if (index <= 10) {
list.firstOrNull { it.deviceNo == index }?.let {
it.weight = realWeightDouble
val pos = list.indexOf(it)
shelfAdapter.notifyItemChanged(pos)
Log.d(TAG, "getWeightInfo: deviceNo=${it.deviceNo},realWeight=${realWeight}")
EventBus.getDefault().post(SendWeightEvent(it.deviceNo, realWeight))
}
}
count += 8 count += 8
index++ index++
} }
// ShelfActivity.updateWeight(getRealWeight())
val intent = Intent(ShelfActivity.RECEIVER_DEVICE_INFO) // if (list.isNotEmpty()) {
intent.putExtra(ShelfActivity.SHELF_WEIGHT, weightArray[clickIndex]) // val intent = Intent(ShelfActivity.RECEIVER_DEVICE_INFO + list[shelfIndex].deviceNo)
intent.putExtra(ShelfActivity.RECEIVER_DEVICE_INFO, data) // intent.putExtra(ShelfActivity.SHELF_WEIGHT, weightArray[shelfIndex])
sendBroadcast(intent) // LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
// }
} }
else -> {} private fun getDeviceInfo(data: String) {
} Log.d(TAG, "getDeviceInfo: data=$data")
} val weightStartIndex = HEADER.length + 14
val temperatureStartIndex = weightStartIndex + 12 * 8
val temperatureEndIndex = temperatureStartIndex + 2
val temperatureHex = data.substring(temperatureStartIndex, temperatureEndIndex)
val temperature = hexToDec(temperatureHex)
val tempC = f2C(temperature.toDouble())
showTemperatureC = "%.1f".format(tempC)
private val weightArray by lazy { SparseIntArray() } val percent = 10 * list.count { it.goodsName.isNullOrBlank().not() }
private var clickIndex = 0
updateLeftStatus("1-1冷藏柜 ${showTemperatureC}°C / ${percent}%")
getWeightInfo(
start = weightStartIndex,
end = temperatureStartIndex,
data = data
)
}
override fun onDestroy() { override fun onDestroy() {
lifecycleScope.launch { lifecycleScope.launch {
SerialPortManager.close() SerialPortManager.close()
} }
TaskManager.cancelTask() TaskManager.cancelTask()
EventBus.getDefault().unregister(this)
super.onDestroy() super.onDestroy()
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private val shelfAdapter by lazy { private val shelfAdapter by lazy {
// val list = viewModel.getCurrentItems()
ShelfAdapter(list).apply { ShelfAdapter(list).apply {
setOnDebouncedItemClick { adapter, view, position -> setOnDebouncedItemClick { adapter, view, position ->
this@HomeActivity.clickIndex = position shelfIndex = position
lifecycleScope.launch { lifecycleScope.launch {
val openCmd = if (list[position].shelfNo in 1..5) // val openCmd = if (list[position].deviceNo in 1..5)
LEFT_SHELF_OPEN_CMD // LEFT_SHELF_OPEN_CMD
else // else
RIGHT_SHELF_OPEN_CMD // RIGHT_SHELF_OPEN_CMD
val openState = SerialPortManager.send(openCmd) // val openState = SerialPortManager.send(openCmd)
if (openState.not()) { // if (openState.not()) {
UIUtils.toast("${list[position].foodName}柜门开启失败") // toast("${list[position].goodsName}柜门开启失败")
return@launch // return@launch
} // }
launch(Intent(this@HomeActivity, ShelfActivity::class.java).also { launch(Intent(this@HomeActivity, ShelfActivity::class.java).also {
it.putExtra(ShelfActivity.SHELF_MODEL, list[position]) it.putExtra(ShelfActivity.SHELF_MODEL, list[position])
}) { }) {
@@ -165,11 +481,33 @@ class HomeActivity : BaseActivity() {
val model = val model =
getSerializableExtra(ShelfActivity.SHELF_MODEL) as ShelfModel getSerializableExtra(ShelfActivity.SHELF_MODEL) as ShelfModel
list[position].apply { list[position].apply {
foodName = model.foodName goodsId = model.goodsId
foodWeight = model.foodWeight goodsName = model.goodsName
storeDate = model.storeDate weight = model.weight
if (model.createTime.isNullOrBlank().not()) {
createTime = model.createTime
}
} }
notifyItemChanged(position) notifyItemChanged(position)
try {
val submitList = list.sortedBy { it.deviceNo }
val body = ShelfBody().also {
it.deviceId = App.deviceId ?: ""
it.canteenId = App.canteenId
it.temperature = showTemperatureC
it.humidity = showHumidity
it.goodsList = submitList
}
Log.d("mzf", "performSync: body:${body.toJsonString()}")
lifecycleScope.launch {
val resp = apiService.saveShelfGoodsList(body = body)
Log.d("mzf", "performSync: resp:${resp.toJsonString()}")
}
} catch (e: Exception) {
e.printStackTrace()
}
} }
} }
} }
@@ -182,25 +520,14 @@ class HomeActivity : BaseActivity() {
layoutManager = layoutManager =
GridLayoutManager(this@HomeActivity, 2, GridLayoutManager.VERTICAL, false) GridLayoutManager(this@HomeActivity, 2, GridLayoutManager.VERTICAL, false)
adapter = shelfAdapter adapter = shelfAdapter
}
}
private fun initList() { itemAnimator.let {
// val list: MutableList<ShelfModel> = mutableListOf() if (it is DefaultItemAnimator) {
list.add(ShelfModel(shelfNo = 1)) it.supportsChangeAnimations = false
list.add(ShelfModel(shelfNo = 6)) }
list.add(ShelfModel(shelfNo = 2)) }
list.add(ShelfModel(shelfNo = 7)) }
list.add(ShelfModel(shelfNo = 3))
list.add(ShelfModel(shelfNo = 8))
list.add(ShelfModel(shelfNo = 4))
list.add(ShelfModel(shelfNo = 9))
list.add(ShelfModel(shelfNo = 5))
list.add(ShelfModel(shelfNo = 10))
// viewModel.updateItems(list)
} }
private val MM_DD_EEEE__HH_MM_SS = "MM月dd日 EEEE HH:mm:ss"
private fun updateDateTime() { private fun updateDateTime() {
val sdf = SimpleDateFormat(MM_DD_EEEE__HH_MM_SS, Locale.CHINA) val sdf = SimpleDateFormat(MM_DD_EEEE__HH_MM_SS, Locale.CHINA)
@@ -226,4 +553,37 @@ class HomeActivity : BaseActivity() {
super.onPause() super.onPause()
handler.removeCallbacks(updateTask) handler.removeCallbacks(updateTask)
} }
@SuppressLint("NotifyDataSetChanged")
private fun loadEmptyView() {
list.clear()
shelfAdapter.notifyDataSetChanged()
binding.include?.let {
it.root.visible()
it.root.setOnClickListener {
viewModel.getAccessToken(App.deviceId)
}
it.ivEmptyIcon.setImageResource(R.drawable.ic_empty_white)
it.tvEmptyContent.setTextColor(Color.WHITE)
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public fun weightEvent(event: WeightEvent) {
}
@Subscribe(threadMode = ThreadMode.MAIN)
public fun clearEmptyShelf(event: ClearShelfEvent) {
val item = list.firstOrNull { it.deviceNo == event.shelfNo }
item?.apply {
goodsId = ""
goodsName = null
weight = null
createTime = null
overdueDay = null
}
shelfAdapter.notifyItemChanged(list.indexOf(item))
}
} }
@@ -0,0 +1,167 @@
package com.shuwei.intelligent.shelves
import android.annotation.SuppressLint
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityInitBinding
import com.shuwei.intelligent.shelves.model.DeviceConfigInfo
import com.shuwei.intelligent.shelves.net.NetViewModel
import com.shuwei.intelligent.shelves.net.UiState
import com.shuwei.intelligent.shelves.net.UrlConfig
import com.shuwei.intelligent.shelves.utils.AppUtil
import com.shuwei.intelligent.shelves.utils.QRCodeUtil
import com.shuwei.intelligent.shelves.utils.SpTool
import com.shuwei.intelligent.shelves.utils.ext.dp
import com.shuwei.intelligent.shelves.utils.ext.invisible
import com.shuwei.intelligent.shelves.utils.ext.startActivity
import com.shuwei.intelligent.shelves.utils.ext.toJsonString
import com.shuwei.intelligent.shelves.utils.ext.toObject
import com.shuwei.intelligent.shelves.utils.ext.toast
import com.shuwei.intelligent.shelves.utils.ext.visible
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlin.collections.forEach
import kotlin.getValue
import kotlin.jvm.java
import kotlin.ranges.downTo
import kotlin.text.isBlank
import kotlin.to
class InitActivity : BaseActivity() {
companion object {
const val TAG = "InitActivity"
}
private lateinit var binding: ActivityInitBinding
private val viewModel: NetViewModel by viewModels()
@SuppressLint("HardwareIds")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityInitBinding.inflate(layoutInflater)
setContentView(binding.root)
App.deviceId = AppUtil.getUDID( this)
SpTool.put(SpTool.DEVICE_ID, App.deviceId)
App.configUrl = UrlConfig.BASE_URL
App.canteenId = "0"
// var deviceId = AppUtil.getUDID(this)
// Log.d(TAG, "onCreate: deviceId=$deviceId")
//// deviceId = "39a7abdd06b3c7ab"
//// deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
// App.deviceId = deviceId
//
// SpTool.put(SpTool.DEVICE_ID, deviceId)
// val deviceConfigCache = SpTool.getString(SpTool.DEVICE_CONFIG_CACHE)
// val checkResult = checkConfigData(deviceConfigCache)
// if (checkResult.not()) {
// binding.ivQrCode.visible()
// binding.btnInit.visible()
// //进行初始化操作
// initConfig()
// return
// }
binding.ivQrCode.invisible()
binding.btnInit.invisible()
countDown()
}
private fun countDown() {
lifecycleScope.launch {
flow {
(2 downTo 1).forEach {
delay(1000)
emit(it)
}
}.collect {
// 倒计时结束执行跳转
if (it == 1) {
startActivity<HomeActivity>()
finish()
}
}
}
}
private fun initConfig() {
binding.ivQrCode.setImageBitmap(
QRCodeUtil.generateQRCode(
content = App.deviceId,
size = 200.dp
)
)
binding.btnInit.setOnClickListener {
viewModel.getDeviceToken(App.deviceId)
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.getDeviceTokenUiState.collect { state ->
when (state) {
is UiState.Loading -> {}
is UiState.Success<*> -> {
state.data.data?.let { deviceToken ->
Log.d(TAG, "initConfig: $deviceToken")
viewModel.getDeviceConfig(
deviceId = App.deviceId,
deviceToken = deviceToken.toString()
)
}
}
is UiState.Error -> toast(state.msg)
else -> {}
}
}
}
launch {
viewModel.getDeviceConfigUiState.collect { state ->
when (state) {
is UiState.Loading -> {}
is UiState.Success<*> -> {
state.data.data?.let {
if (it is DeviceConfigInfo) {
SpTool.put(SpTool.DEVICE_CONFIG_CACHE, it.toJsonString())
App.configUrl = it.appPackageUrl?:""
App.canteenId = it.canteenId?:""
startActivity<HomeActivity>()
finish()
}
}
}
is UiState.Error -> toast(message = state.msg)
else -> {}
}
}
}
}
}
}
private fun checkConfigData(data: String): Boolean {
if (data.isBlank()) {
return false
}
val config = data.toObject<DeviceConfigInfo?>()
if (config == null) {
return false
}
App.configUrl = config.appPackageUrl?:""
App.canteenId = config.canteenId?:""
return true
}
}
@@ -1,47 +1,66 @@
package com.shuwei.intelligent.shelves package com.shuwei.intelligent.shelves
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import android.widget.LinearLayout
import androidx.activity.viewModels
import androidx.core.view.updateLayoutParams
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter4.util.setOnDebouncedItemClick import com.chad.library.adapter4.util.setOnDebouncedItemClick
import com.shuwei.intelligent.shelves.HomeActivity.Companion.ACTIVE_CMD import com.scwang.smart.refresh.layout.constant.RefreshState
import com.shuwei.intelligent.shelves.HomeActivity.Companion.DEVICE_INFO_CMD import com.shuwei.intelligent.shelves.HomeActivity.Companion.DEVICE_INFO_CMD
import com.shuwei.intelligent.shelves.utils.ext.addOnActionSearchListener
import com.shuwei.intelligent.shelves.utils.ext.clickWithDebounce
import com.shuwei.intelligent.shelves.utils.ext.toast
import com.shuwei.intelligent.shelves.adapter.SearchAdapter import com.shuwei.intelligent.shelves.adapter.SearchAdapter
import com.shuwei.intelligent.shelves.base.BaseActivity import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityShelfBinding import com.shuwei.intelligent.shelves.databinding.ActivityShelfBinding
import com.shuwei.intelligent.shelves.model.SearchModel import com.shuwei.intelligent.shelves.model.ClearShelfEvent
import com.shuwei.intelligent.shelves.model.GoodsModel
import com.shuwei.intelligent.shelves.model.GoodsRecord
import com.shuwei.intelligent.shelves.model.SendWeightEvent
import com.shuwei.intelligent.shelves.model.ShelfModel import com.shuwei.intelligent.shelves.model.ShelfModel
import com.shuwei.intelligent.shelves.net.Loading
import com.shuwei.intelligent.shelves.net.NetViewModel
import com.shuwei.intelligent.shelves.net.RespData
import com.shuwei.intelligent.shelves.net.UiState
import com.shuwei.intelligent.shelves.serial.SerialPortManager import com.shuwei.intelligent.shelves.serial.SerialPortManager
import com.shuwei.intelligent.shelves.task.TaskManager
import com.shuwei.intelligent.shelves.utils.DateTimeUtil import com.shuwei.intelligent.shelves.utils.DateTimeUtil
import com.shuwei.intelligent.shelves.utils.KeyboardUtil import com.shuwei.intelligent.shelves.utils.KeyboardUtil
import com.shuwei.intelligent.shelves.utils.decToHex import com.shuwei.intelligent.shelves.utils.ext.addOnActionSearchListener
import com.shuwei.intelligent.shelves.utils.ext.clickWithDebounce
import com.shuwei.intelligent.shelves.utils.ext.dp
import com.shuwei.intelligent.shelves.utils.ext.gone
import com.shuwei.intelligent.shelves.utils.ext.toJsonString
import com.shuwei.intelligent.shelves.utils.ext.toast
import com.shuwei.intelligent.shelves.utils.ext.visible
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import kotlin.random.Random
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
class ShelfActivity : BaseActivity() { class ShelfActivity : BaseActivity() {
companion object { companion object {
private const val TAG = "ShelfActivity" private const val TAG = "ShelfActivity"
private const val YYYY_MM_DD__EEEE_HH_MM_SS = "yyyy年MM月dd日 EEEE***HH:mm:ss"
const val SHELF_MODEL = "shelfModel" const val SHELF_MODEL = "shelfModel"
const val RECEIVER_DEVICE_INFO = "receiverDeviceInfo" const val RECEIVER_DEVICE_INFO = "receiverDeviceInfo"
const val SHELF_WEIGHT = "shelfWeight" const val SHELF_WEIGHT = "shelfWeight"
const val SHELF_INDEX = "shelfIndex"
const val PAGE_SIZE = 100
} }
@@ -52,32 +71,48 @@ class ShelfActivity : BaseActivity() {
private var clickIndex: Int = -1 private var clickIndex: Int = -1
private var realWeight: Int = 0 private var realWeight: Int = 0
private var pageNo: Int = 1
private val viewModel: NetViewModel by viewModels()
@SuppressLint("UnspecifiedRegisterReceiverFlag") @SuppressLint("UnspecifiedRegisterReceiverFlag")
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityShelfBinding.inflate(layoutInflater) binding = ActivityShelfBinding.inflate(layoutInflater)
setBackground()
setContentView(binding.root) setContentView(binding.root)
EventBus.getDefault().register(this)
// tvFoodWeight =binding.tvFoodWeight
shelfModel = intent.getSerializableExtra(SHELF_MODEL) as ShelfModel? shelfModel = intent.getSerializableExtra(SHELF_MODEL) as ShelfModel?
shelfModel?.let { shelfModel?.let {
binding.tvShelfName.text = it.shelfName binding.tvShelfName.text = it.shelfName
binding.tvFoodName.text = if (it.foodName.isNullOrBlank()) "-" else it.foodName binding.tvFoodName.text = if (it.goodsName.isNullOrBlank()) "-" else it.goodsName
realWeight = ((it.weight ?: 0.0) * 1000).toInt()
// realWeight = (HomeActivity.getRealWeight() * 1000).toInt()
binding.tvFoodWeight.text = "${realWeight}"
} }
initRecyclerView() initRecyclerView()
// initWeight()
binding.etInputFood.run { binding.etInputFood.run {
addOnActionSearchListener { addOnActionSearchListener {
if (text.isNullOrBlank()) { if (text.isNullOrBlank()) {
toast(hint.toString()) toast(hint.toString())
return@addOnActionSearchListener return@addOnActionSearchListener
} }
loadSearchData() pageNo = 1
getGoodsList()
KeyboardUtil.hideKeyboard(context, this) KeyboardUtil.hideKeyboard(context, this)
} }
addTextChangedListener(afterTextChanged = { editable ->
if (editable.isNullOrBlank()) {
pageNo = 1
getGoodsList()
}
})
} }
binding.btnConfirm.clickWithDebounce { binding.btnConfirm.clickWithDebounce {
@@ -85,11 +120,15 @@ class ShelfActivity : BaseActivity() {
toast("请选择食材") toast("请选择食材")
return@clickWithDebounce return@clickWithDebounce
} }
val currentGoodsId = list[clickIndex].goodsId ?: ""
val data = ShelfModel( val data = ShelfModel(
shelfName = shelfModel?.shelfName, shelfName = shelfModel?.shelfName,
foodName = list[clickIndex].foodName, goodsId = currentGoodsId,
foodWeight = realWeight, goodsName = list[clickIndex].goodsName,
storeDate = DateTimeUtil.formatDateTime(dateTime = Date()) weight = realWeight / 1000.0,
overdueDay = list[clickIndex].overdueDay,
// createTime = if (shelfModel?.goodsId == currentGoodsId) null else DateTimeUtil.formatDateTime(dateTime = Date())
createTime = DateTimeUtil.formatDateTime(dateTime = Date())
) )
val intent = Intent().apply { val intent = Intent().apply {
putExtra(SHELF_MODEL, data) putExtra(SHELF_MODEL, data)
@@ -97,69 +136,156 @@ class ShelfActivity : BaseActivity() {
setResult(RESULT_OK, intent) setResult(RESULT_OK, intent)
finish() finish()
} }
binding.tvFoodWeight.text = "${realWeight}"
binding.root.setOnClickListener { v -> binding.root.setOnClickListener { v ->
KeyboardUtil.hideKeyboard(v.context, v) KeyboardUtil.hideKeyboard(v)
} }
binding.btnClearZero.setOnClickListener { v -> binding.btnClearZero.setOnClickListener {
lifecycleScope.launch { clearZero()
val shelfNo = shelfModel?.shelfNo ?: 0
val zeroClearingCmd =
"${HomeActivity.HEADER}0401${decToHex(shelfNo)}${HomeActivity.FOOTER}"
SerialPortManager.send(zeroClearingCmd)
} }
KeyboardUtil.hideKeyboard(v.context, v) binding.btnClearEmpty?.setOnClickListener {
clearZero()
binding.tvFoodName.text = "-"
binding.tvFoodWeight.text = "0克"
EventBus.getDefault().post(ClearShelfEvent(shelfModel!!.deviceNo))
} }
lifecycleScope.launch { lifecycleScope.launch {
SerialPortManager.send(DEVICE_INFO_CMD) SerialPortManager.send(DEVICE_INFO_CMD)
}
registerReceiver(receiver, IntentFilter(RECEIVER_DEVICE_INFO)) repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.getGoodsListUiState.collect { state ->
when (state) {
is UiState.Loading -> showProgress()
is UiState.Success<*> -> updateUI(state.data)
is UiState.Error -> showError(state.msg)
else -> {}
} }
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
val data = it.getStringExtra(RECEIVER_DEVICE_INFO)
Log.d(TAG, "onReceive: $data")
realWeight = it.getIntExtra(SHELF_WEIGHT, 0)
binding.tvFoodWeight.text = "${realWeight}"
} }
} }
} }
override fun onDestroy() { // registerReceiver(receiver, IntentFilter(RECEIVER_DEVICE_INFO + shelfModel?.deviceNo))
unregisterReceiver(receiver) binding.ivBack?.setOnClickListener { finish() }
super.onDestroy() binding.refreshLayout.let {
it.setEnableRefresh(true)
it.setEnableLoadMore(false)
it.setOnRefreshListener {
pageNo = 1
getGoodsList()
}
it.setOnLoadMoreListener { getGoodsList() }
}
getGoodsList()
TaskManager.startDeviceTask()
} }
// private fun initWeight() { private fun finishRefresh() {
// realWeight = Random.nextInt(1, 5001) binding.refreshLayout.let {
if (it.state == RefreshState.Refreshing) {
it.finishRefresh(500)
} else if (binding.refreshLayout.state == RefreshState.Loading) {
it.finishLoadMore(500)
} else {
}
}
}
private fun getGoodsList() {
viewModel.getGoodsList(
canteenId = App.canteenId,
goodsName = binding.etInputFood.text.trim().toString(),
pageNo = pageNo,
pageSize = PAGE_SIZE
)
}
private fun showProgress() {
Loading.show(this)
}
@SuppressLint("NotifyDataSetChanged")
private fun updateUI(data: RespData<*>) {
binding.include?.root?.gone()
finishRefresh()
binding.root.postDelayed({ Loading.dismiss() }, 200)
Log.d(TAG, "updateUI: ${data.toJsonString()}")
val goodsList = data.data as MutableList<GoodsModel>
if (data.data.isNullOrEmpty()) {
if (pageNo == 1) {
loadEmptyView()
}
return
}
if(pageNo == 1){
list.clear()
}
// var firstOne:GoodsModel?=null
// if (pageNo == 1) {
// if (shelfModel?.goodsId.isNullOrBlank().not()) {
// firstOne = list.firstOrNull { it.goodsId == shelfModel?.goodsId }
// if (firstOne == null) {
// firstOne = GoodsModel(
// goodsId = shelfModel?.goodsId,
// goodsName = shelfModel?.goodsName,
// isClicked = true
// )
// } // }
// }
private fun loadSearchData() { // list.clear()
list.add(SearchModel(foodId = 1000, foodName = "菲律宾乳猪五花肉")) // }
list.add(SearchModel(foodId = 1001, foodName = "金针菇")) // val records = data.data.records
list.add(SearchModel(foodId = 1002, foodName = "大菠菜")) // if (pageNo == 1) {
list.add(SearchModel(foodId = 1003, foodName = "清远麻鸡块")) // firstOne?.let { one ->
list.add(SearchModel(foodId = 1004, foodName = "普罗旺斯番茄")) // val filterResult = records.firstOrNull{one.goodsId == it.goodsId }
list.add(SearchModel(foodId = 1005, foodName = "长条茄子")) // if (filterResult != null) {
list.add(SearchModel(foodId = 1006, foodName = "得莫利鱼")) // records.remove(filterResult)
list.add(SearchModel(foodId = 1007, foodName = "土豆丝")) // }
list.add(SearchModel(foodId = 1008, foodName = "辣椒炒肉")) // clickIndex = 0
list.add(SearchModel(foodId = 1009, foodName = "雪菜烧豆腐")) // list.add(one)
list.add(SearchModel(foodId = 1010, foodName = "冬虫夏草炝拌芥兰苗")) // }
list.add( // }
SearchModel( list.addAll(goodsList)
foodId = 1011, val enableLoadMore = goodsList.size >= PAGE_SIZE
foodName = "蘑菇玉米山药莲藕胡萝卜红枣莲子枸杞清炖排骨汤" binding.refreshLayout.setEnableLoadMore(enableLoadMore)
) if (enableLoadMore) {
) pageNo++
}
searchAdapter.notifyDataSetChanged() searchAdapter.notifyDataSetChanged()
} }
private val list: MutableList<SearchModel> = mutableListOf() private fun showError(message: String) {
finishRefresh()
Loading.dismiss()
toast(message)
if (pageNo == 1) {
loadEmptyView()
}
}
// private val receiver = object : BroadcastReceiver() {
// override fun onReceive(context: Context?, intent: Intent?) {
// intent?.let {
// if (it.action == RECEIVER_DEVICE_INFO + shelfModel?.deviceNo) {
// val weight = it.getDoubleExtra(SHELF_WEIGHT, 0.0)
// Log.d(TAG, "getDeviceInfo:onReceive: weight=$weight")
// realWeight = (weight * 1000).toInt()
// binding.tvFoodWeight.text = "${realWeight}克"
// }
// }
// }
// }
override fun onDestroy() {
// unregisterReceiver(receiver)
EventBus.getDefault().unregister(this)
TaskManager.cancelDeviceTask()
super.onDestroy()
}
private val list: MutableList<GoodsModel> = mutableListOf()
private val searchAdapter by lazy { private val searchAdapter by lazy {
SearchAdapter(list).apply { SearchAdapter(list).apply {
setOnDebouncedItemClick { adapter, v, position -> setOnDebouncedItemClick { adapter, v, position ->
@@ -167,7 +293,7 @@ class ShelfActivity : BaseActivity() {
list.forEach { it.isClicked = false } list.forEach { it.isClicked = false }
list[position].isClicked = true list[position].isClicked = true
notifyDataSetChanged() notifyDataSetChanged()
binding.tvFoodName.text = list[position].foodName binding.tvFoodName.text = list[position].goodsName
KeyboardUtil.hideKeyboard(v.context, v) KeyboardUtil.hideKeyboard(v.context, v)
} }
} }
@@ -180,8 +306,6 @@ class ShelfActivity : BaseActivity() {
} }
} }
private val YYYY_MM_DD__EEEE_HH_MM_SS = "yyyy年MM月dd日 EEEE***HH:mm:ss"
private fun updateDateTime() { private fun updateDateTime() {
val sdf = SimpleDateFormat(YYYY_MM_DD__EEEE_HH_MM_SS, Locale.CHINA) val sdf = SimpleDateFormat(YYYY_MM_DD__EEEE_HH_MM_SS, Locale.CHINA)
val dateTime = sdf.format(Date()) val dateTime = sdf.format(Date())
@@ -209,4 +333,52 @@ class ShelfActivity : BaseActivity() {
handler.removeCallbacks(updateTask) handler.removeCallbacks(updateTask)
} }
@SuppressLint("NotifyDataSetChanged")
private fun loadEmptyView() {
list.clear()
searchAdapter.notifyDataSetChanged()
binding.include?.let {
it.root.visible()
it.root.setOnClickListener {
pageNo = 1
getGoodsList()
}
it.ivEmptyIcon.setImageResource(R.drawable.ic_empty_gray)
it.ivEmptyIcon.updateLayoutParams<LinearLayout.LayoutParams> {
val swDpValue = resources?.configuration?.smallestScreenWidthDp ?: 0
width = if (swDpValue > 600) 200.dp else 120.dp
}
}
binding.refreshLayout.run {
setEnableRefresh(false)
setEnableLoadMore(false)
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public fun receiveWeightEvent(event: SendWeightEvent) {
if (event.shelfNo == (shelfModel?.deviceNo ?: 0)) {
binding.tvFoodWeight.text = "${event.weight}"
}
}
private fun clearZero() {
lifecycleScope.launch {
val shelfNo = shelfModel?.deviceNo ?: 0
val hex = shelfNo.toString(16).padStart(2, '0').uppercase()
Log.d(TAG, "onCreate: hex=$hex")
val zeroClearingCmd = "${HomeActivity.HEADER}0401${hex}${HomeActivity.FOOTER}"
Log.d(TAG, "onCreate: zeroClearingCmd=$zeroClearingCmd")
SerialPortManager.send(zeroClearingCmd)
//清零
realWeight = 0
// binding.tvFoodWeight.text = "${realWeight}克"
SerialPortManager.send(DEVICE_INFO_CMD)
Loading.show(this@ShelfActivity)
window.decorView.postDelayed({ Loading.dismiss() }, 5000)
}
KeyboardUtil.hideKeyboard(window.decorView)
}
} }
@@ -11,10 +11,10 @@ import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.intelligent.shelves.R import com.shuwei.intelligent.shelves.R
import com.shuwei.intelligent.shelves.databinding.ListItemSearchBinding import com.shuwei.intelligent.shelves.databinding.ListItemSearchBinding
import com.shuwei.intelligent.shelves.model.SearchModel import com.shuwei.intelligent.shelves.model.GoodsModel
class SearchAdapter(list: MutableList<SearchModel>) : class SearchAdapter(list: MutableList<GoodsModel>) :
BaseQuickAdapter<SearchModel, SearchAdapter.VH>(list) { BaseQuickAdapter<GoodsModel, SearchAdapter.VH>(list) {
inner class VH(var binding: ListItemSearchBinding) : QuickViewHolder(binding.root) inner class VH(var binding: ListItemSearchBinding) : QuickViewHolder(binding.root)
@@ -24,10 +24,10 @@ class SearchAdapter(list: MutableList<SearchModel>) :
return VH(binding) return VH(binding)
} }
override fun onBindViewHolder(holder: VH, position: Int, item: SearchModel?) { override fun onBindViewHolder(holder: VH, position: Int, item: GoodsModel?) {
val binding = holder.binding val binding = holder.binding
binding.btnFoodName.run { binding.btnFoodName.run {
text = item!!.foodName text = " ${item!!.goodsName}"
setTextColor( setTextColor(
getColor(if (item.isClicked) R.color.shelf_name_blue else R.color.black999) getColor(if (item.isClicked) R.color.shelf_name_blue else R.color.black999)
) )
@@ -10,6 +10,11 @@ import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.intelligent.shelves.R import com.shuwei.intelligent.shelves.R
import com.shuwei.intelligent.shelves.databinding.ListItemShelfBinding import com.shuwei.intelligent.shelves.databinding.ListItemShelfBinding
import com.shuwei.intelligent.shelves.model.ShelfModel import com.shuwei.intelligent.shelves.model.ShelfModel
import com.shuwei.intelligent.shelves.utils.DateTimeUtil
import com.shuwei.intelligent.shelves.utils.ext.gone
import com.shuwei.intelligent.shelves.utils.ext.visible
import java.util.Date
import kotlin.math.roundToInt
class ShelfAdapter(list: MutableList<ShelfModel>) : class ShelfAdapter(list: MutableList<ShelfModel>) :
BaseQuickAdapter<ShelfModel, ShelfAdapter.VH>(list) { BaseQuickAdapter<ShelfModel, ShelfAdapter.VH>(list) {
@@ -22,12 +27,46 @@ class ShelfAdapter(list: MutableList<ShelfModel>) :
return VH(binding) return VH(binding)
} }
private fun stringToDate(createTime: String?): Date? {
if (createTime.isNullOrBlank()) {
return null
}
return DateTimeUtil.stringToDate(createTime)
}
override fun onBindViewHolder(holder: VH, position: Int, item: ShelfModel?) { override fun onBindViewHolder(holder: VH, position: Int, item: ShelfModel?) {
val shelfNo = item!!.shelfNo val shelfNo = item!!.deviceNo
item.shelfName = "货架-${if (shelfNo < 10) "0${shelfNo}" else "$shelfNo" }" item.shelfName = "货架-${if (shelfNo < 10) "0${shelfNo}" else "$shelfNo"}"
val weight = item.foodWeight ?: 0 val weight = item.weight ?: 0.toDouble()
val binding = holder.binding val binding = holder.binding
val isBlankShelf = weight <= 0 if (item.overdueDay.isNullOrBlank()) {
binding.ivStaleFood.gone()
} else {
runCatching {
val shelfDate = stringToDate(item.createTime)
if (shelfDate == null) {
binding.ivStaleFood.gone()
} else {
val days = item.overdueDay!!.toInt()
val resultDate = DateTimeUtil.addDays(shelfDate, days)
if (resultDate.before(Date())) {
binding.ivStaleFood.visible()
} else {
binding.ivStaleFood.gone()
}
}
}.onFailure {
binding.ivStaleFood.gone()
}
}
//?.setImageResource()
binding.tvFoodWeight.run {
setTextColor(getColor(R.color.food_weight_orange))
//val showWeight = if (weight == 0.toDouble()) "0克" else "%.3f千克".format(weight)
text = "${(weight*1000).roundToInt()}"
}
//val isBlankShelf = weight <= 0
val isBlankShelf = item.goodsName.isNullOrBlank()
if (isBlankShelf) { if (isBlankShelf) {
binding.layoutCard.setCardBackgroundColor(getColor(R.color.bg_card_blue)) binding.layoutCard.setCardBackgroundColor(getColor(R.color.bg_card_blue))
binding.tvShelfName.run { binding.tvShelfName.run {
@@ -38,10 +77,10 @@ class ShelfAdapter(list: MutableList<ShelfModel>) :
setTextColor(getColor(R.color.white)) setTextColor(getColor(R.color.white))
text = "" text = ""
} }
binding.tvFoodWeight.run { // binding.tvFoodWeight.run {
setTextColor(getColor(R.color.food_weight_blue)) // setTextColor(getColor(R.color.food_weight_blue))
text = "0千克" // text = "0千克"
} // }
binding.tvStoreDate.run { binding.tvStoreDate.run {
setTextColor(getColor(R.color.food_weight_blue)) setTextColor(getColor(R.color.food_weight_blue))
text = "-" text = "-"
@@ -55,15 +94,16 @@ class ShelfAdapter(list: MutableList<ShelfModel>) :
} }
binding.tvFoodName.run { binding.tvFoodName.run {
setTextColor(getColor(R.color.food_name_black)) setTextColor(getColor(R.color.food_name_black))
text = item.foodName text = item.goodsName
}
binding.tvFoodWeight.run {
setTextColor(getColor(R.color.food_weight_orange))
text = "${weight/1000F}千克"
} }
// binding.tvFoodWeight.run {
// setTextColor(getColor(R.color.food_weight_orange))
//// text = "${weight/1000F}千克"
// text = "${weight}克"
// }
binding.tvStoreDate.run { binding.tvStoreDate.run {
setTextColor(getColor(R.color.black999)) setTextColor(getColor(R.color.black999))
text = item.storeDate text = item.createTime
} }
} }
@@ -1,14 +1,21 @@
package com.shuwei.intelligent.shelves.base package com.shuwei.intelligent.shelves.base
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View import android.view.View
import android.view.WindowInsets
import android.view.WindowInsetsController
import android.widget.TextView import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.gyf.immersionbar.BarHide
import com.gyf.immersionbar.ImmersionBar
import com.shuwei.intelligent.shelves.HomeActivity
import com.shuwei.intelligent.shelves.R import com.shuwei.intelligent.shelves.R
import com.shuwei.intelligent.shelves.databinding.ActivityBaseBinding import com.shuwei.intelligent.shelves.databinding.ActivityBaseBinding
@@ -33,7 +40,7 @@ open class BaseActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityBaseBinding.inflate(layoutInflater) binding = ActivityBaseBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
statusBarDarkFont(enable = false) statusBarDarkFont()
launcher = launcher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) { if (result.resultCode == RESULT_OK) {
@@ -41,28 +48,39 @@ open class BaseActivity : AppCompatActivity() {
} }
} }
// window.setDecorFitsSystemWindows(false) // 启用 Edge-to-Edge // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// window.setDecorFitsSystemWindows(false)
// window.insetsController?.apply { // window.insetsController?.apply {
// hide(WindowInsets.Type.statusBars()) // 隐藏状态栏 // hide(WindowInsets.Type.statusBars()) // 隐藏状态栏
// systemBarsBehavior = // systemBarsBehavior =
// WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // 滑动时临时显示 // WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // 滑动时临时显示
// } // }
// }
} }
fun hideStatusBar() { fun hideStatusBar() {
enableEdgeToEdge() // enableEdgeToEdge()
// val uiOptions = (View.SYSTEM_UI_FLAG_FULLSCREEN // 隐藏状态栏 // val uiOptions = (View.SYSTEM_UI_FLAG_FULLSCREEN // 隐藏状态栏
// or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) // 隐藏导航栏(可选) // or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) // 隐藏导航栏(可选)
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN // window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
ImmersionBar.with(this)
.hideBar(BarHide.FLAG_HIDE_STATUS_BAR)
.init()
} }
fun statusBarDarkFont(enable: Boolean) { fun statusBarDarkFont() {
//window.decorView.systemUiVisibility = if (enable) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else 0 //window.decorView.systemUiVisibility = if (enable) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else 0
val color = ContextCompat.getColor(this, R.color.white) val color = ContextCompat.getColor(this, R.color.white)
binding.tvLeftStatus.setTextColor(color) binding.tvLeftStatus.setTextColor(color)
binding.tvRightStatus.setTextColor(color) binding.tvRightStatus.setTextColor(color)
} }
fun setBackground() {
binding.root.setBackgroundColor(ContextCompat.getColor(this,R.color.bg_page))
}
override fun setContentView(view: View?) { override fun setContentView(view: View?) {
if (view == binding.root) { if (view == binding.root) {
super.setContentView(view) super.setContentView(view)
@@ -79,5 +97,53 @@ open class BaseActivity : AppCompatActivity() {
binding.tvRightStatus.text = data binding.tvRightStatus.text = data
} }
fun addViewClick(view:View, click: () -> Unit) {
view.setOnClickListener {
click()
}
}
fun getLeftView(): TextView {
return binding.tvLeftStatus
}
fun addLeftClick(click: (View) -> Unit) {
binding.tvLeftStatus.setOnClickListener(click)
}
fun addRightClick(click: (View) -> Unit) {
binding.tvRightStatus.setOnClickListener(click)
}
// 5分钟
private val TIME_OUT: Long = (5 * 60 * 1000).toLong()
private val mHandler by lazy { Handler(Looper.getMainLooper()) }
private val mTimeoutRunnable = Runnable {
if (this is HomeActivity) {
this.switchLight(false)
}
}
override fun onUserInteraction() {
super.onUserInteraction()
// 重置定时器
mHandler.removeCallbacks(mTimeoutRunnable)
mHandler.postDelayed(mTimeoutRunnable, TIME_OUT)
}
override fun onResume() {
super.onResume()
// 启动定时器
mHandler.postDelayed(mTimeoutRunnable, TIME_OUT)
}
override fun onPause() {
super.onPause()
// 取消定时器
mHandler.removeCallbacks(mTimeoutRunnable)
}
fun timeOutOperation() {
}
} }
@@ -0,0 +1,6 @@
package com.shuwei.intelligent.shelves.model
class DeviceConfigInfo {
var appPackageUrl:String? = null
var canteenId:String? = null
}
@@ -0,0 +1,10 @@
package com.shuwei.intelligent.shelves.model
import java.io.Serializable
data class GoodsModel(
var goodsId: String? = null,
var goodsName: String? = null,
var overdueDay: String? = null,
var isClicked: Boolean = false
) : Serializable
@@ -0,0 +1,8 @@
package com.shuwei.intelligent.shelves.model
data class GoodsRecord(
val total: Int = 0,
val size: Int = 0,
val page: Int = 0,
val records: MutableList<GoodsModel>? = null
)
@@ -1,9 +0,0 @@
package com.shuwei.intelligent.shelves.model
import java.io.Serializable
data class SearchModel(
var foodId: Int? = null,
var foodName: String? = null,
var isClicked: Boolean = false
) : Serializable
@@ -0,0 +1,10 @@
package com.shuwei.intelligent.shelves.model
data class SendWeightEvent(
var shelfNo: Int = 0,
var weight:Int=0
)
data class WeightEvent(var weight: Int)
data class ClearShelfEvent(var shelfNo: Int)
@@ -0,0 +1,11 @@
package com.shuwei.intelligent.shelves.model
class ShelfBody {
var deviceId: String = ""
var canteenId: String = ""
var temperature: String? = null
var humidity: String = "0"
var goodsList: List<ShelfModel>? = null
}
@@ -3,9 +3,15 @@ package com.shuwei.intelligent.shelves.model
import java.io.Serializable import java.io.Serializable
data class ShelfModel( data class ShelfModel(
var shelfNo: Int = 0, var id: String? = null,
var deviceNo: Int = 0,
var shelfName: String? = null, var shelfName: String? = null,
var foodName: String? = null, var goodsId: String = "",
var foodWeight: Int? = null, var goodsName: String? = null,
var storeDate: String? = null var deviceId: String? = null,
var weight: Double? = null,
var createTime: String? = null,
var overdueDay: String? = null,
var temperature: String? = null,
var humidity: String = "0",
) : Serializable ) : Serializable
@@ -0,0 +1,7 @@
package com.shuwei.intelligent.shelves.model
data class ShelfResult(
val placeId: String = "",
val canteenName: String = "",
val containerGoodsList: List<ShelfModel>? = null
)
@@ -0,0 +1,70 @@
package com.shuwei.intelligent.shelves.net
import com.shuwei.intelligent.shelves.App
import com.shuwei.intelligent.shelves.model.DeviceConfigInfo
import com.shuwei.intelligent.shelves.model.GoodsModel
import com.shuwei.intelligent.shelves.model.GoodsRecord
import com.shuwei.intelligent.shelves.model.ShelfBody
import com.shuwei.intelligent.shelves.model.ShelfResult
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Query
import retrofit2.http.Url
interface ApiService {
/**
* device获取token
*/
@GET("/sys/getEquipmentToken")
suspend fun getDeviceToken(
@Query("qrcodeId") qrcodeId: String,
@Query("appVersion") appVersion: String = App.appVersion
): RespData<String>
/**
*获取配置信息
*/
@GET("/equipment/stEquipment/queryByEquipmentCode")
suspend fun getDeviceInfo(
@Query("equipmentCode") equipmentCode: String,
@Query("appVersion") appVersion: String = App.appVersion,
@Header("X-Access-Token") token: String
): RespData<DeviceConfigInfo>
@GET
suspend fun getAccessToken(
@Url url: String = UrlConfig.GET_ACCESS_TOKEN,
@Query("qrcodeId") qrcodeId: String,
@Query("x-access-token") token: String = App.accessToken
): RespData<String?>
@GET
suspend fun getShelfList(
@Url url: String = UrlConfig.GET_SHELF_LIST,
@Query("deviceId") deviceId: String,
@Query("x-access-token") token: String = App.accessToken,
@Header("authorization") authorization: String = "57ee87183f2a4fa59683ec9ef41c8f5d"
): RespData<ShelfResult>
@GET
suspend fun getGoodsList(
@Url url: String = UrlConfig.GET_GOODS_LIST,
@Query("canteenId") canteenId: String = "0",
@Query("goodsName") goodsName: String? = null,
@Query("pageNo") pageNo: Int = 1,
@Query("pageSize") pageSize: Int = 50,
@Query("x-access-token") token: String = App.accessToken,
@Header("authorization") authorization: String = "57ee87183f2a4fa59683ec9ef41c8f5d"
): RespData<MutableList<GoodsModel>?>
@POST
suspend fun saveShelfGoodsList(
@Url url: String = UrlConfig.SAVE_SHELF_GOODS_LIST,
@Body body: ShelfBody,
@Query("x-access-token") token: String = App.accessToken,
@Header("authorization") authorization: String = "57ee87183f2a4fa59683ec9ef41c8f5d"
): RespData<Any?>
}
@@ -0,0 +1,88 @@
package com.shuwei.intelligent.shelves.net
import android.annotation.SuppressLint
import android.util.Log
import com.shuwei.intelligent.shelves.App
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import javax.net.ssl.*
import java.security.SecureRandom
import java.security.cert.X509Certificate
import kotlin.apply
val apiService: ApiService = Retrofit.Builder()
// .baseUrl(UrlConfig.BASE_URL)
.baseUrl(UrlConfig.DEVICE_BASE_URL)
.client(HttpManager.instance.client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
class HttpManager private constructor() {
val client: OkHttpClient by lazy {
OkHttpClient.Builder()
.apply {
connectTimeout(15, TimeUnit.SECONDS)
readTimeout(30, TimeUnit.SECONDS)
writeTimeout(15, TimeUnit.SECONDS)
sslSocketFactory(createSSLSocketFactory(), TrustAllCerts())
hostnameVerifier { _, _ -> true }
addInterceptor(LoggingInterceptor())
// addInterceptor { chain ->
// val request = chain.request().newBuilder()
// .header("x-access-token", App.accessToken)
// .build()
// chain.proceed(request)
// }
}
.build()
}
companion object {
val instance by lazy { HttpManager() }
}
// fun newCall(request: Request): Call = client.newCall(request)
inner class LoggingInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
// 打印请求日志
Log.d("OkHttp", "--> ${request.method},${request.url}")
val response = chain.proceed(request)
// 打印响应日志
Log.d("OkHttp", "<-- ${response.code},${response.request.url}")
return response
}
}
// 信任所有证书的TrustManager实现
@SuppressLint("CustomX509TrustManager")
class TrustAllCerts : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
@SuppressLint("TrustAllX509TrustManager")
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
// 创建信任所有证书的SSLSocketFactory
fun createSSLSocketFactory(): SSLSocketFactory {
val sslContext = SSLContext.getInstance("TLS").apply {
init(null, arrayOf(TrustAllCerts()), SecureRandom())
}
return sslContext.socketFactory
}
}
@@ -0,0 +1,62 @@
package com.shuwei.intelligent.shelves.net
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.WindowManager
import androidx.core.graphics.drawable.toDrawable
import com.shuwei.intelligent.shelves.R
import com.shuwei.intelligent.shelves.databinding.DialogLoadingBinding
import kotlin.let
import kotlin.run
object Loading {
private var dialog: LoadingDialog? = null
fun show(context: Context) {
if (dialog?.isShowing == true) {
dialog?.dismiss()
}
if (dialog == null) {
dialog = LoadingDialog(context)
}
dialog?.show()
}
fun dismiss() {
dialog?.let {
if (it.isShowing) {
it.dismiss()
}
}
dialog = null
}
}
class LoadingDialog(
context: Context,
message: String = "加载中……",
private var onDismiss: () -> Unit = {}
) : Dialog(context, R.style.LoadingDialog) {
init {
val binding = DialogLoadingBinding.inflate(LayoutInflater.from(context))
binding.tvMessage.text = message
setContentView(binding.root)
setCancelable(true)
window?.run {
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
);
}
setOnDismissListener {
onDismiss()
}
}
}
@@ -0,0 +1,149 @@
package com.shuwei.intelligent.shelves.net
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.shuwei.intelligent.shelves.model.ShelfBody
import com.shuwei.intelligent.shelves.net.HttpManager.Companion.instance
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class NetViewModel : ViewModel() {
// val apiService: ApiService = HttpManager.instance.apiService
// val apiService: ApiService = Retrofit.Builder()
// .baseUrl(UrlConfig.BASE_URL)
// .client(HttpManager.instance.client)
// .addConverterFactory(GsonConverterFactory.create())
// .build()
// .create(ApiService::class.java)
private val _getShelfListUiState = MutableStateFlow<UiState>(UiState.Initial)
val getShelfListUiState: StateFlow<UiState> = _getShelfListUiState
// private val _saveShelfGoodsListUiState = MutableStateFlow<UiState>(UiState.Initial)
// val saveShelfGoodsListUiState: StateFlow<UiState> = _saveShelfGoodsListUiState
private val _getGoodsListUiState = MutableStateFlow<UiState>(UiState.Initial)
val getGoodsListUiState: StateFlow<UiState> = _getGoodsListUiState
private val _getAccessTokenUiState = MutableStateFlow<UiState>(UiState.Initial)
val getAccessTokenUiState: StateFlow<UiState> = _getAccessTokenUiState
private val _getDeviceTokenUiState = MutableStateFlow<UiState>(UiState.Initial)
val getDeviceTokenUiState: StateFlow<UiState> = _getDeviceTokenUiState
private val _getDeviceConfigUiState = MutableStateFlow<UiState>(UiState.Initial)
val getDeviceConfigUiState: StateFlow<UiState> = _getDeviceConfigUiState
fun getDeviceToken(deviceId: String) {
viewModelScope.launch {
_getDeviceTokenUiState.value = UiState.Loading
runCatching {
val response = apiService.getDeviceToken(qrcodeId = deviceId)
if (response.code == 0) {
_getDeviceTokenUiState.value = UiState.Success(response)
} else {
_getDeviceTokenUiState.value = UiState.Error(response.msg ?: "请求失败")
}
}.onFailure {
_getDeviceTokenUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
fun getDeviceConfig(deviceId: String, deviceToken: String) {
viewModelScope.launch {
_getDeviceTokenUiState.value = UiState.Loading
runCatching {
val response =
apiService.getDeviceInfo(equipmentCode = deviceId, token = deviceToken)
if (response.code == 0) {
_getDeviceTokenUiState.value = UiState.Success(response)
} else {
_getDeviceTokenUiState.value = UiState.Error(response.msg ?: "请求失败")
}
}.onFailure {
_getDeviceTokenUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
fun getAccessToken(deviceId: String) {
viewModelScope.launch {
_getAccessTokenUiState.value = UiState.Loading
runCatching {
val response = apiService.getAccessToken(qrcodeId = deviceId)
if (response.code == 0) {
_getAccessTokenUiState.value = UiState.Success(response)
} else {
_getAccessTokenUiState.value = UiState.Error(response.msg ?: "请求失败")
}
}.onFailure {
_getAccessTokenUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
fun getShelfList(deviceId: String) {
viewModelScope.launch {
_getShelfListUiState.value = UiState.Loading
runCatching {
val response = apiService.getShelfList(deviceId = deviceId)
if (response.code == 0) {
_getShelfListUiState.value = UiState.Success(response)
} else {
_getShelfListUiState.value = UiState.Error(response.msg ?: "请求失败")
}
}.onFailure {
_getShelfListUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
// fun saveShelfGoodsList(body: ShelfBody) {
// viewModelScope.launch {
// _saveShelfGoodsListUiState.value = UiState.Loading
// runCatching {
// val response = apiService.saveShelfGoodsList(body)
// if (response.success) {
// _saveShelfGoodsListUiState.value = UiState.Success(response)
// } else {
// _saveShelfGoodsListUiState.value = UiState.Error(response.message ?: "请求失败")
// }
// }.onFailure {
// _saveShelfGoodsListUiState.value = UiState.Error(it.message ?: "请求异常")
// }
// }
// }
fun getGoodsList(
canteenId: String = "",
goodsName: String = "",
pageNo: Int = 1,
pageSize: Int = 50,
) {
viewModelScope.launch {
_getGoodsListUiState.value = UiState.Loading
runCatching {
val response = apiService.getGoodsList(
canteenId = canteenId,
goodsName = goodsName,
pageNo = pageNo,
pageSize = pageSize
)
if (response.code == 0) {
_getGoodsListUiState.value = UiState.Success(response)
} else {
_getGoodsListUiState.value = UiState.Error(response.msg ?: "请求失败")
}
}.onFailure {
_getGoodsListUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
}
@@ -0,0 +1,9 @@
package com.shuwei.intelligent.shelves.net
data class RespData<T>(
// val success: Boolean = false,
val msg: String? = null,
val code: Int = 0,
val data: T? = null,
val total: Int
)
@@ -0,0 +1,8 @@
package com.shuwei.intelligent.shelves.net
sealed class UiState {
object Initial : UiState()
object Loading : UiState()
data class Success<T>(val data: RespData<T>) : UiState()
data class Error(val msg: String) : UiState()
}
@@ -0,0 +1,29 @@
package com.shuwei.intelligent.shelves.net
import com.shuwei.intelligent.shelves.App
object UrlConfig {
const val DEVICE_BASE_URL = "http://device.shuziweidao.com:8889"
// /**
// * device获取token
// */
// const val DEVICE_TOKEN = "${DEVICE_BASE_URL}/sys/getEquipmentToken"
// /**
// *获取配置信息
// */
// const val DEVICE_CONFIG = "${DEVICE_BASE_URL}/equipment/stEquipment/queryByEquipmentCode"
const val BASE_URL = "http://dev.yixiong-tech.com:8081"
// const val BASE_URL = "https://yyjk.shuziweidao.com/gateway"
// const val BASE_URL = "http://192.168.1.201:14801"
var GET_ACCESS_TOKEN = "${App.configUrl}/restaurant/equipment/stEquipment/getEquipmentToken"
var GET_SHELF_LIST =
"${App.configUrl}/terminal/neglect/smartShelves/app/smartShelves/app/getShelvesListByDeviceId"
var GET_GOODS_LIST =
"${App.configUrl}/terminal/neglect/smartShelves/app/smartShelves/app/getGoodsPageList"
var SAVE_SHELF_GOODS_LIST =
"${App.configUrl}/terminal/neglect/smartShelves/app/smartShelves/app/saveShelvesGoodsList"
}
@@ -1,11 +1,13 @@
package com.shuwei.intelligent.shelves.serial package com.shuwei.intelligent.shelves.serial
import android.annotation.SuppressLint
import com.shuwei.intelligent.shelves.utils.hexToBytes import com.shuwei.intelligent.shelves.utils.hexToBytes
import com.shuwei.intelligent.shelves.utils.toHexString2 import com.shuwei.intelligent.shelves.utils.toHexString2
import io.github.jeadyx.jserialport.AndroidSerialPort import io.github.jeadyx.jserialport.AndroidSerialPort
import io.github.jeadyx.jserialport.SerialPort import io.github.jeadyx.jserialport.SerialPort
import io.github.jeadyx.jserialport.SerialPortFactory import io.github.jeadyx.jserialport.SerialPortFactory
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collectLatest
import java.nio.charset.Charset import java.nio.charset.Charset
import java.util.Locale import java.util.Locale
@@ -38,7 +40,6 @@ object SerialPortManager {
// 发送数据 // 发送数据
suspend fun send(data: String): Boolean { suspend fun send(data: String): Boolean {
return try { return try {
// serialPort?.write(data.toByteArray())
serialPort?.write(data.hexToBytes()) serialPort?.write(data.hexToBytes())
true true
} catch (e: Exception) { } catch (e: Exception) {
@@ -48,14 +49,20 @@ object SerialPortManager {
} }
// 启动接收协程 // 启动接收协程
@Suppress("DEPRECATION")
@SuppressLint("DefaultLocale")
fun startReceive(callback: (String) -> Unit) { fun startReceive(callback: (String) -> Unit) {
scope.launch { scope.launch {
while (isActive) { while (isActive) {
serialPort?.read()?.collect { buffer -> try {
// val data = String(buffer) val flow = serialPort?.read()
flow?.collect { buffer ->
val data = buffer.toHexString2().toUpperCase() val data = buffer.toHexString2().toUpperCase()
callback(data) callback(data)
} }
} catch (e: Exception) {
e.printStackTrace()
}
delay(50) delay(50)
} }
} }
@@ -0,0 +1,32 @@
package com.shuwei.intelligent.shelves.task
import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.shuwei.intelligent.shelves.HomeActivity
import com.shuwei.intelligent.shelves.serial.SerialPortManager
class SyncDeviceTask(appContext: Context, workerParams: WorkerParameters) :
CoroutineWorker(appContext, workerParams) {
companion object {
private const val TAG = "SyncDeviceTask"
}
override suspend fun doWork(): Result {
return try {
// 执行后台任务逻辑
Log.d(TAG, "doWork: ----------SyncDeviceTask----------")
SerialPortManager.send(HomeActivity.DEVICE_INFO_CMD)
TaskManager.startDeviceTask()
Result.success()
} catch (e: Exception) {
e.printStackTrace()
Result.retry()
}
}
}
@@ -4,7 +4,10 @@ import android.content.Context
import android.util.Log import android.util.Log
import androidx.work.CoroutineWorker import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.shuwei.intelligent.shelves.App
import com.shuwei.intelligent.shelves.HomeActivity import com.shuwei.intelligent.shelves.HomeActivity
import com.shuwei.intelligent.shelves.model.ShelfBody
import com.shuwei.intelligent.shelves.net.apiService
import com.shuwei.intelligent.shelves.utils.ext.toJsonString import com.shuwei.intelligent.shelves.utils.ext.toJsonString
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -34,6 +37,21 @@ class SyncTask(appContext: Context, workerParams: WorkerParameters) :
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val list = HomeActivity.list val list = HomeActivity.list
Log.d(TAG, "performSync: list:${list.toJsonString()}") Log.d(TAG, "performSync: list:${list.toJsonString()}")
val submitList = list.sortedBy { it.deviceNo }
// submitList.forEach {
// it.temperature = HomeActivity.showTemperatureC
// it.humidity = HomeActivity.showHumidity
// }
val body = ShelfBody().also {
it.deviceId = App.deviceId ?: ""
it.canteenId = App.canteenId
it.temperature = HomeActivity.showTemperatureC
it.humidity = HomeActivity.showHumidity
it.goodsList = submitList
}
Log.d(TAG, "performSync: body:${body.toJsonString()}")
val resp = apiService.saveShelfGoodsList(body = body)
Log.d(TAG, "performSync: resp:${resp.toJsonString()}")
} }
} }
@@ -8,14 +8,15 @@ import java.util.concurrent.TimeUnit
object TaskManager { object TaskManager {
const val TASK_NAME = "IntelligentShelvesSyncTask" const val TASK_NAME = "IntelligentShelvesSyncTask"
const val DEVICE_TASK_NAME = "IntelligentShelvesDeviceTask"
fun startTask() { fun startTask() {
val nextRequest = OneTimeWorkRequestBuilder<SyncTask>() val nextRequest = OneTimeWorkRequestBuilder<SyncTask>()
.setInitialDelay(3, TimeUnit.MINUTES) .setInitialDelay(2, TimeUnit.MINUTES)
// .setInitialDelay(10, TimeUnit.SECONDS) // .setInitialDelay(30, TimeUnit.SECONDS)
// .setInputData(inputData) // .setInputData(inputData)
.build() .build()
WorkManager.getInstance(App.get()) WorkManager.getInstance(App.getInstance())
.enqueueUniqueWork(TASK_NAME, ExistingWorkPolicy.REPLACE, nextRequest) .enqueueUniqueWork(TASK_NAME, ExistingWorkPolicy.REPLACE, nextRequest)
// val constraints = Constraints.Builder() // val constraints = Constraints.Builder()
@@ -37,8 +38,21 @@ object TaskManager {
} }
fun cancelTask() { fun cancelTask() {
WorkManager.getInstance(App.get()) WorkManager.getInstance(App.getInstance())
.cancelUniqueWork(TASK_NAME) .cancelUniqueWork(TASK_NAME)
} }
fun startDeviceTask() {
val nextRequest = OneTimeWorkRequestBuilder<SyncDeviceTask>()
.setInitialDelay(2, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(App.getInstance())
.enqueueUniqueWork(DEVICE_TASK_NAME, ExistingWorkPolicy.REPLACE, nextRequest)
}
fun cancelDeviceTask() {
WorkManager.getInstance(App.getInstance())
.cancelUniqueWork(DEVICE_TASK_NAME)
}
} }
@@ -0,0 +1,749 @@
package com.shuwei.intelligent.shelves.utils;
import static android.content.Context.TELEPHONY_SERVICE;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.core.content.FileProvider;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.NetworkInterface;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
public class AppUtil {
public static String getAppPackageName(Context context) {
String packageName = "";
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
packageName = pi.packageName;
if (AppUtil.isEmpty(packageName)) {
return "";
}
} catch (Exception e) {
e.printStackTrace();
}
return packageName;
}
public static String getAppVersionName(Context context) {
String versionName = "";
// int versioncode=1;
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
versionName = pi.versionName;
// versioncode = pi.versionCode;表示更新了多少次
if (versionName == null || versionName.length() <= 0) {
return "";
}
} catch (Exception e) {
e.printStackTrace();
}
return versionName;
}
public static int getAppVersionCode(Context context) {
int versioncode = 1;
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
versioncode = pi.versionCode;
} catch (Exception e) {
e.printStackTrace();
}
return versioncode;
}
//判断微信是否安装
public static boolean isWeixinInstalled(Context context) {
final PackageManager packageManager = context.getPackageManager();// 获取packagemanager
List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息
if (pinfo != null) {
for (int i = 0; i < pinfo.size(); i++) {
String pn = pinfo.get(i).packageName;
if (pn.equals("com.tencent.mm")) {
return true;
}
}
}
return false;
}
/**
* 打电话
* <p>
* Intent.ACTION_DIAL Intent.ACTION_CALL
*
* @param context
* @param mobile
*/
public static void callUp(Context context, String mobile) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"
+ mobile));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 获取设备ID
*
* @param context
* @return
*/
public static String getDevId(Context context) {
TelephonyManager TelephonyMgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
return TelephonyMgr.getDeviceId();
}
/**
* 姓名脱敏
*
* @param fullName
* @return
*/
public static String desensitizedName(String fullName) {
if (fullName == null || fullName.length() <= 1) {
return fullName;
}
char[] nameArr = fullName.toCharArray();
if (nameArr.length > 2) {
for (int i = 1; i < nameArr.length - 1; i++) {
nameArr[i] = '*';
}
} else {
nameArr[1] = '*';
}
return new String(nameArr);
}
public static String formatDateGetFull(String date) {
if (isEmpty(date)) {
return "";
}
Date d = new Date(Long.parseLong(date));
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
return dateFormat1.format(d);
}
public static String formatDateGetCurrentTime() {
Date d = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//.SSS
return dateFormat1.format(d);
}
public static String formatDateGetFull(long date) {
if (date == 0) {
return "";
}
Date d = new Date(date);
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return dateFormat1.format(d);
}
public static String formatDateGetDay(long date) {
if (date == 0) {
return "";
}
Date d = new Date(date);
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
return dateFormat1.format(d);
}
public static boolean isEmpty(String s) {
if (TextUtils.isEmpty(s) || s.trim().equals("null")) {
return true;
} else {
return false;
}
}
/**
* 格式化浮点型
*
* @param data
* @return
*/
public static String formatDouble(double data) {
return new DecimalFormat("0.00").format(data);
}
/**
* 格式化分钟
*
* @param minutes
* @return
*/
public static String formatMinutes(int minutes) {
int hour = minutes / 60;
int minute = minutes % 60;
if (hour > 0 && minute > 0) {
return hour + "小时" + minute + "分钟";
} else if (hour > 0) {
return hour + "小时";
} else {
return minute + "分钟";
}
}
//com.fawan.news
public static void goToMarket(Context context, String packageName) {
Uri uri = Uri.parse("market://details?id=" + packageName);
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
try {
context.startActivity(goToMarket);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
/**
* true为存在,false为不存在
*
* @param context
* @param packageName
* @return
*/
public static boolean isInstallApp(Context context, String packageName) {
try {
context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
/**
* 格式化float 保留两位小数
*
* @param data
* @return
*/
public static float formatFloat2(float data) {
// DecimalFormat decimalFormat = new DecimalFormat("0.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
// return decimalFormat.format(data);//返回字符串
int scale = 1;//设置位数
int roundingMode = 4;//表示四舍五入,可以选择其他舍值方式,例如去尾,等等.
BigDecimal bd = new BigDecimal((double) data);
bd = bd.setScale(scale, roundingMode);
data = bd.floatValue();
return data;
}
/**
* Android 6.0 之前(不包括6.0)获取mac地址
* 必须的权限 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
*
* @param context * @return
*/
public static String getMacDefault(Context context) {
String mac = "";
if (context == null) {
return mac;
}
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = null;
try {
info = wifi.getConnectionInfo();
} catch (Exception e) {
e.printStackTrace();
}
if (info == null) {
return null;
}
mac = info.getMacAddress();
if (!TextUtils.isEmpty(mac)) {
mac = mac.toUpperCase(Locale.ENGLISH);
}
return mac;
}
/**
* Android 6.0-Android 7.0 获取mac地址
*/
public static String getMacAddress() {
String macSerial = null;
String str = "";
try {
Process pp = Runtime.getRuntime().exec("cat/sys/class/net/wlan0/address");
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
while (null != str) {
str = input.readLine();
if (str != null) {
macSerial = str.trim();//去空格
break;
}
}
} catch (IOException ex) {
// 赋予默认值
ex.printStackTrace();
}
return macSerial;
}
/**
* Android 7.0之后获取Mac地址
* 遍历循环所有的网络接口,找到接口是 wlan0
* 必须的权限 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
*
* @return
*/
public static String getMacFromHardware() {
try {
ArrayList<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equals("wlan0"))
continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) return "";
StringBuilder res1 = new StringBuilder();
for (Byte b : macBytes) {
res1.append(String.format("%02X:", b));
}
if (!TextUtils.isEmpty(res1)) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 获取mac地址(适配所有Android版本)
*
* @return
*/
public static String getMac(Context context) {
String mac = "";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mac = getMacDefault(context);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
mac = getMacAddress();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mac = getMacFromHardware();
}
return mac;
}
//把String转化为float
public static double convertToFloat(String number, double defaultValue) {
if (TextUtils.isEmpty(number)) {
return defaultValue;
}
try {
return Double.parseDouble(number);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 获取AndroidId
*
* @param context
* @return
*/
public static String getAndroidId(Context context) {
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
return androidId;
}
/**
* 获取设备唯一 UDID
*
* @param context
* @return
*/
@SuppressLint("MissingPermission")
public static String getUDID(Context context) {
return "test111";
// String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
// if (!androidID.equals("")) {
// try {
// if (!"9774d56d682e549c".equals(androidID)) {
// androidID = UUID.nameUUIDFromBytes(androidID.getBytes("utf8")).toString();
// } else {
// @SuppressLint("MissingPermission") final String deviceId = ((TelephonyManager) context.getSystemService(TELEPHONY_SERVICE)).getDeviceId();
// androidID = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")).toString() : UUID.randomUUID().toString();
// }
// } catch (UnsupportedEncodingException e) {
// throw new RuntimeException(e);
// }
// return androidID;
// }
//
// //需要权限 android.permission.READ_PHONE_STATE
// TelephonyManager TelephonyMgr = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
// String szImei = TelephonyMgr.getDeviceId();
// if (!szImei.equals("")) {
// return szImei;
// }
//
// //需要权限 android.permission.ACCESS_WIFI_STATE
// WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
// if (!m_szWLANMAC.equals("")) {
// return m_szWLANMAC;
// }
//
// //需要权限 android.permission.BLUETOOTH
// BluetoothAdapter m_BluetoothAdapter = null;
// m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// String m_szBTMAC = m_BluetoothAdapter.getAddress();
// if (!m_szBTMAC.equals("")) {
// return m_szBTMAC;
// }
// return getUniquePsuedoID();
}
//获得 Psuedo ID
public static String getUniquePsuedoID() {
String serial = null;
String m_szDevIDShort = "35" +
Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
Build.USER.length() % 10; //13 位
try {
serial = Build.class.getField("SERIAL").get(null).toString();
//API>=9 使用serial号
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
//serial需要一个初始化,随意值
serial = "serial";
}
//使用硬件信息拼凑出来的15位号码
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
public static String getCPUSerial() {
String line = "";
String TAG = "aaa";
Log.e(TAG, " get_quck_Sn() ");
Class<?> c = null;
try {
c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
line = (String) get.invoke(c, "ro.serialno");
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.e(TAG, " get_quck_Sn() " + line);
System.out.println("设备串号" + line);
return line;
}
/**
* 判断网络连接状态
*
* @param context
* @return
*/
public static boolean isNetworkConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
}
}
return false;
}
/**
* 判断WiFi连接状态
*
* @param context
* @return
*/
public static boolean isWifiConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWiFiNetworkInfo != null) {
return mWiFiNetworkInfo.isAvailable();
}
}
return false;
}
/**
* 判断移动网络状态
*
* @param context
* @return
*/
public static boolean isMobileConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (mMobileNetworkInfo != null) {
return mMobileNetworkInfo.isAvailable();
}
}
return false;
}
/**
* 获取网络连接类型
*
* @param context
* @return
*/
public static int getConnectedType(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
return mNetworkInfo.getType();
}
}
return -1;
}
/**
* 根据字符的起始和结束索引提取子串
*
* @param input 原始字符串
* @param startIndex 起始索引(包含,从0开始)
* @param endIndex 结束索引(不包含)
* @return 子串,若输入无效或索引越界则返回空字符串
*/
public static String getSubstringByIndices(String input, int startIndex, int endIndex) {
if (input == null) {
return "";
}
// 处理索引越界问题
int safeStart = Math.max(startIndex, 0);
int safeEnd = Math.min(endIndex, input.length());
if (safeStart > safeEnd) {
return "";
}
return input.substring(safeStart, safeEnd);
}
public static String getSubstringByIndex(String input, int startIndex, int length) {
if (input == null) {
return "";
}
// 处理索引越界问题
int safeStart = Math.max(startIndex, 0);
int safeEnd = Math.min(startIndex + length, input.length());
if (safeStart > safeEnd) {
return "";
}
return input.substring(safeStart, safeEnd);
}
/**
* 十进制转十六进制
*
* @param decimal
* @return
*/
public static String decimalToHexWithPadding(int decimal, int padding) {
// 将十进制转换为十六进制,并转换为字符串
String hex = Integer.toHexString(decimal);
// 确保字符串长度为至少4位,不足部分前面补0
while (hex.length() < padding) {
hex = "0" + hex;
}
return hex.toUpperCase(); // 返回大写形式的十六进制字符串
}
/**
* 十进制转二进制,且返回的二进制为至少7位数
*
* @param decimal
* @return
*/
public static String decimalToBinary(int decimal) {
// 如果输入为0,直接返回"0"
if (decimal == 0) {
return "0";
}
StringBuilder binary = new StringBuilder();
// 除2取余法,将余数加入二进制字符串
while (decimal > 0) {
int remainder = decimal % 2;
binary.insert(0, remainder);
decimal = decimal / 2;
}
int length = binary.length();
if (length < 7) {
int padding = 7 - length;
for (int i = 0; i < padding; i++) {
binary.insert(0, '0');
}
}
return binary.toString();
}
/**
* 将二进制字符串转换为十六进制字符串,每8位转换为两位十六进制,不足两位前面补零
*
* @param binaryStr 输入的二进制字符串(仅包含0和1)
* @return 转换后的十六进制字符串
* @throws IllegalArgumentException 如果输入不是有效的二进制字符串
*/
public static String binaryToHex(String binaryStr) {
// 校验输入合法性
if (binaryStr == null || !binaryStr.matches("[01]+")) {
throw new IllegalArgumentException("Invalid binary string");
}
// 补前导零使长度成为8的倍数
int length = binaryStr.length();
int padding = (8 - (length % 8)) % 8; // 计算需要补零的数量
StringBuilder paddedBinary = new StringBuilder();
for (int i = 0; i < padding; i++) {
paddedBinary.append('0');
}
paddedBinary.append(binaryStr);
// 每8位转换为两位十六进制
StringBuilder hexStr = new StringBuilder();
for (int i = 0; i < paddedBinary.length(); i += 8) {
String byteStr = paddedBinary.substring(i, i + 8);
int decimalValue = Integer.parseInt(byteStr, 2);
hexStr.append(String.format("%02X", decimalValue & 0xFF));
}
return hexStr.toString();
}
/**
* 数据校验 异或处理
*/
public static String getXor(String content) {
int a = 0;
for (int i = 0; i < content.length() / 2; i++) {
a = a ^ Integer.parseInt(content.substring(i * 2, (i * 2) + 2), 16);
}
String result = Integer.toHexString(a).toUpperCase();
if (result.length() == 1) {
return "0" + result;
} else {
return result;
}
}
public static double formatPersonInfo(String input, int startIndex, int length) {
if (input == null) {
return 0;
}
// 处理索引越界问题
int safeStart = Math.max(startIndex, 0);
int safeEnd = Math.min(startIndex + length, input.length());
if (safeStart > safeEnd) {
return 0;
}
String result = input.substring(safeStart, safeEnd);
double num = Integer.parseInt(result, 16);
return num;
}
/**
* 安装apk
*
* @param activity
* @param apkFile
*/
public static void installApk(Context activity, File apkFile) {
//文件有所有者概念,现在是属于当前进程的,需要把这个文件暴露给系统安装程序(其他进程)去安装
//因此,可能会存在权限问题,需要做下面的设置
//如果文件是sdcard上的,就不需要这个操作了
try {
apkFile.setExecutable(true, false);
apkFile.setReadable(true, false);
apkFile.setWritable(true, false);
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
Uri uri;
//TODO N FileProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileProvider", apkFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} else {
uri = Uri.fromFile(apkFile);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
activity.startActivity(intent);
//TODO 0 INSTALL PERMISSION
//在AndroidManifest中加入权限即可
}
}
@@ -0,0 +1,18 @@
package com.shuwei.intelligent.shelves.utils
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.shuwei.intelligent.shelves.InitActivity
import kotlin.jvm.java
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (Intent.ACTION_BOOT_COMPLETED == intent.action) {
// 启动服务或Activity
val launchIntent = Intent(context, InitActivity::class.java)
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(launchIntent)
}
}
}
@@ -1,9 +1,11 @@
package com.shuwei.intelligent.shelves.utils package com.shuwei.intelligent.shelves.utils
import androidx.annotation.NonNull
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -19,6 +21,19 @@ object DateTimeUtil {
return sdf.format(dateTime) return sdf.format(dateTime)
} }
fun stringToDate(dateText: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date? {
val sdf = SimpleDateFormat(pattern, Locale.CHINA)
return sdf.parse(dateText)
}
fun addDays(date: Date, days: Int): Date {
val calendar = Calendar.getInstance().apply {
time = date
add(Calendar.DAY_OF_MONTH, days)
}
return calendar.time
}
// fun convert(dateStr: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date { // fun convert(dateStr: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date {
// val formatter = DateTimeFormatter.ofPattern(pattern) // val formatter = DateTimeFormatter.ofPattern(pattern)
// val ldt = LocalDateTime.parse(dateStr, formatter) // val ldt = LocalDateTime.parse(dateStr, formatter)
@@ -45,3 +45,49 @@ fun byteArrayToHexString(bytes: ByteArray): String {
fun String.hexToBytes(): ByteArray = hexStringToByteArray(this) fun String.hexToBytes(): ByteArray = hexStringToByteArray(this)
fun ByteArray.toHexString2(): String = byteArrayToHexString(this) fun ByteArray.toHexString2(): String = byteArrayToHexString(this)
fun hexToBinary(hex: String): String {
val hexToBinaryMap = mapOf(
'0' to "0000", '1' to "0001", '2' to "0010", '3' to "0011",
'4' to "0100", '5' to "0101", '6' to "0110", '7' to "0111",
'8' to "1000", '9' to "1001", 'A' to "1010", 'B' to "1011",
'C' to "1100", 'D' to "1101", 'E' to "1110", 'F' to "1111"
)
return hex.map { char ->
hexToBinaryMap[char] ?: throw IllegalArgumentException("非法十六进制字符: $char")
}.joinToString("")
}
fun binaryToHex(binary: String): String {
// 补齐到4的倍数长度(方便分组)
val paddedBinary = binary.padStart(
length = ((binary.length + 3) / 4) * 4,
padChar = '0'
)
// 每4位二进制对应1位十六进制
return paddedBinary.chunked(4).joinToString("") { nibble ->
when (nibble) {
"0000" -> "0"
"0001" -> "1"
"0010" -> "2"
"0011" -> "3"
"0100" -> "4"
"0101" -> "5"
"0110" -> "6"
"0111" -> "7"
"1000" -> "8"
"1001" -> "9"
"1010" -> "A"
"1011" -> "B"
"1100" -> "C"
"1101" -> "D"
"1110" -> "E"
"1111" -> "F"
else -> throw IllegalArgumentException("无效的二进制段: $nibble")
}
}
.trimStart('0') // 去除前导零
.ifEmpty { "0" } // 处理全零情况
}
@@ -0,0 +1,5 @@
package com.shuwei.intelligent.shelves.utils
fun f2C(fahrenheit: Double): Double {
return (fahrenheit - 32) * 5 / 9
}
@@ -13,5 +13,9 @@ object KeyboardUtil {
view.clearFocus() // 清除焦点避免键盘再次弹出 view.clearFocus() // 清除焦点避免键盘再次弹出
} }
fun hideKeyboard(view: View) {
val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
view.clearFocus() // 清除焦点避免键盘再次弹出
}
} }
@@ -0,0 +1,101 @@
package com.shuwei.intelligent.shelves.utils
import android.graphics.Bitmap
import android.graphics.Canvas
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 = Canvas(this)
canvas.drawBitmap(qrCode, 0f, 0f, null)
canvas.drawBitmap(scaledLogo, offset.toFloat(), offset.toFloat(), null)
}
}
}
@@ -0,0 +1,31 @@
package com.shuwei.intelligent.shelves.utils
import com.shuwei.intelligent.shelves.App
import com.shuwei.intelligent.shelves.utils.ext.put
import kotlin.to
object SpTool {
const val DEVICE_CONFIG_CACHE = "deviceConfigCache"
const val TOKEN = "token"
const val LAUNCH_PAGE_TYPE = "launchPageType"
const val DEVICE_ID = "deviceId"
val pref = App.getSharedPref()!!
fun put(key: String, value: Any) {
pref.put(key to value)
}
fun getInt(key: String, defValue: Int = 0): Int {
return pref.getInt(key, defValue)
}
fun getString(key: String, defValue: String? = ""): String {
return pref.getString(key, defValue) ?: ""
}
fun getBoolean(key: String, defValue: Boolean = false): Boolean {
return pref.getBoolean(key, defValue)
}
}
@@ -1,14 +0,0 @@
package com.shuwei.intelligent.shelves.utils
import android.widget.Toast
import com.shuwei.intelligent.shelves.App
//D6DADEDB0302000001000C06
object UIUtils {
fun toast(strRes: Int) {
Toast.makeText(App.get(), strRes, Toast.LENGTH_SHORT).show()
}
fun toast(str: String) {
Toast.makeText(App.get(), str, Toast.LENGTH_SHORT).show()
}
}
@@ -1,19 +0,0 @@
//package com.shuwei.intelligent.shelves.viewmodel
//
//import androidx.lifecycle.LiveData
//import androidx.lifecycle.MutableLiveData
//import androidx.lifecycle.ViewModel
//import com.shuwei.intelligent.shelves.model.ShelfModel
//
//class ShelfDataViewModel : ViewModel() {
//
// private val _shelfItems = MutableLiveData<MutableList<ShelfModel>>()
// val shelfItems: LiveData<MutableList<ShelfModel>> = _shelfItems
//
// fun updateItems(newItems: MutableList<ShelfModel>) {
// _shelfItems.value = newItems
// }
//
// fun getCurrentItems(): MutableList<ShelfModel> = _shelfItems.value ?: mutableListOf()
//
//}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- android:width="800dp"-->
<!-- android:height="1280dp"-->
<item>
<shape android:shape="rectangle">
<solid android:color="@color/bg_page" />
</shape>
</item>
<item
android:width="450dp"
android:height="430dp"
android:gravity="top|center_horizontal"
android:top="150dp">
<bitmap android:src="@drawable/img_init" android:scaleType="fitCenter"/>
</item>
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#30000000">
<item>
<shape android:shape="rectangle">
<solid android:color="#ff08C6DC" />
<corners android:radius="8dp" />
</shape>
</item>
</ripple>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- android:width="800dp"-->
<!-- android:height="1280dp"-->
<item>
<shape android:shape="rectangle">
<solid android:color="@color/bg_page" />
</shape>
</item>
<item
android:width="225dp"
android:height="215dp"
android:gravity="top|center_horizontal"
android:top="75dp">
<bitmap android:src="@drawable/img_init" android:scaleType="fitCenter"/>
</item>
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#90000000"/>
<corners android:radius="5dp"/>
</shape>
@@ -0,0 +1,45 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="@color/bg_page">
<FrameLayout
android:id="@+id/flStatusBar"
android:layout_width="match_parent"
android:layout_height="68dp"
android:paddingStart="25dp"
android:paddingEnd="25dp"
android:paddingTop="25dp">
<TextView
android:id="@+id/tv_left_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:layout_gravity="start"
android:textSize="24sp"
android:fontFamily="sans-serif-medium"
tools:text="1-1冷藏柜 -2°C / 87%" />
<TextView
android:id="@+id/tv_right_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:layout_gravity="end"
android:fontFamily="sans-serif-medium"
android:textSize="24sp"
tools:text="6月22日 星期日 15:26:33" />
</FrameLayout>
<FrameLayout
android:id="@+id/flContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
@@ -0,0 +1,27 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:background="@color/bg_page">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvShelf"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
android:overScrollMode="never"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
tools:listitem="@layout/list_item_shelf"/>
<include
android:id="@+id/include"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_empty_view"
android:visibility="gone"/>
</FrameLayout>
@@ -0,0 +1,48 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="450dp"
android:layout_height="430dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="150dp"
android:src="@drawable/img_init"
tools:ignore="ContentDescription"
android:visibility="invisible"/>
<TextView
android:id="@+id/btnInit"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="100dp"
android:background="@drawable/bg_init_button"
android:gravity="center"
android:padding="10dp"
android:text="设备初始化"
android:textColor="@color/white"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="visible"
tools:ignore="HardcodedText" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/ivQrCode"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="50dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/ic_logo512" />
</LinearLayout>
@@ -0,0 +1,240 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="@color/bg_page">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="376dp"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="24dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="12dp"
app:cardElevation="0dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/tvShelfName"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_marginTop="24dp"
android:gravity="center"
android:textColor="@color/bg_page"
android:textSize="30sp"
android:fontFamily="sans-serif-medium"
tools:text="货架 - 03" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/tvFoodWeight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxLines="1"
android:textColor="@color/food_weight_orange"
android:textSize="60sp"
android:textStyle="bold"
tools:text="1506克" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/tvFoodName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/food_name_black"
android:textSize="36sp"
android:textStyle="bold"
tools:text="金针菇" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnClearZero"
android:layout_width="120dp"
android:layout_height="60dp"
android:layout_gravity="top|end"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:backgroundTint="@color/bg_page"
android:ellipsize="end"
android:insetTop="0dp"
android:insetBottom="0dp"
android:maxLines="1"
android:text="清零"
android:fontFamily="sans-serif-medium"
android:textColor="@color/white"
android:textSize="30sp"
app:cornerRadius="12dp"
app:elevation="0dp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="top|start"
android:layout_marginTop="24dp"
android:layout_marginStart="24dp"
android:src="@drawable/ic_back_512"
tools:ignore="ContentDescription" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="12dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginStart="48dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="48dp"
android:background="@drawable/shape_search"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:src="@drawable/ic_search_food" />
<EditText
android:id="@+id/etInputFood"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginEnd="24dp"
android:background="@null"
android:hint="输入食材名称"
android:maxLines="1"
android:inputType="text"
android:text=""
android:imeOptions="actionSearch"
android:textColor="@color/food_name_black"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:textColorHint="#B4BEC8"
android:fontFamily="sans-serif-medium"
android:textSize="30sp"
tools:ignore="Autofill,HardcodedText,TextFields" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="24dp">
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.scwang.smart.refresh.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSearch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="36dp"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:paddingEnd="36dp"
android:clipToPadding="false"
android:overScrollMode="never"
tools:listitem="@layout/list_item_search"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="10"/>
<com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<include
android:id="@+id/include"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_empty_view"
android:visibility="gone"/>
</FrameLayout>
<!-- android:layout_marginTop="48dp"-->
<com.google.android.material.button.MaterialButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="48dp"
android:layout_marginStart="48dp"
android:layout_marginBottom="24dp"
android:backgroundTint="@color/bg_page"
android:ellipsize="end"
android:insetTop="0dp"
android:insetBottom="0dp"
android:maxLines="1"
android:text="确定"
android:textStyle="bold"
android:textColor="@color/white"
android:textSize="30sp"
app:cornerRadius="12dp"
app:elevation="0dp"
tools:ignore="HardcodedText" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_dialog">
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingStart="25dp"
android:paddingTop="13dp"
android:paddingBottom="13dp"
android:paddingEnd="25dp"
android:textColor="@color/white_f6"
android:textSize="32sp"
tools:text="暂无数据" />
</FrameLayout>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingTop="10dp"
android:paddingEnd="20dp"
android:paddingBottom="10dp"
android:background="@drawable/shape_dialog"
tools:ignore="MissingDefaultResource">
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateTint="@color/white_f6" />
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="加载中……"
android:textColor="@color/white_f6"
android:textSize="26sp"
tools:ignore="HardcodedText" />
</LinearLayout>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
tools:ignore="MissingDefaultResource,UseCompoundDrawables">
<ImageView
android:id="@+id/ivEmptyIcon"
android:layout_width="270dp"
android:layout_height="wrap_content"
android:src="@drawable/ic_empty_gray"
android:adjustViewBounds="true"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tvEmptyContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black999"
android:layout_marginTop="60dp"
android:textSize="60sp"
android:text="暂无数据"
tools:ignore="HardcodedText" />
</LinearLayout>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- xmlns:tools="http://schemas.android.com/tools"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="80dp"-->
<!-- android:layout_margin="12dp">-->
<!-- <TextView-->
<!-- android:id="@+id/btnFoodName"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="center"-->
<!-- android:ellipsize="end"-->
<!-- android:gravity="center"-->
<!-- android:maxLines="1"-->
<!-- android:paddingStart="5dp"-->
<!-- android:paddingEnd="5dp"-->
<!-- android:fontFamily="sans-serif-medium"-->
<!-- android:textColor="@color/black999"-->
<!-- android:textSize="30sp"-->
<!-- tools:text="土豆丝" />-->
<!--</FrameLayout>-->
<com.google.android.material.button.MaterialButton 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/btnFoodName"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_margin="12dp"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:insetTop="0dp"
android:insetBottom="0dp"
android:maxLines="1"
app:paddingStart="5dp"
app:paddingEnd="5dp"
android:insetRight="0dp"
android:insetLeft="0dp"
android:paddingHorizontal="8dp"
android:textColor="@color/black999"
android:textSize="30sp"
app:cornerRadius="12dp"
app:strokeWidth="2dp"
tools:text="土豆丝土豆丝土豆丝土豆丝土豆丝土豆丝"
/>
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView 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/layoutCard"
android:layout_width="match_parent"
android:layout_height="216dp"
android:layout_margin="12dp"
app:cardBackgroundColor="@color/bg_card_blue"
app:cardCornerRadius="12dp"
app:cardElevation="5dp"
app:rippleColor="#B0BEC5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:id="@+id/tvShelfName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/shelf_name_white"
android:textSize="20sp"
android:textStyle="bold"
tools:text="货架-01" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/tvFoodName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="30sp"
android:textStyle="bold"
tools:text="空" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.833" />
<TextView
android:id="@+id/tvFoodWeight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/food_weight_blue"
android:textSize="24sp"
android:textStyle="bold"
tools:text="0千克" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.933" />
<TextView
android:id="@+id/tvStoreDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/food_weight_blue"
android:textSize="18sp"
tools:text="-" />
</LinearLayout>
<ImageView
android:id="@+id/ivStaleFood"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_stale_food_512"
android:layout_gravity="top|end"
tools:ignore="ContentDescription"
android:visibility="gone"/>
</com.google.android.material.card.MaterialCardView>
+14 -9
View File
@@ -5,34 +5,39 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:background="@color/bg_page"> android:fitsSystemWindows="false"
tools:background="@color/bg_page">
<FrameLayout <FrameLayout
android:id="@+id/flStatusBar" android:id="@+id/flStatusBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="68dp" android:layout_height="30dp">
android:paddingStart="25dp" <!-- android:paddingTop="9dp"-->
android:paddingEnd="25dp"
android:paddingTop="25dp">
<TextView <TextView
android:id="@+id/tv_left_status" android:id="@+id/tv_left_status"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:gravity="center_vertical"
android:textColor="@color/white" android:textColor="@color/white"
android:layout_gravity="start" android:layout_gravity="start"
android:textSize="24sp" android:textSize="12sp"
android:paddingStart="12dp"
android:paddingEnd="0dp"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
tools:text="1-1冷藏柜 -2°C / 87%" /> tools:text="1-1冷藏柜 -2°C / 87%" />
<TextView <TextView
android:id="@+id/tv_right_status" android:id="@+id/tv_right_status"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:gravity="center_vertical"
android:textColor="@color/white" android:textColor="@color/white"
android:layout_gravity="end" android:layout_gravity="end"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
android:textSize="24sp" android:textSize="12sp"
android:paddingStart="0dp"
android:paddingEnd="12dp"
tools:text="6月22日 星期日 15:26:33" /> tools:text="6月22日 星期日 15:26:33" />
</FrameLayout> </FrameLayout>
+19 -4
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -13,8 +13,23 @@
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
android:overScrollMode="never" android:overScrollMode="never"
android:layout_marginStart="12dp" android:layout_marginStart="6dp"
android:layout_marginEnd="12dp" android:layout_marginEnd="6dp"
tools:listitem="@layout/list_item_shelf"/> tools:listitem="@layout/list_item_shelf"/>
</LinearLayout>
<include
android:id="@+id/include"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_empty_view"
android:visibility="gone"/>
<!-- <include-->
<!-- android:id="@+id/includeLight"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- layout="@layout/layout_light_switch"-->
<!-- android:visibility="gone"/>-->
</FrameLayout>
+48
View File
@@ -0,0 +1,48 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="225dp"
android:layout_height="215dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="75dp"
android:src="@drawable/img_init"
tools:ignore="ContentDescription"
android:visibility="invisible"/>
<TextView
android:id="@+id/btnInit"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dp"
android:background="@drawable/bg_init_button"
android:gravity="center"
android:padding="10dp"
android:text="设备初始化"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
android:visibility="visible"
tools:ignore="HardcodedText" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/ivQrCode"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="25dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/ic_logo512" />
</LinearLayout>
+113 -57
View File
@@ -9,12 +9,12 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="376dp" android:layout_height="190dp"
android:layout_marginStart="24dp" android:layout_marginStart="12dp"
android:layout_marginTop="12dp" android:layout_marginTop="6dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
app:cardBackgroundColor="@color/white" app:cardBackgroundColor="@color/white"
app:cardCornerRadius="12dp" app:cardCornerRadius="6dp"
app:cardElevation="0dp"> app:cardElevation="0dp">
<FrameLayout <FrameLayout
@@ -25,20 +25,20 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="24dp" android:layout_marginStart="12dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/tvShelfName" android:id="@+id/tvShelfName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="60dp" android:layout_height="30dp"
android:layout_marginTop="24dp" android:layout_marginTop="12dp"
android:fontFamily="sans-serif-medium"
android:gravity="center" android:gravity="center"
android:textColor="@color/bg_page" android:textColor="@color/bg_page"
android:textSize="30sp" android:textSize="15sp"
android:fontFamily="sans-serif-medium"
tools:text="货架 - 03" /> tools:text="货架 - 03" />
<Space <Space
@@ -54,7 +54,7 @@
android:includeFontPadding="false" android:includeFontPadding="false"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/food_weight_orange" android:textColor="@color/food_weight_orange"
android:textSize="60sp" android:textSize="30sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="1506克" /> tools:text="1506克" />
@@ -70,7 +70,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/food_name_black" android:textColor="@color/food_name_black"
android:textSize="36sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="金针菇" /> tools:text="金针菇" />
@@ -82,24 +82,49 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btnClearZero" android:id="@+id/btnClearZero"
android:layout_width="120dp" android:layout_width="65dp"
android:layout_height="60dp" android:layout_height="30dp"
android:layout_gravity="top|end" android:layout_gravity="top|end"
android:layout_marginTop="24dp" android:layout_marginTop="12dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
android:backgroundTint="@color/bg_page" android:backgroundTint="@color/bg_page"
android:ellipsize="end" android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:insetTop="0dp" android:insetTop="0dp"
android:insetBottom="0dp" android:insetBottom="0dp"
android:maxLines="1" android:maxLines="1"
android:text="清零" android:text="清零00"
android:fontFamily="sans-serif-medium"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="30sp" android:textSize="15sp"
app:cornerRadius="12dp" app:cornerRadius="6dp"
app:elevation="0dp" app:elevation="0dp"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="top|start"
android:layout_marginTop="12dp"
android:layout_marginStart="12dp"
android:src="@drawable/ic_back_512"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/btnClearEmpty"
android:layout_width="65dp"
android:layout_height="30dp"
android:layout_gravity="bottom|end"
android:layout_marginBottom="22dp"
android:layout_marginEnd="12dp"
android:maxLines="1"
android:text="清空"
android:textStyle="bold"
android:gravity="center"
android:textColor="@color/food_name_black"
android:textSize="15sp"
tools:ignore="HardcodedText" />
</FrameLayout> </FrameLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
@@ -107,12 +132,12 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="24dp" android:layout_marginStart="12dp"
android:layout_marginTop="24dp" android:layout_marginTop="12dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="12dp"
app:cardBackgroundColor="@color/white" app:cardBackgroundColor="@color/white"
app:cardCornerRadius="12dp" app:cardCornerRadius="6dp"
app:cardElevation="0dp"> app:cardElevation="0dp">
<LinearLayout <LinearLayout
@@ -122,73 +147,104 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp" android:layout_height="40dp"
android:layout_marginStart="48dp" android:layout_marginStart="16dp"
android:layout_marginTop="48dp" android:layout_marginTop="16dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="16dp"
android:background="@drawable/shape_search" android:background="@drawable/shape_search"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:layout_width="32dp" android:layout_width="16dp"
android:layout_height="32dp" android:layout_height="16dp"
android:layout_marginStart="24dp" android:layout_marginStart="12dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
android:src="@drawable/ic_search_food" /> android:src="@drawable/ic_search_food" />
<EditText <EditText
android:id="@+id/etInputFood" android:id="@+id/etInputFood"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="36dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="12dp"
android:background="@null" android:background="@null"
android:fontFamily="sans-serif-medium"
android:hint="输入食材名称" android:hint="输入食材名称"
android:maxLines="1"
android:inputType="text"
android:text=""
android:imeOptions="actionSearch" android:imeOptions="actionSearch"
android:textColor="@color/food_name_black" android:inputType="text"
android:maxLines="1"
android:paddingStart="1dp" android:paddingStart="1dp"
android:paddingEnd="1dp" android:paddingEnd="1dp"
android:text=""
android:textColor="@color/food_name_black"
android:textColorHint="#B4BEC8" android:textColorHint="#B4BEC8"
android:fontFamily="sans-serif-medium" android:textSize="15sp"
android:textSize="30sp"
tools:ignore="Autofill,HardcodedText,TextFields" /> tools:ignore="Autofill,HardcodedText,TextFields" />
</LinearLayout> </LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_weight="1">
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.scwang.smart.refresh.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSearch" android:id="@+id/rvSearch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:layout_marginStart="36dp" android:clipToPadding="false"
android:layout_marginTop="36dp"
android:layout_marginEnd="36dp"
android:layout_weight="1"
android:overScrollMode="never" android:overScrollMode="never"
tools:listitem="@layout/list_item_search" android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
tools:itemCount="10"/> tools:itemCount="10"
tools:listitem="@layout/list_item_search" />
<com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<include
android:id="@+id/include"
layout="@layout/layout_empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>
<!-- android:layout_marginTop="48dp"-->
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btnConfirm" android:id="@+id/btnConfirm"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp" android:layout_height="40dp"
android:layout_marginTop="48dp" android:layout_marginStart="24dp"
android:layout_marginEnd="48dp" android:layout_marginTop="12dp"
android:layout_marginStart="48dp" android:layout_marginEnd="24dp"
android:layout_marginBottom="48dp" android:layout_marginBottom="12dp"
android:backgroundTint="@color/bg_page" android:backgroundTint="@color/bg_page"
android:ellipsize="end" android:ellipsize="end"
android:insetTop="0dp" android:insetTop="0dp"
android:insetBottom="0dp" android:insetBottom="0dp"
android:maxLines="1" android:maxLines="1"
android:text="确定" android:text="确定"
android:textStyle="bold"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="30sp" android:textSize="15sp"
app:cornerRadius="12dp" android:textStyle="bold"
app:cornerRadius="6dp"
app:elevation="0dp" app:elevation="0dp"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
+5 -5
View File
@@ -11,12 +11,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:gravity="center" android:gravity="center"
android:paddingStart="25dp" android:paddingStart="12dp"
android:paddingTop="13dp" android:paddingTop="6dp"
android:paddingBottom="13dp" android:paddingBottom="6dp"
android:paddingEnd="25dp" android:paddingEnd="12dp"
android:textColor="@color/white_f6" android:textColor="@color/white_f6"
android:textSize="32sp" android:textSize="16sp"
tools:text="暂无数据" /> tools:text="暂无数据" />
</FrameLayout> </FrameLayout>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:background="@drawable/shape_dialog_small"
tools:ignore="MissingDefaultResource">
<ProgressBar
android:layout_width="26dp"
android:layout_height="26dp"
android:indeterminateTint="@color/white_f6" />
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="加载中……"
android:textColor="@color/white_f6"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
tools:ignore="MissingDefaultResource,UseCompoundDrawables">
<ImageView
android:id="@+id/ivEmptyIcon"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:src="@drawable/ic_empty_gray"
android:adjustViewBounds="true"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tvEmptyContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black999"
android:layout_marginTop="20dp"
android:textSize="20sp"
android:text="暂无数据"
tools:ignore="HardcodedText" />
</LinearLayout>
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DDFFFFFF">
<ImageView
android:id="@+id/ivLightHide"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginVertical="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="end|center_vertical"
android:src="@drawable/close"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="继电器1"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightOpen"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="开"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightClose"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="关"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="继电器2"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightOpen2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="开"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightClose2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="关"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="继电器3"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightOpen3"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="开"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/btnLightClose3"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="关"
android:gravity="center"
android:background="@drawable/bg_init_button"
android:layout_marginStart="50dp"
android:textColor="@color/black"/>
</LinearLayout>
</LinearLayout>
+13 -11
View File
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?><!--<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
<!--<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- xmlns:tools="http://schemas.android.com/tools"--> <!-- xmlns:tools="http://schemas.android.com/tools"-->
<!-- android:layout_width="match_parent"--> <!-- android:layout_width="match_parent"-->
<!-- android:layout_height="80dp"--> <!-- android:layout_height="80dp"-->
@@ -26,20 +25,23 @@
android:id="@+id/btnFoodName" android:id="@+id/btnFoodName"
style="@style/Widget.MaterialComponents.Button.OutlinedButton" style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp" android:layout_height="40dp"
android:layout_margin="12dp" android:layout_margin="6dp"
android:ellipsize="end" android:ellipsize="end"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
android:gravity="center" android:gravity="center"
android:insetTop="0dp" android:insetTop="0dp"
android:insetBottom="0dp" android:insetBottom="0dp"
android:maxLines="1" android:maxLines="1"
app:paddingStart="5dp" android:insetRight="0dp"
app:paddingEnd="5dp" android:insetLeft="0dp"
android:paddingHorizontal="8dp"
android:textColor="@color/black999" android:textColor="@color/black999"
android:textSize="30sp" android:textSize="15sp"
app:cornerRadius="12dp" app:cornerRadius="6dp"
app:strokeWidth="2dp" app:strokeWidth="1dp"
tools:text="土豆丝土豆丝土豆丝土豆丝土豆丝土豆丝" tools:text="土豆丝土豆丝土豆丝土豆丝土豆丝土豆丝" />
/> <!-- android:paddingHorizontal="2dp"-->
<!-- android:paddingLeft="5dp"-->
<!-- android:paddingRight="5dp"-->
+18 -10
View File
@@ -4,26 +4,26 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutCard" android:id="@+id/layoutCard"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="216dp" android:layout_height="140dp"
android:layout_margin="12dp" android:layout_margin="6dp"
app:cardBackgroundColor="@color/bg_card_blue" app:cardBackgroundColor="@color/bg_card_blue"
app:cardCornerRadius="12dp" app:cardCornerRadius="6dp"
app:cardElevation="5dp" app:cardElevation="2dp"
app:rippleColor="#B0BEC5"> app:rippleColor="#B0BEC5">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="216dp" android:layout_height="match_parent"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
android:padding="24dp"> android:padding="12dp">
<TextView <TextView
android:id="@+id/tvShelfName" android:id="@+id/tvShelfName"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/shelf_name_white" android:textColor="@color/shelf_name_white"
android:textSize="20sp" android:textSize="12sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="货架-01" /> tools:text="货架-01" />
@@ -39,7 +39,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="30sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="空" /> tools:text="空" />
@@ -55,7 +55,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/food_weight_blue" android:textColor="@color/food_weight_blue"
android:textSize="24sp" android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="0千克" /> tools:text="0千克" />
@@ -71,9 +71,17 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/food_weight_blue" android:textColor="@color/food_weight_blue"
android:textSize="18sp" android:textSize="12sp"
tools:text="-" /> tools:text="-" />
</LinearLayout> </LinearLayout>
<ImageView
android:id="@+id/ivStaleFood"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_stale_food_512"
android:layout_gravity="top|end"
tools:ignore="ContentDescription"
android:visibility="gone"/>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+1
View File
@@ -12,6 +12,7 @@
<!-- Status bar color. --> <!-- Status bar color. -->
<!-- <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>--> <!-- <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>-->
<item name="android:statusBarColor">@color/white</item> <item name="android:statusBarColor">@color/white</item>
<item name="android:windowBackground">@drawable/bg_splash</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
</style> </style>
</resources> </resources>
+7 -1
View File
@@ -10,7 +10,13 @@
<item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item> <item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <item name="android:statusBarColor">@color/bg_page</item>
<!-- <item name="android:statusBarColor">@color/white</item>-->
<item name="android:windowBackground">@drawable/bg_splash</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
</style> </style>
<style name="LoadingDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowIsFloating">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources> </resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- <domain-config cleartextTrafficPermitted="true">-->
<!-- <domain includeSubdomains="true">192.168.1.3</domain>-->
<!-- <domain includeSubdomains="true">192.168.1.7</domain>-->
<!-- </domain-config> -->
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
+4
View File
@@ -8,8 +8,12 @@ junitVersion = "1.1.5"
espressoCore = "3.5.1" espressoCore = "3.5.1"
appcompat = "1.6.1" appcompat = "1.6.1"
material = "1.10.0" material = "1.10.0"
core = "3.4.1"
androidCore = "3.3.0"
[libraries] [libraries]
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
core = { module = "com.google.zxing:core", version.ref = "core" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
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" }