增加初始化功能、采样菜品搜索功能优化、布局移动到layout目录
This commit is contained in:
Generated
+2
-2
@@ -4,10 +4,10 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-08-18T06:18:22.594579400Z">
|
||||
<DropdownSelection timestamp="2025-09-10T07:28:30.961571900Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.185:5555;connection=2158168e" />
|
||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.21:5555;connection=bc7af9a5" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
||||
+10
-25
@@ -17,13 +17,11 @@ android {
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
ndk {
|
||||
//设置支持的SO库架构
|
||||
abiFilters.addAll(listOf("armeabi", "armeabi-v7a"))
|
||||
//, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
|
||||
}
|
||||
|
||||
resConfigs("sw800dp")
|
||||
// ndk {
|
||||
// //设置支持的SO库架构
|
||||
// abiFilters.addAll(listOf("armeabi", "armeabi-v7a"))
|
||||
// //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
|
||||
// }
|
||||
}
|
||||
signingConfigs {
|
||||
create("debug_507") {
|
||||
@@ -71,15 +69,7 @@ android {
|
||||
)
|
||||
}
|
||||
}
|
||||
lint {
|
||||
disable.add("MissingDefaultResource")
|
||||
}
|
||||
// productFlavors {
|
||||
// create("sw800dp") {
|
||||
// dimension = "screen"
|
||||
//// resConfigs("en", "xxhdpi") // 可选额外配置
|
||||
// }
|
||||
// }
|
||||
// li
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -88,6 +78,8 @@ dependencies {
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.androidx.gridlayout)
|
||||
implementation(libs.android.core)
|
||||
implementation(libs.core)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
@@ -113,15 +105,8 @@ dependencies {
|
||||
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
|
||||
//经典刷新头
|
||||
implementation("io.github.scwang90:refresh-header-radar:3.0.0-alpha")
|
||||
// //雷达刷新头
|
||||
// implementation("io.github.scwang90:refresh-header-falsify:3.0.0-alpha")
|
||||
// //虚拟刷新头
|
||||
// implementation("io.github.scwang90:refresh-header-material:3.0.0-alpha")
|
||||
// //谷歌刷新头
|
||||
// implementation("io.github.scwang90:refresh-header-two-level:3.0.0-alpha")
|
||||
// //二级刷新头
|
||||
// implementation("io.github.scwang90:refresh-footer-ball:3.0.0-alpha")
|
||||
//球脉冲加载
|
||||
implementation("io.github.scwang90:refresh-footer-classics:3.0.0-alpha")
|
||||
//经典加载
|
||||
|
||||
//implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -7,8 +7,11 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
@@ -27,16 +30,16 @@
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:icon="@mipmap/ic_logo512"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:roundIcon="@mipmap/ic_logo512"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.DishMatch"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<activity
|
||||
android:name=".ui.HomeActivity"
|
||||
android:name=".ui.InitActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="DiscouragedApi,LockedOrientationActivity">
|
||||
@@ -46,6 +49,9 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ui.HomeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.SelectDishActivity"
|
||||
|
||||
@@ -99,7 +99,7 @@ class TextCellAdapter(var list: MutableList<SeasoningEntity>) :
|
||||
}
|
||||
|
||||
fun getTextSpan(item: SeasoningEntity): SpannableStringBuilder {
|
||||
val endIndex = if (item.sort == 10 || item.sort == 14) 10 else 6
|
||||
val endIndex = if (item.sort == 9) 10 else 6
|
||||
var name = if (item.goodsName.isNullOrBlank()) "未配置" else item.goodsName!!
|
||||
if (name.length > endIndex) {
|
||||
name = "${name.substring(0, endIndex)}…"
|
||||
|
||||
@@ -14,9 +14,6 @@ class BaseApp : Application() {
|
||||
|
||||
val database by lazy { DatabaseProvider(this).instance }
|
||||
|
||||
var token: String? = null
|
||||
var androidId: String? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
@@ -29,6 +26,10 @@ class BaseApp : Application() {
|
||||
|
||||
// const val canteenId = "1678234139391512577"
|
||||
var canteenId = "0"
|
||||
var configUrl = ""
|
||||
|
||||
var token: String? = null
|
||||
var deviceId: String? = null
|
||||
@Volatile
|
||||
private var sharedPref: SharedPreferences? = null
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ import com.shuwei.dish.match.utils.ext.toast
|
||||
* @param goodsType 1-调料,0-食材
|
||||
*/
|
||||
class BottomDialog(
|
||||
private var goodsType: Int = 1
|
||||
private var goodsType: Int = 1,
|
||||
private var defGoodsName:String? = null
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "BottomDialog"
|
||||
@@ -115,6 +116,13 @@ class BottomDialog(
|
||||
}
|
||||
binding.refreshLayout.setEnableRefresh(false)
|
||||
binding.refreshLayout.setEnableLoadMore(false)
|
||||
|
||||
if (defGoodsName.isNullOrBlank().not()) {
|
||||
binding.etSheetInput.let {
|
||||
it.setText(defGoodsName)
|
||||
searchGoods(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchGoods(v: View) {
|
||||
|
||||
@@ -17,7 +17,6 @@ import androidx.core.view.isEmpty
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.aithings.Weigher
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.SeasoningSearchAdapter
|
||||
@@ -130,7 +129,7 @@ class BottomDialog2(
|
||||
}
|
||||
binding.refreshLayout.setEnableRefresh(false)
|
||||
binding.tvClear.setOnClickListener {
|
||||
Weigher.tareTwo(weighAddress)
|
||||
WeightUtil.tareTwo(weighAddress)
|
||||
}
|
||||
WeightUtil.addWeightListener { address, state, weight ->
|
||||
if (weighAddress == address) {
|
||||
|
||||
@@ -14,14 +14,18 @@ object Loading {
|
||||
private var dialog: LoadingDialog? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
if (dialog?.isShowing == true) {
|
||||
dialog?.dismiss()
|
||||
}
|
||||
try {
|
||||
if (dialog?.isShowing == true) {
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
if (dialog == null) {
|
||||
dialog = LoadingDialog(context)
|
||||
if (dialog == null) {
|
||||
dialog = LoadingDialog(context)
|
||||
}
|
||||
dialog?.show()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.shuwei.dish.match.http
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
@@ -7,9 +8,11 @@ import com.google.gson.reflect.TypeToken
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.base.BaseReq
|
||||
import com.shuwei.dish.match.http.HttpUtil.runMainThread
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
import com.shuwei.dish.match.utils.ext.put
|
||||
import com.shuwei.dish.match.utils.ext.toType
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import kotlinx.coroutines.Runnable
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.HttpUrl
|
||||
@@ -18,6 +21,8 @@ import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
object HttpUtil {
|
||||
@@ -31,50 +36,57 @@ object HttpUtil {
|
||||
// GET请求(HTTPS)
|
||||
fun get(
|
||||
url: String,
|
||||
header: Map<String, String>?=null,
|
||||
doSuccess: (data: Any) -> Unit,
|
||||
doFailure: (code: Int?, msg: String?) -> Unit
|
||||
) {
|
||||
val token = getToken()
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.apply {
|
||||
if (token.isNotBlank()) {
|
||||
addHeader("X-Access-Token", token)
|
||||
}
|
||||
}
|
||||
.get()
|
||||
.build()
|
||||
HttpClient.instance.newCall(request).enqueue(CallbackImpl(doSuccess, doFailure))
|
||||
}
|
||||
|
||||
fun get(
|
||||
isHttps: Boolean = false,
|
||||
host: String = "vip.shuziweidao.com",
|
||||
pathSegmentList: List<String>,
|
||||
queryParams: Map<String, String>,
|
||||
doSuccess: (data: Any) -> Unit,
|
||||
doFailure: (code: Int?, msg: String?) -> Unit
|
||||
) {
|
||||
val token = getToken()
|
||||
val url = HttpUrl.Builder()
|
||||
.scheme(if (isHttps) "https" else "http")
|
||||
.host(host)
|
||||
.apply {
|
||||
pathSegmentList.forEach { addPathSegment(it) }
|
||||
queryParams.forEach { (key, value) -> addQueryParameter(key, value) }
|
||||
}
|
||||
.build()
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.apply {
|
||||
if (token.isNotBlank()) {
|
||||
addHeader("Authorization", token)
|
||||
if (header != null) {
|
||||
header.forEach {
|
||||
addHeader(it.value, it.value)
|
||||
}
|
||||
} else {
|
||||
val token = getToken()
|
||||
if (token.isNotBlank()) {
|
||||
addHeader("X-Access-Token", token)
|
||||
}
|
||||
}
|
||||
}
|
||||
.get()
|
||||
.build()
|
||||
HttpClient.instance.newCall(request).enqueue(CallbackImpl(doSuccess, doFailure))
|
||||
}
|
||||
//
|
||||
// fun get(
|
||||
// isHttps: Boolean = false,
|
||||
// host: String = "vip.shuziweidao.com",
|
||||
// pathSegmentList: List<String>,
|
||||
// queryParams: Map<String, String>,
|
||||
// doSuccess: (data: Any) -> Unit,
|
||||
// doFailure: (code: Int?, msg: String?) -> Unit
|
||||
// ) {
|
||||
// val token = getToken()
|
||||
// val url = HttpUrl.Builder()
|
||||
// .scheme(if (isHttps) "https" else "http")
|
||||
// .host(host)
|
||||
// .apply {
|
||||
// pathSegmentList.forEach { addPathSegment(it) }
|
||||
// queryParams.forEach { (key, value) -> addQueryParameter(key, value) }
|
||||
// }
|
||||
// .build()
|
||||
// val request = Request.Builder()
|
||||
// .url(url)
|
||||
// .apply {
|
||||
// if (token.isNotBlank()) {
|
||||
// addHeader("Authorization", token)
|
||||
// }
|
||||
// }
|
||||
// .get()
|
||||
// .build()
|
||||
// HttpClient.instance.newCall(request).enqueue(CallbackImpl(doSuccess, doFailure))
|
||||
// }
|
||||
|
||||
// POST表单(HTTPS)
|
||||
// fun postForm(url: String, params: Map<String, String>, callback: Callback) {
|
||||
@@ -110,57 +122,79 @@ object HttpUtil {
|
||||
.let { HttpClient.instance.newCall(it).enqueue(CallbackImpl(doSuccess, doFailure)) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CallbackImpl(
|
||||
private val doSuccess: (data: Any) -> Unit,
|
||||
private val doFailure: (code: Int?, msg: String?) -> Unit
|
||||
) :
|
||||
Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
runMainThread {
|
||||
e.printStackTrace()
|
||||
doFailure(-1, "服务异常,${e.message}")
|
||||
val executor = Executors.newSingleThreadScheduledExecutor()
|
||||
var getTokenIsRunning = false
|
||||
private fun exeTokenThread() {
|
||||
if (getTokenIsRunning.not()) {
|
||||
executor.scheduleWithFixedDelay(
|
||||
task, 0, 1, TimeUnit.MINUTES
|
||||
)
|
||||
getTokenIsRunning = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val respData = response.body?.string()
|
||||
runMainThread {
|
||||
Log.d("HttpUtil", respData ?: "")
|
||||
runCatching {
|
||||
val typeToken = object : TypeToken<BaseReq<Any>>() {}
|
||||
val baseReq = respData?.toType<BaseReq<Any>>(typeToken = typeToken)
|
||||
if (baseReq == null) {
|
||||
doFailure(-1, "查询数据失败")
|
||||
return@runCatching
|
||||
}
|
||||
if (baseReq.code != 200) {
|
||||
doFailure(baseReq.code, baseReq.message)
|
||||
if (baseReq.code == 500 || baseReq.code == 401) {
|
||||
getAppToken()
|
||||
}
|
||||
return@runCatching
|
||||
}
|
||||
doSuccess(baseReq.result ?: "")
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
doFailure(-1, "解析异常")
|
||||
}
|
||||
val task = Runnable {
|
||||
if (BaseApp.token.isNullOrBlank()) {
|
||||
getAppToken()
|
||||
} else {
|
||||
executor.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getToken() = BaseApp.instance?.token ?:""
|
||||
fun getToken() = SpTool.getString(SpTool.TOKEN)
|
||||
//BaseApp.instance?.token ?:""
|
||||
//BaseApp.getSharedPref()?.getString("token", "") ?: ""
|
||||
|
||||
private fun getAppToken() {
|
||||
val url = "${UrlConfig.GET_TOKEN}?qrcodeId=${BaseApp.instance?.androidId}"
|
||||
fun getAppToken() {
|
||||
val url = "${UrlConfig.GET_TOKEN}?qrcodeId=${SpTool.getString(SpTool.DEVICE_ID)}"
|
||||
// Log.d(TAG, "getToken: url = $url")
|
||||
HttpUtil.get(url = url, doSuccess = {
|
||||
BaseApp.getSharedPref()?.put("token" to it)
|
||||
BaseApp.instance?.token = it.toString()
|
||||
}) { code, msg ->
|
||||
//toast(msg)
|
||||
get(url = url, doSuccess = {
|
||||
SpTool.put(SpTool.TOKEN, it)
|
||||
BaseApp.token = it.toString()
|
||||
}) { code, msg ->
|
||||
//toast(msg)
|
||||
}
|
||||
}
|
||||
|
||||
class CallbackImpl(
|
||||
private val doSuccess: (data: Any) -> Unit,
|
||||
private val doFailure: (code: Int?, msg: String?) -> Unit
|
||||
) :
|
||||
Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
runMainThread {
|
||||
e.printStackTrace()
|
||||
doFailure(-1, "服务异常,${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val respData = response.body?.string()
|
||||
runMainThread {
|
||||
Log.d("HttpUtil", respData ?: "")
|
||||
runCatching {
|
||||
val typeToken = object : TypeToken<BaseReq<Any>>() {}
|
||||
val baseReq = respData?.toType<BaseReq<Any>>(typeToken = typeToken)
|
||||
if (baseReq == null) {
|
||||
doFailure(-1, "查询数据失败")
|
||||
return@runCatching
|
||||
}
|
||||
if (baseReq.code != 200) {
|
||||
doFailure(baseReq.code, baseReq.message)
|
||||
if (baseReq.code == 500 || baseReq.code == 401) {
|
||||
exeTokenThread()
|
||||
}
|
||||
return@runCatching
|
||||
}
|
||||
doSuccess(baseReq.result ?: "")
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
doFailure(-1, "解析异常")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +1,36 @@
|
||||
package com.shuwei.dish.match.http
|
||||
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
|
||||
object UrlConfig {
|
||||
private 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://vip.shuziweidao.com/shuwei-zhct"
|
||||
// const val DISH_DETAIL = "$BASE_URL/scales/goodsUseList?foodId={foodId}&foodWeight={foodWeight}"
|
||||
// const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName"
|
||||
|
||||
// const val BASE_URL = "http://192.168.1.207:9102"
|
||||
const val BASE_URL = "https://yyjk.shuziweidao.com/gateway"
|
||||
// const val BASE_URL = "https://yyjk.shuziweidao.com/gateway"
|
||||
// const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName"
|
||||
|
||||
const val DISH_DETAIL = "$BASE_URL/food/stFoodInfoMatching/queryById"
|
||||
|
||||
var DISH_DETAIL = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryById"
|
||||
|
||||
// "$BASE_URL/scales/generateToken?deviceId=1111111111111111111111111111"
|
||||
|
||||
const val GET_TOKEN = "$BASE_URL/restaurant/equipment/stEquipment/getEquipmentToken"
|
||||
const val SUBMIT_DISH = "$BASE_URL/food/stFoodInfoMatching/saveoredit"
|
||||
var GET_TOKEN = "${BaseApp.configUrl}/restaurant/equipment/stEquipment/getEquipmentToken"
|
||||
var SUBMIT_DISH = "${BaseApp.configUrl}/food/stFoodInfoMatching/saveoredit"
|
||||
|
||||
const val QUERY_GOODS_LIST = "$BASE_URL/food/stFoodInfoMatching/queryGoodsInfoList"
|
||||
const val QUERY_FOOD_LIST = "$BASE_URL/food/stFoodInfoMatching/list"
|
||||
const val SAMPLING_LIST = "$BASE_URL/food/stFoodInfoMatching/queryHistorical/goodsInfoList"
|
||||
var QUERY_GOODS_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryGoodsInfoList"
|
||||
var QUERY_FOOD_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/list"
|
||||
var SAMPLING_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryHistorical/goodsInfoList"
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
||||
import com.shuwei.dish.match.databinding.ActivityDeviceConfigBinding
|
||||
import com.shuwei.dish.match.dialog.BottomDialog2
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||
|
||||
class DeviceConfigActivity : BaseActivity() {
|
||||
@@ -112,6 +113,7 @@ class DeviceConfigActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
binding.rbModeCook.setOnClickListener {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 0)
|
||||
binding.rbModeCook.isChecked = true
|
||||
binding.rbModeSampling.isChecked = false
|
||||
loadCookSpan(isClicked = true)
|
||||
@@ -120,6 +122,7 @@ class DeviceConfigActivity : BaseActivity() {
|
||||
finish()
|
||||
}
|
||||
binding.rbModeSampling.setOnClickListener {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 1)
|
||||
binding.rbModeCook.isChecked = false
|
||||
binding.rbModeSampling.isChecked = true
|
||||
loadCookSpan()
|
||||
|
||||
@@ -7,7 +7,6 @@ import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.aithings.Weigher
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.DishPartAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
@@ -157,35 +156,35 @@ class DishSamplingActivity : BaseActivity() {
|
||||
LinearLayoutManager(this@DishSamplingActivity, LinearLayoutManager.VERTICAL, false)
|
||||
adapter = dishAdapter
|
||||
}
|
||||
binding.tvInputDishType.run {
|
||||
clickWithDebounce {
|
||||
BottomDialog(goodsType = 0).show(this@DishSamplingActivity) { item ->
|
||||
val filterResult = list.firstOrNull { it.goodsName == item.goodsName }
|
||||
if (filterResult != null) {
|
||||
toast("不允许重复添加同一食材")
|
||||
return@show
|
||||
}
|
||||
text = item.goodsName
|
||||
tempDishEntity = CookFoodGoodsEntity().apply {
|
||||
goodsId = item.goodsId
|
||||
goodsName = item.goodsName
|
||||
|
||||
relateionType = item.relateionType ?: 0
|
||||
goodsOrRelationCode = item.goodsOrRelationCode
|
||||
binding.ivDishTypeSearch.setOnClickListener {
|
||||
val inputText = binding.etInputDishType.text.toString().trim()
|
||||
BottomDialog(goodsType = 0, defGoodsName = inputText).show(this@DishSamplingActivity) { item ->
|
||||
val filterResult = list.firstOrNull { it.goodsName == item.goodsName }
|
||||
if (filterResult != null) {
|
||||
toast("不允许重复添加同一食材")
|
||||
return@show
|
||||
}
|
||||
binding.etInputDishType.setText(item.goodsName)
|
||||
tempDishEntity = CookFoodGoodsEntity().apply {
|
||||
goodsId = item.goodsId
|
||||
goodsName = item.goodsName
|
||||
|
||||
// TODO: 待定
|
||||
//allEdible = item.allEdible
|
||||
}
|
||||
relateionType = item.relateionType ?: 0
|
||||
goodsOrRelationCode = item.goodsOrRelationCode
|
||||
|
||||
// TODO: 待定
|
||||
//allEdible = item.allEdible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivWeightClear.setOnClickListener {
|
||||
Weigher.tareTwo(AddressUtil.ONE)
|
||||
WeightUtil.tareTwo(AddressUtil.ONE)
|
||||
}
|
||||
WeightUtil.addWeightListener(getWeight = { address, state, weight ->
|
||||
Log.d(TAG, "addViewClickListener: address=$address,state=$state,weight=$weight")
|
||||
if (address == 2) {
|
||||
if (address == AddressUtil.ONE) {
|
||||
tempDishEntity?.useWeight = weight.toDouble()
|
||||
binding.tvDishPartWeight.text = "${weight}"
|
||||
}
|
||||
@@ -200,10 +199,14 @@ class DishSamplingActivity : BaseActivity() {
|
||||
return@setOnClickListener
|
||||
}
|
||||
val realWeight = tempDishEntity!!.useWeight ?: 0.0
|
||||
if (realWeight < 0.toDouble()) {
|
||||
if (realWeight <= 0.toDouble()) {
|
||||
toast("食材用量需要大于0")
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (tempDishEntity?.goodsName != binding.etInputDishType.text.toString().trim()) {
|
||||
toast("所选择的食材名称与输入框内容不一致")
|
||||
return@setOnClickListener
|
||||
}
|
||||
tempDishEntity!!.apply {
|
||||
isSamplingPage = true
|
||||
materialType = dishMaterialType
|
||||
@@ -216,7 +219,7 @@ class DishSamplingActivity : BaseActivity() {
|
||||
list.add(tempDishEntity!!)
|
||||
dishAdapter.notifyDataSetChanged()
|
||||
tempDishEntity = null
|
||||
binding.tvInputDishType.text = ""
|
||||
binding.etInputDishType.setText("")
|
||||
binding.rgSampling.clearCheck()
|
||||
}
|
||||
binding.rgSampling.setOnCheckedChangeListener { group, checkedId ->
|
||||
@@ -236,7 +239,11 @@ class DishSamplingActivity : BaseActivity() {
|
||||
return@clickWithDebounce
|
||||
}
|
||||
val food = FoodRecord()
|
||||
food.foodId = foodId
|
||||
binding.etInputDish.let {
|
||||
if (it.tag!=null && it.tag.toString() == it.text.toString()) {
|
||||
food.foodId = foodId
|
||||
}
|
||||
}
|
||||
food.foodName = showFoodName
|
||||
food.cookMode = 1
|
||||
Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
|
||||
@@ -262,6 +269,7 @@ class DishSamplingActivity : BaseActivity() {
|
||||
foodName = it.getStringExtra(FoodSearchActivity.FOOD_NAME)
|
||||
binding.etInputDish.run {
|
||||
setText(foodName)
|
||||
tag = foodName
|
||||
setSelection(text.length)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,8 @@ package com.shuwei.dish.match.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.aithings.Weigher
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.HomeModeAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
@@ -15,9 +12,8 @@ import com.shuwei.dish.match.databinding.ActivityHomeBinding
|
||||
import com.shuwei.dish.match.db.AppRepository
|
||||
import com.shuwei.dish.match.entity.HomeModeBean
|
||||
import com.shuwei.dish.match.http.HttpUtil
|
||||
import com.shuwei.dish.match.http.UrlConfig
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
import com.shuwei.dish.match.utils.WeightUtil
|
||||
import com.shuwei.dish.match.utils.ext.put
|
||||
import com.shuwei.dish.match.utils.ext.startActivity
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||
@@ -31,18 +27,18 @@ class HomeActivity : BaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivityHomeBinding
|
||||
|
||||
private var connect: Boolean = false
|
||||
// private var connect: Boolean = false
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
statusBarDarkFont(enable = true)
|
||||
initViewModel()
|
||||
// 获取 ANDROID_ID
|
||||
val deviceId =
|
||||
Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
Log.d(TAG, "onCreate: deviceId=$deviceId")
|
||||
BaseApp.instance?.androidId = deviceId
|
||||
// // 获取 ANDROID_ID
|
||||
// val deviceId =
|
||||
// Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
// Log.d(TAG, "onCreate: deviceId=$deviceId")
|
||||
// BaseApp.instance?.androidId = deviceId
|
||||
|
||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
@@ -56,13 +52,13 @@ class HomeActivity : BaseActivity() {
|
||||
}
|
||||
binding.radioGroup?.check(R.id.radioZk)
|
||||
initRecyclerView()
|
||||
getAppToken()
|
||||
WeightUtil.connect { connect ->
|
||||
this.connect = connect
|
||||
}
|
||||
Weigher.init()
|
||||
Weigher.getWeight()
|
||||
Weigher.startContinuousRead()
|
||||
// HttpUtil.getAppToken()
|
||||
// WeightUtil.connect { connect ->
|
||||
// this.connect = connect
|
||||
// }
|
||||
// WeightUtil.init()
|
||||
// WeightUtil.getWeight()
|
||||
// WeightUtil.startContinuousRead()
|
||||
// binding.tvTopText.setOnClickListener {
|
||||
// startActivity<SamplingListActivity>()
|
||||
// }
|
||||
@@ -111,6 +107,7 @@ class HomeActivity : BaseActivity() {
|
||||
modeDesc = "菜品快速制作,记录熟重",
|
||||
modeIconId = R.drawable.ic_mode_cook,
|
||||
onClick = {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 0)
|
||||
startActivity<SelectDishActivity>()
|
||||
finish()
|
||||
})
|
||||
@@ -121,6 +118,7 @@ class HomeActivity : BaseActivity() {
|
||||
modeDesc = "菜品快速制作,记录熟重",
|
||||
modeIconId = R.drawable.ic_mode_sampling,
|
||||
onClick = {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 1)
|
||||
goSampling()
|
||||
})
|
||||
)
|
||||
@@ -158,15 +156,5 @@ class HomeActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAppToken() {
|
||||
val url = "${UrlConfig.GET_TOKEN}?qrcodeId=${BaseApp.instance?.androidId}"
|
||||
// Log.d(TAG, "getToken: url = $url")
|
||||
HttpUtil.get(url = url, doSuccess = {
|
||||
BaseApp.getSharedPref()?.put("token" to it)
|
||||
BaseApp.instance?.token = it.toString()
|
||||
}) { code, msg ->
|
||||
toast(msg)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.shuwei.dish.match.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.databinding.ActivityInitBinding
|
||||
import com.shuwei.dish.match.db.AppRepository
|
||||
import com.shuwei.dish.match.http.HttpUtil
|
||||
import com.shuwei.dish.match.http.UrlConfig
|
||||
import com.shuwei.dish.match.utils.AppUtil
|
||||
import com.shuwei.dish.match.utils.QRCodeUtil
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
import com.shuwei.dish.match.utils.WeightUtil
|
||||
import com.shuwei.dish.match.utils.ext.dp
|
||||
import com.shuwei.dish.match.utils.ext.invisible
|
||||
import com.shuwei.dish.match.utils.ext.startActivity
|
||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||
import com.shuwei.dish.match.utils.ext.toObject
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import com.shuwei.dish.match.utils.ext.visible
|
||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class InitActivity : BaseActivity() {
|
||||
companion object {
|
||||
const val TAG = "InitActivity"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityInitBinding
|
||||
private lateinit var appViewModel: AppViewModel
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
statusBarDarkFont(enable = true)
|
||||
binding = ActivityInitBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setHeaderBackground(isHomePage = true)
|
||||
|
||||
// 获取 ANDROID_ID
|
||||
val androidId =
|
||||
Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
BaseApp.deviceId = androidId
|
||||
SpTool.put(SpTool.DEVICE_ID, androidId)
|
||||
// TODO: 以上保存deviceId用于临时使用,后续改为下面注释方式
|
||||
// var deviceId = AppUtil.getUDID(this)
|
||||
// Log.d(TAG, "onCreate: deviceId=$deviceId")
|
||||
//// deviceId = "39a7abdd06b3c7ab"
|
||||
//// deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
|
||||
//
|
||||
// BaseApp.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()
|
||||
|
||||
initViewModel()
|
||||
WeightUtil.init()
|
||||
WeightUtil.connect {}
|
||||
WeightUtil.getWeight()
|
||||
WeightUtil.startContinuousRead()
|
||||
HttpUtil.getAppToken()
|
||||
|
||||
countDown()
|
||||
}
|
||||
|
||||
private fun initViewModel() {
|
||||
val db = BaseApp.instance!!.database
|
||||
val factory = AppFactory(AppRepository(db.appDao()))
|
||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||
}
|
||||
|
||||
private fun startNextPage() {
|
||||
val launchPageType = SpTool.getInt(SpTool.LAUNCH_PAGE_TYPE, -1)
|
||||
when (launchPageType) {
|
||||
0 -> {
|
||||
startActivity<SelectDishActivity>()
|
||||
}
|
||||
|
||||
1 -> {
|
||||
goSampling()
|
||||
}
|
||||
|
||||
else -> {
|
||||
startActivity<HomeActivity>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun goSampling() {
|
||||
appViewModel.countCookFood(cookMode = 1) {
|
||||
if (it > 0) {
|
||||
startActivity<SamplingListActivity>()
|
||||
finish()
|
||||
return@countCookFood
|
||||
}
|
||||
startActivity<DishSamplingActivity> {
|
||||
putExtra(DishSamplingActivity.PAGE_FROM, DishSamplingActivity.HOME)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun countDown() {
|
||||
lifecycleScope.launch {
|
||||
flow {
|
||||
(2 downTo 1).forEach {
|
||||
delay(1000)
|
||||
emit(it)
|
||||
}
|
||||
}.collect {
|
||||
// 倒计时结束执行跳转
|
||||
if (it == 1) {
|
||||
startNextPage()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initConfig() {
|
||||
binding.ivQrCode.setImageBitmap(
|
||||
QRCodeUtil.generateQRCode(
|
||||
content = BaseApp.deviceId?:"",
|
||||
size = 200.dp
|
||||
)
|
||||
)
|
||||
binding.btnInit.setOnClickListener {
|
||||
getDeviceConfig()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeviceConfig() {
|
||||
val tokenUrl = "${UrlConfig.DEVICE_TOKEN}?qrcodeId=${BaseApp.deviceId}&appVersion=1"
|
||||
HttpUtil.get(url = tokenUrl, doSuccess = { token ->
|
||||
Log.d(TAG, "initConfig: $token")
|
||||
getConfig(token.toString())
|
||||
}, doFailure = { code, msg ->
|
||||
Log.d(TAG, "initConfig: $code,$msg")
|
||||
})
|
||||
}
|
||||
private fun getConfig(token: String) {
|
||||
val deviceConfigUrl = "${UrlConfig.DEVICE_CONFIG}?equipmentCode=${BaseApp.deviceId}&&appVersion=1"
|
||||
HttpUtil.get(url = deviceConfigUrl, header = mutableMapOf(
|
||||
"X-Access-Token" to token
|
||||
), doSuccess = {
|
||||
Log.d(TAG, "getDeviceConfig: $it")
|
||||
val data = it.toJsonString()
|
||||
val checkResult = checkConfigData(data)
|
||||
if (checkResult.not()) {
|
||||
toast("初始化设备失败,请稍后重试")
|
||||
return@get
|
||||
}
|
||||
SpTool.put(SpTool.DEVICE_CONFIG_CACHE, data)
|
||||
startActivity<HomeActivity>()
|
||||
finish()
|
||||
}, doFailure = { code, msg ->
|
||||
Log.d(TAG, "getDeviceConfig: $code,$msg")
|
||||
toast("初始化设备失败,请稍后重试,code=${code},msg=${msg}")
|
||||
})
|
||||
}
|
||||
|
||||
data class DeviceConfigBean(
|
||||
var appPackageUrl:String? = null,
|
||||
var canteenId:String? = null
|
||||
)
|
||||
|
||||
private fun checkConfigData(data: String): Boolean {
|
||||
if (data.isBlank()) {
|
||||
return false
|
||||
}
|
||||
val config = data.toObject<DeviceConfigBean?>()
|
||||
if (config == null) {
|
||||
return false
|
||||
}
|
||||
BaseApp.configUrl = config.appPackageUrl?:""
|
||||
BaseApp.canteenId = config.canteenId?:""
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.aithings.Weigher
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.DishPartAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
@@ -75,11 +74,11 @@ class PrepareCookActivity : BaseActivity() {
|
||||
|
||||
private fun addViewClickListener() {
|
||||
binding.ivWeightClear.setOnClickListener {
|
||||
Weigher.tareTwo(AddressUtil.ONE)
|
||||
WeightUtil.tareTwo(AddressUtil.ONE)
|
||||
}
|
||||
WeightUtil.addWeightListener(getWeight = { address, state, weight ->
|
||||
Log.d(TAG, "addViewClickListener: address=$address,state=$state,weight=$weight")
|
||||
if (address == 2) {
|
||||
if (address == AddressUtil.ONE) {
|
||||
binding.tvDishPartWeight.text = "${weight}"
|
||||
}
|
||||
})
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.util.SparseIntArray
|
||||
import android.widget.TextView
|
||||
import androidx.core.util.forEach
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.aithings.Weigher
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
||||
@@ -150,7 +149,7 @@ class SubmitFoodActivity : BaseActivity() {
|
||||
|
||||
private fun addViewListener() {
|
||||
addWeightListener()
|
||||
binding.btnWeightClear.setOnClickListener { Weigher.tareTwo(AddressUtil.TWO) }
|
||||
binding.btnWeightClear.setOnClickListener { WeightUtil.tareTwo(AddressUtil.TWO) }
|
||||
|
||||
binding.btnCook.clickWithDebounce {
|
||||
cook()
|
||||
@@ -167,7 +166,7 @@ class SubmitFoodActivity : BaseActivity() {
|
||||
|
||||
private fun addWeightListener() {
|
||||
WeightUtil.addWeightListener(getWeight = { address, state, weight ->
|
||||
if (address == 1) {
|
||||
if (address == AddressUtil.TWO) {
|
||||
cookFoodEntity.foodWeight = weight.toDouble()
|
||||
binding.tvTotalWeight.text = "${weight / 1000f}"
|
||||
}
|
||||
|
||||
@@ -207,19 +207,23 @@ class DishListFragment : Fragment() {
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun loadEmptyView() {
|
||||
list.clear()
|
||||
dishAdapter.notifyDataSetChanged()
|
||||
if (emptyViewBinding == null) {
|
||||
emptyViewBinding = LayoutEmptyViewBinding.inflate(
|
||||
LayoutInflater.from(requireContext()),
|
||||
binding.rvDishList,
|
||||
false
|
||||
)
|
||||
try {
|
||||
list.clear()
|
||||
dishAdapter.notifyDataSetChanged()
|
||||
if (emptyViewBinding == null) {
|
||||
emptyViewBinding = LayoutEmptyViewBinding.inflate(
|
||||
LayoutInflater.from(requireContext()),
|
||||
binding.rvDishList,
|
||||
false
|
||||
)
|
||||
}
|
||||
emptyViewBinding!!.tvContent.text = "暂无数据"
|
||||
emptyViewBinding!!.tvSubContent.text = "获取菜品数据失败,请检查网络设置或稍后重试"
|
||||
dishAdapter.stateView = emptyViewBinding!!.root
|
||||
//dishAdapter.setStateViewLayout(requireContext(), R.layout-sw800dp.layout_empty_view)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
emptyViewBinding!!.tvContent.text = "暂无数据"
|
||||
emptyViewBinding!!.tvSubContent.text = "获取菜品数据失败,请检查网络设置或稍后重试"
|
||||
dishAdapter.stateView = emptyViewBinding!!.root
|
||||
//dishAdapter.setStateViewLayout(requireContext(), R.layout-sw800dp.layout_empty_view)
|
||||
}
|
||||
|
||||
private fun finishRefresh() {
|
||||
|
||||
@@ -0,0 +1,750 @@
|
||||
package com.shuwei.dish.match.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) {
|
||||
// String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
// L.e("androidID===" + androidID);
|
||||
// return androidID;
|
||||
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,100 @@
|
||||
package com.shuwei.dish.match.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,30 @@
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.utils.ext.put
|
||||
|
||||
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 = BaseApp.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)
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,26 @@ import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.util.SparseIntArray
|
||||
import com.aithings.Weigher
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
|
||||
|
||||
object WeightUtil {
|
||||
|
||||
// val weightArray = SparseIntArray()
|
||||
fun init() {
|
||||
Weigher.init()
|
||||
}
|
||||
|
||||
fun getWeight() {
|
||||
Weigher.getWeight()
|
||||
}
|
||||
|
||||
fun startContinuousRead() {
|
||||
Weigher.startContinuousRead()
|
||||
}
|
||||
|
||||
fun tareTwo(address: Int) {
|
||||
Weigher.tareTwo(address)
|
||||
}
|
||||
|
||||
fun connect(initCallback: (connect: Boolean) -> Unit) {
|
||||
Weigher.setListener(object : WeightListenerImpl() {
|
||||
@@ -34,17 +45,17 @@ object WeightUtil {
|
||||
}
|
||||
|
||||
override fun onGetWeight(address: Int, state: Int, weight: Int) {
|
||||
// runOnUiThread {
|
||||
// val stateStr = when (state) {
|
||||
// SensorScale.STATE_STABLE -> "稳定"
|
||||
// SensorScale.STATE_UNSTABLE -> "不稳定"
|
||||
// SensorScale.STATE_OVER_WEIGHT -> "量程溢出"
|
||||
// else -> ""
|
||||
// }
|
||||
// val result1 = String.format("$stateStr 重量:%s kg", weight / 1000f)
|
||||
// //Log.d("WeightUtil", "ttlReturn, address:$address,$result1")
|
||||
runOnUiThread {
|
||||
val stateStr = when (state) {
|
||||
SensorScale.STATE_STABLE -> "稳定"
|
||||
SensorScale.STATE_UNSTABLE -> "不稳定"
|
||||
SensorScale.STATE_OVER_WEIGHT -> "量程溢出"
|
||||
else -> ""
|
||||
}
|
||||
val result1 = String.format("$stateStr 重量:%s kg", weight / 1000f)
|
||||
Log.d("WeightUtil", "ttlReturn, address:$address,$result1")
|
||||
// weightArray.put(address, weight)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReadIdentify(rate: Int) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/ripple_color">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
|
||||
<solid android:color="#ff08C6DC" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:width="828dp" android:height="1768dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/bg_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:gravity="top" android:width="828dp" android:height="414dp">
|
||||
<bitmap android:src="@drawable/bg_home_page"/>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 999 KiB |
-21
@@ -43,13 +43,6 @@
|
||||
android:textSize="28sp" />
|
||||
</FrameLayout>
|
||||
|
||||
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="1dp"-->
|
||||
<!-- android:layout_marginStart="30dp"-->
|
||||
<!-- android:layout_marginEnd="30dp"-->
|
||||
<!-- android:background="@color/gray_eb" />-->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/modeRadioGroup"
|
||||
android:layout_width="match_parent"
|
||||
@@ -69,13 +62,6 @@
|
||||
android:textSize="36sp"
|
||||
tools:text="制作模式" />
|
||||
|
||||
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="1dp"-->
|
||||
<!-- android:layout_marginStart="30dp"-->
|
||||
<!-- android:layout_marginEnd="30dp"-->
|
||||
<!-- android:background="@color/gray_eb" />-->
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbModeSampling"
|
||||
android:layout_width="match_parent"
|
||||
@@ -89,13 +75,6 @@
|
||||
android:textSize="36sp"
|
||||
tools:text="采样模式" />
|
||||
|
||||
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="1dp"-->
|
||||
<!-- android:layout_marginStart="30dp"-->
|
||||
<!-- android:layout_marginEnd="30dp"-->
|
||||
<!-- android:background="@color/gray_eb" />-->
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbModeQuality"
|
||||
android:layout_width="match_parent"
|
||||
+15
-8
@@ -74,22 +74,29 @@
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvInputDishType"
|
||||
<EditText
|
||||
android:id="@+id/etInputDishType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="80dp"
|
||||
android:background="@color/white"
|
||||
android:gravity="center_vertical|end"
|
||||
android:gravity="center_vertical"
|
||||
android:hint="@string/dish_search_hint2"
|
||||
android:textColor="@color/black333"
|
||||
android:textColorHint="@color/gray_c8"
|
||||
android:textSize="28sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:drawablePadding="30dp"
|
||||
android:paddingEnd="30dp"
|
||||
android:paddingStart="30dp"
|
||||
app:drawableEndCompat="@drawable/ic_search_green" />
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingStart="6dp"
|
||||
android:ellipsize="end"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivDishTypeSearch"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:padding="24dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:src="@drawable/ic_search_green"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<!-- <ImageView-->
|
||||
<!-- android:id="@+id/ivDishTypeSearch"-->
|
||||
@@ -0,0 +1,49 @@
|
||||
<?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="500dp"
|
||||
android:layout_height="500dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginTop="250dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/img_init"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnInit"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="160dp"
|
||||
android:background="@drawable/bg_init_button"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:text="设备初始化"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText"
|
||||
android:visibility="visible"/>
|
||||
|
||||
<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:src="@mipmap/ic_logo1024"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</LinearLayout>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -10,8 +10,12 @@
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<!-- Customize your theme here. -->
|
||||
<!-- <item name="android:layout_width">828dp</item>-->
|
||||
<item name="android:fitsSystemWindows">false</item>
|
||||
<item name="android:windowBackground">@drawable/bg_splash</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
|
||||
</style>
|
||||
</resources>
|
||||
@@ -10,9 +10,13 @@
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<!-- Customize your theme here. -->
|
||||
<!-- <item name="android:layout_width">828dp</item>-->
|
||||
<item name="android:fitsSystemWindows">false</item>
|
||||
<item name="android:windowBackground">@drawable/bg_splash</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="CookButtonStyle" parent="Widget.MaterialComponents.Button">
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">vip.shuziweidao.com</domain>
|
||||
<domain includeSubdomains="true">192.168.1.207</domain>
|
||||
</domain-config>
|
||||
<!-- <domain-config cleartextTrafficPermitted="true">-->
|
||||
<!-- <domain includeSubdomains="true">vip.shuziweidao.com</domain>-->
|
||||
<!-- <domain includeSubdomains="true">192.168.1.207</domain>-->
|
||||
<!-- <domain includeSubdomains="true">device.shuziweidao.com</domain>-->
|
||||
<!-- </domain-config>-->
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
|
||||
@@ -9,8 +9,12 @@ espressoCore = "3.5.1"
|
||||
appcompat = "1.6.1"
|
||||
material = "1.10.0"
|
||||
gridlayout = "1.1.0"
|
||||
core = "3.4.1"
|
||||
androidCore = "3.3.0"
|
||||
|
||||
[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" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
|
||||
Reference in New Issue
Block a user