Merge branch 'dev-lvmeng'
# Conflicts: # app/build.gradle.kts
This commit is contained in:
@@ -116,4 +116,10 @@ dependencies {
|
||||
implementation(libs.timber)
|
||||
// 图片显示
|
||||
implementation("io.coil-kt:coil-compose:2.4.0")
|
||||
|
||||
implementation(libs.core)
|
||||
implementation(libs.android.core)
|
||||
|
||||
implementation("androidx.compose.foundation:foundation:1.7.0")
|
||||
implementation("androidx.compose.foundation:foundation-layout:1.7.0")
|
||||
}
|
||||
@@ -19,9 +19,9 @@
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher512"
|
||||
android:icon="@mipmap/ic_logo512"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher512"
|
||||
android:roundIcon="@mipmap/ic_logo512"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Inbound"
|
||||
android:usesCleartextTraffic="true"
|
||||
@@ -41,6 +41,14 @@
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"/>
|
||||
<!-- android:theme="@style/Theme.Inbound"-->
|
||||
|
||||
<activity
|
||||
android:name=".InitActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@style/Theme.Inbound">
|
||||
<intent-filter>
|
||||
|
||||
@@ -39,12 +39,29 @@ object GlobalData {
|
||||
* 单位类型列表
|
||||
*/
|
||||
var unitTypeList: List<DictType> = arrayListOf()
|
||||
|
||||
/**
|
||||
* 具体业务baseurl
|
||||
*/
|
||||
var appBaseUrl: String = ""
|
||||
|
||||
/**
|
||||
* 设备id
|
||||
*/
|
||||
var deviceId: String = ""
|
||||
var restId: String = ""
|
||||
var appVersion: String = "1"
|
||||
var appId = "Hkz1rBk6PZXbS8KwKr67K2eZtsz8bRoMHLg64bUdgCZj"
|
||||
var sdkKey = "AabXs3sHM8UhhE7oCGf4LVMLrdkGb1nJNksbjjTdVt7k"
|
||||
|
||||
var appToken = ""
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
object GlobalKey {
|
||||
const val KEY_EQUIPMENT_INFO = "equipmentInfo"
|
||||
const val KEY_TOKEN = "tokenKey"
|
||||
const val KEY_USER_INFO = "userInfoKey"
|
||||
const val KEY_USER_NAME = "userNameKey"
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.sw.inbound
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandIn
|
||||
import androidx.compose.animation.shrinkOut
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.windowInsetsBottomHeight
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.sw.inbound.utils.AppUtil
|
||||
import com.sw.inbound.utils.QRCodeUtil
|
||||
import com.sw.inbound.viewmodel.DeviceViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* 设备初始化界面
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class InitActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
setContent {
|
||||
InitScreen()
|
||||
}
|
||||
}
|
||||
|
||||
private var scale = 0.8F
|
||||
|
||||
private val qrCodeBmp by lazy {
|
||||
QRCodeUtil.generateQRCode(
|
||||
content = GlobalData.deviceId,
|
||||
size = (scale * 150).toInt()
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(widthDp = 1920, heightDp = 1080)
|
||||
@Composable
|
||||
fun InitScreen(
|
||||
viewModel: DeviceViewModel = hiltViewModel<DeviceViewModel>()
|
||||
) {
|
||||
// val context = LocalContext.current
|
||||
val hasDeviceData = viewModel.checkEquipmentInfo()
|
||||
val deviceInfoResult = viewModel.deviceInfoResult.collectAsState()
|
||||
|
||||
if (hasDeviceData) {
|
||||
LaunchedEffect(this) {
|
||||
delay(1500)
|
||||
goLoginActivity()
|
||||
}
|
||||
} else {
|
||||
FirstPage(viewModel)
|
||||
}
|
||||
if (deviceInfoResult.value == true) {
|
||||
goLoginActivity()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun FirstPage(viewModel: DeviceViewModel) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.size(
|
||||
1920.dp, 1080.dp
|
||||
)
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.padding(top = (scale * 112).dp)
|
||||
.background(Color.White.copy(alpha = 0.0F))
|
||||
.size((scale * 337).dp, (scale * 322).dp)
|
||||
)
|
||||
|
||||
Button(
|
||||
onClick = {
|
||||
viewModel.getDeviceToken()
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
contentColor = Color.Transparent,
|
||||
containerColor = Color(0xFF08C6DC)
|
||||
),
|
||||
shape = RoundedCornerShape((scale * 8).dp),
|
||||
modifier = Modifier
|
||||
.width((scale * 225).dp)
|
||||
.padding(top = (scale * 75).dp)
|
||||
.padding((scale * 10).dp)
|
||||
) {
|
||||
Text(
|
||||
text = "设备初始化",
|
||||
color = Color.White,
|
||||
fontSize = (scale * 22).sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
}
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.weight(1F)
|
||||
)
|
||||
Image(
|
||||
bitmap = qrCodeBmp!!.asImageBitmap(),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.padding(bottom = 10.dp)
|
||||
.size((scale * 150).dp, (scale * 150).dp)
|
||||
)
|
||||
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||
}
|
||||
}
|
||||
// AnimatedVisibility(
|
||||
// visible = isSuccess.not(),
|
||||
// enter = expandIn(clip = false),
|
||||
// exit = shrinkOut(clip = false)
|
||||
// ) {}
|
||||
// fun initialize() {
|
||||
// var deviceId = AppUtil.getUDID(this)
|
||||
// deviceId = "6ce7cd59-b875-38b2-b73d-88a570be3212"
|
||||
// GlobalData.deviceId = deviceId
|
||||
// val isSuccess = deviceViewModel.checkEquipmentInfo()
|
||||
// if (isSuccess) {
|
||||
// goLoginActivity()
|
||||
// return
|
||||
// }
|
||||
// binding.ivQrCode.setImageBitmap(
|
||||
// QRCodeUtil.generateQRCode(
|
||||
// content = GlobalData.deviceId,
|
||||
// size = 200
|
||||
// )
|
||||
// )
|
||||
// binding.btnInit.setOnClickListener {
|
||||
// deviceViewModel.getDeviceToken()
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun goLoginActivity() {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import com.sw.inbound.sdk.SensorScaleUtils
|
||||
import com.sw.inbound.ui.AppScreen
|
||||
import com.sw.inbound.utils.ContextUtils
|
||||
import com.sw.inbound.utils.SPUtil
|
||||
import com.sw.inbound.utils.ThreadUtils
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@@ -15,6 +17,7 @@ class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.sw.inbound
|
||||
|
||||
import android.app.Application
|
||||
import com.sw.inbound.utils.AppUtil
|
||||
import com.sw.inbound.utils.ContextUtils
|
||||
import com.sw.inbound.utils.CrashHandler
|
||||
import com.sw.inbound.utils.SPUtil
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import timber.log.Timber
|
||||
|
||||
@@ -16,6 +18,13 @@ class MyApp : Application() {
|
||||
super.onCreate()
|
||||
Timber.plant(Timber.DebugTree())
|
||||
ContextUtils.initAppContext(this)
|
||||
GlobalData.appVersion = AppUtil.getAppVersionCode(this).toString()
|
||||
var deviceId = AppUtil.getUDID(this)
|
||||
deviceId = "6ce7cd59-b875-38b2-b73d-88a570be3212"
|
||||
GlobalData.deviceId = deviceId
|
||||
|
||||
val spUtil = SPUtil.getInstance(context = ContextUtils.getAppContext())
|
||||
GlobalData.appToken = spUtil.get(GlobalKey.KEY_TOKEN, "") as String
|
||||
|
||||
// 初始化崩溃处理器
|
||||
CrashHandler.init(this)
|
||||
|
||||
@@ -18,6 +18,7 @@ import javax.inject.Singleton
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object NetworkModule {
|
||||
private const val DEVICE_BASE_URL = "http://device.shuziweidao.com:8889/"
|
||||
|
||||
// private const val BASE_URL = "https://127.0.0.1"
|
||||
private const val BASE_URL = "https://yyjk.shuziweidao.com/gateway/"
|
||||
@@ -51,7 +52,7 @@ object NetworkModule {
|
||||
@Singleton
|
||||
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.baseUrl(DEVICE_BASE_URL)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.sw.inbound.model.response
|
||||
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class EquipmentInfo(
|
||||
@SerializedName("appPackageLocalUrl")
|
||||
val appPackageLocalUrl: String? = "",
|
||||
@SerializedName("appPackageUrl")
|
||||
val appPackageUrl: String? = "",
|
||||
@SerializedName("arcsoftActiveKey")
|
||||
val arcsoftActiveKey: String? = "",
|
||||
@SerializedName("arcsoftAppId")
|
||||
val arcsoftAppId: String? = "",
|
||||
@SerializedName("arcsoftSdkKey")
|
||||
val arcsoftSdkKey: String? = "",
|
||||
@SerializedName("arrayCross")
|
||||
val arrayCross: Int? = 0,
|
||||
@SerializedName("arrayMode")
|
||||
val arrayMode: String? = "",
|
||||
@SerializedName("arrayVertical")
|
||||
val arrayVertical: Int? = 0,
|
||||
@SerializedName("canteenId")
|
||||
val canteenId: String? = "",
|
||||
@SerializedName("canteenName")
|
||||
val canteenName: String? = "",
|
||||
@SerializedName("clientServerIp")
|
||||
val clientServerIp: String? = "",
|
||||
@SerializedName("createBy")
|
||||
val createBy: String? = "",
|
||||
@SerializedName("createTime")
|
||||
val createTime: String? = "",
|
||||
@SerializedName("customerName")
|
||||
val customerName: String? = "",
|
||||
@SerializedName("equipmentCode")
|
||||
val equipmentCode: String? = "",
|
||||
@SerializedName("equipmentName")
|
||||
val equipmentName: String? = "",
|
||||
@SerializedName("equipmentName_dictText")
|
||||
val equipmentNameDictText: String? = "",
|
||||
@SerializedName("id")
|
||||
val id: String? = "",
|
||||
@SerializedName("isSync")
|
||||
val isSync: Int? = 0,
|
||||
@SerializedName("mqName")
|
||||
val mqName: String? = "",
|
||||
@SerializedName("mqPassword")
|
||||
val mqPassword: String? = "",
|
||||
@SerializedName("orgCode")
|
||||
val orgCode: String? = "",
|
||||
@SerializedName("owningTrack")
|
||||
val owningTrack: Int? = 0,
|
||||
@SerializedName("owningTrackOrder")
|
||||
val owningTrackOrder: Int? = 0,
|
||||
@SerializedName("screenHtml")
|
||||
val screenHtml: String? = "",
|
||||
@SerializedName("serviceRequestAddress")
|
||||
val serviceRequestAddress: String? = "",
|
||||
@SerializedName("status")
|
||||
val status: Int? = 0,
|
||||
@SerializedName("sysOrgCode")
|
||||
val sysOrgCode: String? = "",
|
||||
@SerializedName("updateBy")
|
||||
val updateBy: String? = "",
|
||||
@SerializedName("updateTime")
|
||||
val updateTime: String? = "",
|
||||
@SerializedName("zhstServerIp")
|
||||
val zhstServerIp: String? = ""
|
||||
) : Parcelable
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.sw.inbound.network.api
|
||||
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.model.request.GoodsAddParam
|
||||
import com.sw.inbound.model.request.GoodsPurchaseUnitParam
|
||||
import com.sw.inbound.model.request.LoginParam
|
||||
@@ -7,6 +8,7 @@ import com.sw.inbound.model.request.PurchaseWarehouseParam
|
||||
import com.sw.inbound.model.request.UploadInfo
|
||||
import com.sw.inbound.model.response.ApiResponse
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.model.response.GoodsType
|
||||
import com.sw.inbound.model.response.PurchaseInfo
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
@@ -17,102 +19,168 @@ import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Multipart
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Part
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Url
|
||||
|
||||
/**
|
||||
* api接口
|
||||
*/
|
||||
interface ApiService {
|
||||
/**
|
||||
* device获取token
|
||||
*/
|
||||
@GET("sys/getEquipmentToken")
|
||||
suspend fun getDeviceToken(
|
||||
@Query("qrcodeId") qrcodeId: String,
|
||||
@Query("appVersion") appVersion: String = GlobalData.appVersion
|
||||
): ApiResponse<String>
|
||||
|
||||
/**
|
||||
*获取配置信息
|
||||
*/
|
||||
@GET("equipment/stEquipment/queryByEquipmentCode")
|
||||
suspend fun getDeviceInfo(
|
||||
@Query("equipmentCode") equipmentCode: String,
|
||||
@Query("appVersion") appVersion: String = GlobalData.appVersion,
|
||||
@Header("X-Access-Token") token: String
|
||||
): ApiResponse<EquipmentInfo>
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@POST("sys/loginPad")
|
||||
suspend fun login(@Body body: LoginParam): ApiResponse<User>
|
||||
@POST//("sys/loginPad")
|
||||
suspend fun login(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/sys/loginPad",
|
||||
@Body body: LoginParam,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<User>
|
||||
|
||||
/**
|
||||
* 采购单入库-列表
|
||||
*/
|
||||
@GET("pad/receivePage")
|
||||
@GET//("pad/receivePage")
|
||||
suspend fun getReceiveList(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/receivePage",
|
||||
@Query("pageNo") pageNo: Int,
|
||||
@Query("pageSize") pageSize: Int
|
||||
@Query("pageSize") pageSize: Int,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<SupplierResponse>
|
||||
|
||||
/**
|
||||
* 采购单入库-详情
|
||||
*/
|
||||
@GET("pad/receiveDetail")
|
||||
suspend fun getReceiveDetail(@Query("id") id: Int): ApiResponse<PurchaseInfo>
|
||||
@GET//("pad/receiveDetail")
|
||||
suspend fun getReceiveDetail(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/receiveDetail",
|
||||
@Query("id") id: Int,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<PurchaseInfo>
|
||||
|
||||
/**
|
||||
* 部分收货
|
||||
*/
|
||||
@POST("pad/partialReceiptGoods")
|
||||
suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
|
||||
@POST//("pad/partialReceiptGoods")
|
||||
suspend fun partialReceipt(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/partialReceiptGoods",
|
||||
@Body uploadInfo: UploadInfo,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<Boolean>
|
||||
|
||||
/**
|
||||
* 确认收货
|
||||
*/
|
||||
@POST("pad/saveAndReceiveAndGoWare")
|
||||
suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
|
||||
@POST//("pad/saveAndReceiveAndGoWare")
|
||||
suspend fun confirmReceipt(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/saveAndReceiveAndGoWare",
|
||||
@Body uploadInfo: UploadInfo,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<Boolean>
|
||||
|
||||
/**
|
||||
* 存储方式
|
||||
*/
|
||||
@GET("sys/dict/getDictItemByF")
|
||||
suspend fun getGoodsStorageType(@Query("dictCode") dictCode: String = "goods_storage_type"): ApiResponse<List<StorageType>>
|
||||
@GET//("sys/dict/getDictItemByF")
|
||||
suspend fun getGoodsStorageType(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/sys/dict/getDictItemByF",
|
||||
@Query("dictCode") dictCode: String = "goods_storage_type",
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<List<StorageType>>
|
||||
|
||||
/**
|
||||
* 物品类型
|
||||
*/
|
||||
@GET("pad/notLimitList")
|
||||
suspend fun getGoodsType(): ApiResponse<GoodsType>
|
||||
@GET//("pad/notLimitList")
|
||||
suspend fun getGoodsType(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/notLimitList",
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<GoodsType>
|
||||
|
||||
/**
|
||||
* 获取字典数据
|
||||
*/
|
||||
@GET("pad/dataList")
|
||||
suspend fun getDictType(@Query("type") type: String): ApiResponse<List<DictType>>
|
||||
@GET//("pad/dataList")
|
||||
suspend fun getDictType(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/dataList",
|
||||
@Query("type") type: String,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<List<DictType>>
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
@Multipart
|
||||
@POST("sys/common/upload")
|
||||
@POST//("sys/common/upload")
|
||||
suspend fun uploadImage(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/sys/common/upload",
|
||||
@Part("code") code: RequestBody,
|
||||
@Part file: MultipartBody.Part
|
||||
@Part file: MultipartBody.Part,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<String>
|
||||
|
||||
/**
|
||||
* 搜索物品列表
|
||||
*/
|
||||
@GET("pad/goodsInfoList")
|
||||
@GET//("pad/goodsInfoList")
|
||||
suspend fun searchGoodsInfoList(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/goodsInfoList",
|
||||
@Query("goodsName") goodsName: String,
|
||||
@Query("pageNo") pageNo: Int,
|
||||
@Query("pageSize") pageSize: Int
|
||||
@Query("pageSize") pageSize: Int,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<SearchGoodsInfo>
|
||||
|
||||
/**
|
||||
* 自采添加商品
|
||||
*/
|
||||
@POST("pad/goodsAdd")
|
||||
suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo>
|
||||
@POST//("pad/goodsAdd")
|
||||
suspend fun selfPurchaseGoodsAdd(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/goodsAdd",
|
||||
@Body goodsAddParam: GoodsAddParam,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<SearchGoodsInfo>
|
||||
|
||||
/**
|
||||
* 添加物品采购单位
|
||||
*/
|
||||
@POST("pad/goodsAddUnit")
|
||||
suspend fun goodsAddUnit(@Body purchaseUnitParam: GoodsPurchaseUnitParam): ApiResponse<Boolean>
|
||||
@POST//("pad/goodsAddUnit")
|
||||
suspend fun goodsAddUnit(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/goodsAddUnit",
|
||||
@Body purchaseUnitParam: GoodsPurchaseUnitParam,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<Boolean>
|
||||
|
||||
/**
|
||||
* 自采入库
|
||||
*/
|
||||
@POST("pad/SelfPurchasedGoods")
|
||||
suspend fun selfPurchaseWarehousing(@Body list: List<PurchaseWarehouseParam>): ApiResponse<Boolean>
|
||||
@POST//("pad/SelfPurchasedGoods")
|
||||
suspend fun selfPurchaseWarehousing(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}/pad/SelfPurchasedGoods",
|
||||
@Body list: List<PurchaseWarehouseParam>,
|
||||
@Header("x-access-token") token: String = GlobalData.appToken
|
||||
): ApiResponse<Boolean>
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class RequestInterceptor : Interceptor {
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
// .header("Authorization", "Bearer ${getToken()}")
|
||||
.header("x-access-token", getToken())
|
||||
// .header("x-access-token", getToken())
|
||||
|
||||
val newRequest = requestBuilder.build()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.sw.inbound.receiver
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.sw.inbound.MainActivity
|
||||
import com.sw.inbound.InitActivity
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ class BootReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (Intent.ACTION_BOOT_COMPLETED == intent.action) {
|
||||
Timber.d("设备启动完成,开始执行自启动逻辑")
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
val intent = Intent(context, InitActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.sw.inbound.model.request.PurchaseWarehouseParam
|
||||
import com.sw.inbound.model.request.UploadInfo
|
||||
import com.sw.inbound.model.response.ApiResponse
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.model.response.GoodsType
|
||||
import com.sw.inbound.model.response.PurchaseInfo
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
@@ -28,20 +29,42 @@ import javax.inject.Inject
|
||||
class RemoteRepository @Inject constructor(
|
||||
private val apiService: ApiService
|
||||
) : BaseRepository() {
|
||||
/**
|
||||
* 生成token
|
||||
*/
|
||||
suspend fun getDeviceToken(qrcodeId: String): ApiResponse<String> {
|
||||
return safeApiCall {
|
||||
apiService.getDeviceToken(
|
||||
qrcodeId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备信息
|
||||
*/
|
||||
suspend fun getDeviceInfo(equipmentCode: String, token: String): ApiResponse<EquipmentInfo> {
|
||||
return safeApiCall {
|
||||
apiService.getDeviceInfo(
|
||||
equipmentCode = equipmentCode,
|
||||
token = token
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun login(loginParam: LoginParam): ApiResponse<User> {
|
||||
return safeApiCall { apiService.login(loginParam) }
|
||||
return safeApiCall { apiService.login(body = loginParam) }
|
||||
}
|
||||
|
||||
suspend fun getReceiveList(pageNum: Int, pageSize: Int): ApiResponse<SupplierResponse> {
|
||||
return safeApiCall {
|
||||
apiService.getReceiveList(pageNum, pageSize)
|
||||
apiService.getReceiveList(pageNo = pageNum, pageSize = pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getReceiveDetail(id: Int): ApiResponse<PurchaseInfo> {
|
||||
return safeApiCall {
|
||||
apiService.getReceiveDetail(id)
|
||||
apiService.getReceiveDetail(id = id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +99,7 @@ class RemoteRepository @Inject constructor(
|
||||
|
||||
suspend fun getDictType(type: TypeEnum): ApiResponse<List<DictType>> {
|
||||
return safeApiCall {
|
||||
apiService.getDictType(type.string)
|
||||
apiService.getDictType(type = type.string)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +127,7 @@ class RemoteRepository @Inject constructor(
|
||||
*/
|
||||
suspend fun partialReceipt(uploadInfo: UploadInfo): ApiResponse<Boolean> {
|
||||
return safeApiCall {
|
||||
apiService.partialReceipt(uploadInfo)
|
||||
apiService.partialReceipt(uploadInfo = uploadInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +136,7 @@ class RemoteRepository @Inject constructor(
|
||||
*/
|
||||
suspend fun confirmReceipt(uploadInfo: UploadInfo): ApiResponse<Boolean> {
|
||||
return safeApiCall {
|
||||
apiService.confirmReceipt(uploadInfo)
|
||||
apiService.confirmReceipt(uploadInfo = uploadInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +146,11 @@ class RemoteRepository @Inject constructor(
|
||||
pageSize: Int = 10
|
||||
): ApiResponse<SearchGoodsInfo> {
|
||||
return safeApiCall {
|
||||
apiService.searchGoodsInfoList(goodsName, pageNo, pageSize)
|
||||
apiService.searchGoodsInfoList(
|
||||
goodsName = goodsName,
|
||||
pageNo = pageNo,
|
||||
pageSize = pageSize
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,13 +159,13 @@ class RemoteRepository @Inject constructor(
|
||||
*/
|
||||
suspend fun selfPurchaseGoodsAdd(goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo> {
|
||||
return safeApiCall {
|
||||
apiService.selfPurchaseGoodsAdd(goodsAddParam)
|
||||
apiService.selfPurchaseGoodsAdd(goodsAddParam = goodsAddParam)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun selfPurchaseGoodsAddUnit(addParam: GoodsPurchaseUnitParam): ApiResponse<Boolean> {
|
||||
return safeApiCall {
|
||||
apiService.goodsAddUnit(addParam)
|
||||
apiService.goodsAddUnit(purchaseUnitParam = addParam)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +174,7 @@ class RemoteRepository @Inject constructor(
|
||||
*/
|
||||
suspend fun selfPurchaseWarehousing(list: List<PurchaseWarehouseParam>): ApiResponse<Boolean> {
|
||||
return safeApiCall {
|
||||
apiService.selfPurchaseWarehousing(list)
|
||||
apiService.selfPurchaseWarehousing(list = list)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,751 @@
|
||||
package com.sw.inbound.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,103 @@
|
||||
package com.sw.inbound.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
|
||||
import kotlin.apply
|
||||
import kotlin.ranges.until
|
||||
import kotlin.text.isEmpty
|
||||
|
||||
/**
|
||||
* 二维码生成工具类
|
||||
*/
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.model.response.ApiResponse
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.model.response.GoodsInfo
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
import com.sw.inbound.network.LoadingState
|
||||
@@ -270,4 +271,13 @@ abstract class BaseViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun parseEquipmentInfo(equipmentInfo: EquipmentInfo) {
|
||||
GlobalData.appBaseUrl = equipmentInfo.appPackageUrl!!
|
||||
GlobalData.sdkKey = equipmentInfo.arcsoftSdkKey!!
|
||||
GlobalData.appId = equipmentInfo.arcsoftAppId!!
|
||||
// GlobalData.activeKey = equipmentInfo.arcsoftActiveKey!!
|
||||
GlobalData.restId = equipmentInfo.canteenId!!
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.sw.inbound.viewmodel
|
||||
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.GlobalKey
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.repository.RemoteRepository
|
||||
import com.sw.inbound.utils.GsonUtils
|
||||
import com.sw.inbound.utils.SPUtil
|
||||
import com.sw.inbound.utils.ToastUtils
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import kotlin.jvm.java
|
||||
|
||||
/**
|
||||
* 初始化的viewmodel
|
||||
*/
|
||||
@HiltViewModel
|
||||
class DeviceViewModel @Inject constructor(
|
||||
private val repository: RemoteRepository
|
||||
) : BaseViewModel(repository) {
|
||||
private val _deviceInfoResult = MutableStateFlow<Boolean?>(null)
|
||||
val deviceInfoResult: StateFlow<Boolean?> = _deviceInfoResult
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
*/
|
||||
fun getDeviceToken(deviceId: String = GlobalData.deviceId) {
|
||||
launchWithLoading {
|
||||
val response = repository.getDeviceToken(deviceId)
|
||||
if (parseResponse(response)) {
|
||||
val response1 = repository.getDeviceInfo(deviceId, response.result!!)
|
||||
|
||||
if (parseResponse(response1)) {
|
||||
val equipmentInfo = response1.result
|
||||
if (equipmentInfo == null) return@launchWithLoading
|
||||
try {
|
||||
parseEquipmentInfo(equipmentInfo)
|
||||
SPUtil.getInstance()
|
||||
.put(GlobalKey.KEY_EQUIPMENT_INFO, GsonUtils.toJson(equipmentInfo))
|
||||
_deviceInfoResult.value = true
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.showToast("获取设备信息失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查缓存数据
|
||||
*/
|
||||
fun checkEquipmentInfo(): Boolean {
|
||||
val equipmentInfoStr = SPUtil.getInstance().get(GlobalKey.KEY_EQUIPMENT_INFO, "")
|
||||
if (equipmentInfoStr == null) {
|
||||
Timber.e("获取缓存设备信息失败")
|
||||
return false
|
||||
}
|
||||
val equipmentInfo =
|
||||
GsonUtils.fromJson<EquipmentInfo>(equipmentInfoStr, EquipmentInfo::class.java)
|
||||
if (equipmentInfo == null) {
|
||||
Timber.e("解析缓存设备信息失败")
|
||||
return false
|
||||
}
|
||||
try {
|
||||
parseEquipmentInfo(equipmentInfo)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleSensorScale(weight: Double) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.sw.inbound.viewmodel
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.GlobalKey
|
||||
import com.sw.inbound.model.request.LoginParam
|
||||
import com.sw.inbound.model.response.User
|
||||
@@ -57,6 +58,7 @@ class UserViewModel @Inject constructor(
|
||||
user?.let {
|
||||
SPUtil.getInstance().put(GlobalKey.KEY_USER_INFO, GsonUtils.toJson(it))
|
||||
SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, it.token)
|
||||
GlobalData.appToken = it.token?:""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:width="1920dp" android:height="1080dp">
|
||||
<bitmap android:src="@mipmap/bg"/>
|
||||
</item>
|
||||
<item
|
||||
android:width="270dp"
|
||||
android:height="258dp"
|
||||
android:gravity="top|center_horizontal"
|
||||
android:top="90dp">
|
||||
<bitmap android:src="@drawable/img_init" android:scaleType="fitCenter"/>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 999 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Inbound" parent="android:Theme.Material.Light.NoActionBar" />
|
||||
<style name="Theme.Inbound" parent="android:Theme.Material.Light.NoActionBar" >
|
||||
<item name="android:windowBackground">@drawable/bg_splash</item>
|
||||
</style>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user