build(servicing): 更新构建配置并升级版本号
-禁用 release 和 debug 构建类型的代码压缩 - 添加 publishNonDefault 配置项 -将版本号从 1.0.1.9.9.126 升级到 1.0.1.9.9.127
258
app/proguard-rules.pro
vendored
@ -19,3 +19,261 @@
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-dontwarn java.lang.invoke.StringConcatFactory
|
||||
|
||||
# 保留行号用于调试
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-renamesourcefileattribute SourceFile
|
||||
|
||||
# 保留基本属性
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes Exceptions
|
||||
-keepattributes InnerClasses
|
||||
|
||||
-dontwarn com.github.luben.zstd.BufferPool
|
||||
-dontwarn com.github.luben.zstd.ZstdInputStream
|
||||
-dontwarn com.github.luben.zstd.ZstdOutputStream
|
||||
-dontwarn org.brotli.dec.BrotliInputStream
|
||||
-dontwarn org.objectweb.asm.AnnotationVisitor
|
||||
-dontwarn org.objectweb.asm.Attribute
|
||||
-dontwarn org.objectweb.asm.ClassReader
|
||||
-dontwarn org.objectweb.asm.ClassVisitor
|
||||
-dontwarn org.objectweb.asm.FieldVisitor
|
||||
-dontwarn org.objectweb.asm.Label
|
||||
-dontwarn org.objectweb.asm.MethodVisitor
|
||||
-dontwarn org.objectweb.asm.Type
|
||||
|
||||
# 保留R文件
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
## 保留servicing模块中的所有model类
|
||||
#-keep class com.za.bean.** { *; }
|
||||
#-keep class com.za.bean.db.** { *; }
|
||||
#-keep class com.za.bean.request.** { *; }
|
||||
#
|
||||
## 保留servicing模块中的所有接口
|
||||
#-keep interface com.za.servicing.** { *; }
|
||||
#-keep interface com.za.net.** { *; }
|
||||
#
|
||||
## 保留servicing模块中的所有枚举
|
||||
#-keepclassmembers enum com.za.** { *; }
|
||||
#
|
||||
## 保留Room数据库相关类
|
||||
#-keep class com.za.room.** { *; }
|
||||
#-keep class com.za.room.db.** { *; }
|
||||
#-keep class * extends androidx.room.RoomDatabase
|
||||
#-keep @androidx.room.Entity class *
|
||||
#-keep @androidx.room.Dao interface *
|
||||
|
||||
# 保留Parcelable实现类
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
# 保留Serializable实现类
|
||||
-keepnames class * implements java.io.Serializable
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
!static !transient <fields>;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
# 保留WebView相关
|
||||
-keepclassmembers class * extends android.webkit.WebViewClient {
|
||||
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
|
||||
public boolean *(android.webkit.WebView, java.lang.String);
|
||||
}
|
||||
-keepclassmembers class * extends android.webkit.WebViewClient {
|
||||
public void *(android.webkit.WebView, java.lang.String);
|
||||
}
|
||||
|
||||
# 保留native方法
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
## 保留View的getter和setter
|
||||
#-keepclassmembers public class * extends android.view.View {
|
||||
# void set*(***); *** get*();
|
||||
#}
|
||||
|
||||
# CameraX相关
|
||||
#-keep class androidx.camera.** { *; }
|
||||
#-dontwarn androidx.camera.**
|
||||
#
|
||||
## Coil图片加载库
|
||||
#-keep class coil.** { *; }
|
||||
#-dontwarn coil.**
|
||||
#
|
||||
## PermissionX权限库
|
||||
#-keep class com.permissionx.guolindev.** { *; }
|
||||
#
|
||||
## 高德地图相关
|
||||
#-keep class com.amap.api.**{*;}
|
||||
#-keep class com.autonavi.**{*;}
|
||||
#-keep class com.loc.**{*;}
|
||||
#-dontwarn com.amap.api.**
|
||||
#-dontwarn com.autonavi.**
|
||||
#-dontwarn com.loc.**
|
||||
#
|
||||
## JPush相关
|
||||
#-dontoptimize
|
||||
#-dontwarn cn.jpush.**
|
||||
#-keep class cn.jpush.** { *; }
|
||||
#-dontwarn cn.jcore.**
|
||||
#-keep class cn.jcore.** { *; }
|
||||
#
|
||||
## Retrofit网络库
|
||||
#-keepattributes Signature
|
||||
#-keepattributes Exceptions
|
||||
#-dontwarn retrofit2.**
|
||||
#-keep class retrofit2.** { *; }
|
||||
#-keepclasseswithmembers class * {
|
||||
# @retrofit2.http.* <methods>;
|
||||
#}
|
||||
#
|
||||
## OkHttp
|
||||
#-dontwarn okhttp3.**
|
||||
#-dontwarn okio.**
|
||||
#-keep class okhttp3.** { *; }
|
||||
#-keep class okio.** { *; }
|
||||
#
|
||||
## RxJava
|
||||
#-dontwarn io.reactivex.**
|
||||
#-keep class io.reactivex.** { *; }
|
||||
#-dontwarn sun.misc.**
|
||||
#-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
|
||||
# long producerIndex;
|
||||
# long consumerIndex;
|
||||
#}
|
||||
#
|
||||
## BlankJ工具库
|
||||
#-dontwarn com.blankj.utilcode.**
|
||||
#-keep class com.blankj.utilcode.** { *; }
|
||||
#-keepclassmembers class * {
|
||||
# @com.blankj.utilcode.util.BusUtils$Bus <methods>;
|
||||
#}
|
||||
#-keep public class * extends com.blankj.utilcode.util.ApiUtils$BaseApi
|
||||
#-keep,allowobfuscation @interface com.blankj.utilcode.util.ApiUtils$Api
|
||||
#-keep @com.blankj.utilcode.util.ApiUtils$Api class *
|
||||
#
|
||||
##mmkv
|
||||
#-renamesourcefileattribute SourceFile
|
||||
#-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,EnclosingMethod
|
||||
#-keep public class * {
|
||||
# public protected *;
|
||||
#}
|
||||
##
|
||||
### 保留所有类的方法名
|
||||
##-keepclassmembernames class * {
|
||||
## java.lang.Class class$(java.lang.String);
|
||||
## java.lang.Class class$(java.lang.String, boolean);
|
||||
##}
|
||||
#
|
||||
## 保留枚举类中的特殊静态方法
|
||||
#-keepclassmembers class * extends java.lang.Enum {
|
||||
# public static **[] values();
|
||||
# public static ** valueOf(java.lang.String);
|
||||
#}
|
||||
#
|
||||
## MQTT相关
|
||||
#-keep class org.eclipse.paho.** { *; }
|
||||
#-dontwarn org.eclipse.paho.**
|
||||
#
|
||||
## Gson
|
||||
#-keep class com.google.gson.** { *; }
|
||||
#-keepattributes Signature
|
||||
#-keepattributes *Annotation*
|
||||
#-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
#-keep class * implements com.google.gson.JsonSerializer
|
||||
#-keep class * implements com.google.gson.JsonDeserializer
|
||||
#
|
||||
### Kotlin相关
|
||||
###-keep class kotlin.** { *; }
|
||||
##-keep class kotlin.Metadata { *; }
|
||||
##-dontwarn kotlin.**
|
||||
##-keepclassmembers class **$WhenMappings {
|
||||
## <fields>;
|
||||
##}
|
||||
##-keepclassmembers class kotlin.Metadata {
|
||||
## public <methods>;
|
||||
##}
|
||||
#
|
||||
## Kotlin协程
|
||||
##-keepclassmembernames class kotlinx.** {
|
||||
## volatile <fields>;
|
||||
##}
|
||||
##-keepclassmembers class * {
|
||||
## @kotlin.coroutines.jvm.internal.DebugMetadata *;
|
||||
## @kotlin.coroutines.jvm.internal.SuspendLambda *;
|
||||
##}
|
||||
##-keep class kotlinx.coroutines.** { *; }
|
||||
##-dontwarn kotlinx.coroutines.**
|
||||
#
|
||||
## Kotlin反射
|
||||
##-keep class kotlin.reflect.** { *; }
|
||||
##-dontwarn kotlin.reflect.**
|
||||
#
|
||||
## 保留Kotlin数据类
|
||||
##-keepclassmembers class ** {
|
||||
## public ** component*();
|
||||
## public ** copy(...);
|
||||
##}
|
||||
#
|
||||
## 保留Kotlin数据类的toString/hashCode/equals方法
|
||||
##-keepclassmembers class ** {
|
||||
## public java.lang.String toString();
|
||||
## public int hashCode();
|
||||
## public boolean equals(java.lang.Object);
|
||||
##}
|
||||
##
|
||||
### 保留Compose相关
|
||||
##-keep class androidx.compose.** { *; }
|
||||
##-dontwarn androidx.compose.**
|
||||
##
|
||||
### 保留自定义签名相关类
|
||||
##-keep class com.za.signature.** { *; }
|
||||
##
|
||||
### 保留Face Detection相关
|
||||
##-keep class com.google.mlkit.** { *; }
|
||||
##-dontwarn com.google.mlkit.**
|
||||
#
|
||||
## 保留ZXing相关
|
||||
#-keep class com.google.zxing.** { *; }
|
||||
#-dontwarn com.google.zxing.**
|
||||
#
|
||||
## 保留Glide相关
|
||||
#-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
#-keep class * extends com.bumptech.glide.module.AppGlideModule {
|
||||
# <init>(...);
|
||||
#}
|
||||
#-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
# **[] $VALUES;
|
||||
# public *;
|
||||
#}
|
||||
#-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
|
||||
# *** rewind();
|
||||
#}
|
||||
#
|
||||
## 保留FastJSON相关
|
||||
#-keep class com.alibaba.fastjson.** { *; }
|
||||
#-dontwarn com.alibaba.fastjson.**
|
||||
#
|
||||
## 保留Bugly相关
|
||||
#-keep class com.tencent.bugly.** { *; }
|
||||
#-dontwarn com.tencent.bugly.**
|
||||
##
|
||||
### 保留自定义UI组件
|
||||
###-keep class com.za.ui.** { *; }
|
||||
###-keep class com.za.base.** { *; }
|
||||
##
|
||||
### 保留Java 8 Lambda表达式
|
||||
##-dontwarn java.lang.invoke.StringConcatFactory
|
@ -1,23 +0,0 @@
|
||||
package com.za.sdk.demo
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() { // Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.za.sdk.demo", appContext.packageName)
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
[versions]
|
||||
accompanistPager = "0.32.0"
|
||||
cameraCore = "1.4.1"
|
||||
coilCompose = "2.6.0"
|
||||
commonsCompress = "1.23.0"
|
||||
@ -6,15 +7,13 @@ compiler = "4.14.2"
|
||||
converterGson = "2.9.0"
|
||||
core = "3.5.3"
|
||||
crashreport = "4.0.4"
|
||||
faceDetection = "16.1.7"
|
||||
fastjson = "1.2.69"
|
||||
glide = "4.16.0"
|
||||
gson = "2.11.0"
|
||||
jcore = "5.0.0"
|
||||
faceDetection = "16.1.7"
|
||||
jpush = "5.6.0"
|
||||
location = "5.6.1"
|
||||
loggingInterceptor = "4.11.0"
|
||||
#这是一个长期维护的版本,不建议升级
|
||||
mmkv = "1.3.11"
|
||||
orgEclipsePahoAndroidService = "1.1.1"
|
||||
orgEclipsePahoClientMqttv3 = "1.2.5"
|
||||
@ -39,14 +38,19 @@ rxjava = "3.1.7"
|
||||
search = "7.3.0"
|
||||
tbssdk = "44286"
|
||||
uiGraphics = "1.7.7"
|
||||
uiTooling = "1.7.7"
|
||||
uiToolingPreview = "1.7.7"
|
||||
uiVersion = "1.7.7"
|
||||
utilcodex = "1.31.1"
|
||||
workRuntimeKtx = "2.10.0"
|
||||
xdmap = "8.1.0"
|
||||
activity = "1.10.0"
|
||||
xz = "1.9"
|
||||
exifinterface = "1.3.7"
|
||||
uiToolingVersion = "1.4.0"
|
||||
[libraries]
|
||||
accompanist-pager = { module = "com.google.accompanist:accompanist-pager", version.ref = "accompanistPager" }
|
||||
accompanist-pager-indicators = { module = "com.google.accompanist:accompanist-pager-indicators", version.ref = "accompanistPager" }
|
||||
adapter-rxjava3 = { module = "com.squareup.retrofit2:adapter-rxjava3", version.ref = "converterGson" }
|
||||
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCore" }
|
||||
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraCore" }
|
||||
@ -60,6 +64,7 @@ androidx-ui = { module = "androidx.compose.ui:ui", version.ref = "uiVersion" }
|
||||
androidx-ui-graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "uiGraphics" }
|
||||
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "uiGraphics" }
|
||||
androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "uiGraphics" }
|
||||
androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "uiTooling" }
|
||||
androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "uiToolingPreview" }
|
||||
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" }
|
||||
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" }
|
||||
@ -69,6 +74,7 @@ compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "compi
|
||||
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
|
||||
core = { module = "com.google.zxing:core", version.ref = "core" }
|
||||
crashreport = { module = "com.tencent.bugly:crashreport", version.ref = "crashreport" }
|
||||
face-detection = { module = "com.google.mlkit:face-detection", version.ref = "faceDetection" }
|
||||
fastjson = { module = "com.alibaba:fastjson", version.ref = "fastjson" }
|
||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
@ -96,12 +102,13 @@ search = { module = "com.amap.api:search", version.ref = "search" }
|
||||
tbssdk = { module = "com.tencent.tbs:tbssdk", version.ref = "tbssdk" }
|
||||
utilcodex = { module = "com.blankj:utilcodex", version.ref = "utilcodex" }
|
||||
xdmap = { module = "com.amap.api:3dmap", version.ref = "xdmap" }
|
||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||
xz = { module = "org.tukaani:xz", version.ref = "xz" }
|
||||
androidx-exifinterface = { group = "androidx.exifinterface", name = "exifinterface", version.ref = "exifinterface" }
|
||||
face-detection = { module = "com.google.mlkit:face-detection", version.ref = "faceDetection" }
|
||||
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiToolingPreview" }
|
||||
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiToolingVersion" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
android-library = { id = "com.android.library", version.ref = "agp" }
|
||||
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
|
@ -31,7 +31,7 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
publishNonDefault true
|
||||
// publishNonDefault true
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
@ -64,7 +64,7 @@ publishing {
|
||||
release(MavenPublication) {
|
||||
groupId = 'io.github.szl9'
|
||||
artifactId = 'zd_servicing'
|
||||
version = "1.0.1.9.9.127"
|
||||
version = "1.0.1.9.9.138"
|
||||
|
||||
pom {
|
||||
packaging = "aar"
|
||||
|
106
servicing/proguard-rules.pro
vendored
@ -1,3 +1,5 @@
|
||||
-dontwarn java.lang.invoke.StringConcatFactory
|
||||
|
||||
# 保留行号用于调试
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-renamesourcefileattribute SourceFile
|
||||
@ -8,19 +10,42 @@
|
||||
-keepattributes Exceptions
|
||||
-keepattributes InnerClasses
|
||||
|
||||
-dontwarn com.github.luben.zstd.BufferPool
|
||||
-dontwarn com.github.luben.zstd.ZstdInputStream
|
||||
-dontwarn com.github.luben.zstd.ZstdOutputStream
|
||||
-dontwarn org.brotli.dec.BrotliInputStream
|
||||
-dontwarn org.objectweb.asm.AnnotationVisitor
|
||||
-dontwarn org.objectweb.asm.Attribute
|
||||
-dontwarn org.objectweb.asm.ClassReader
|
||||
-dontwarn org.objectweb.asm.ClassVisitor
|
||||
-dontwarn org.objectweb.asm.FieldVisitor
|
||||
-dontwarn org.objectweb.asm.Label
|
||||
-dontwarn org.objectweb.asm.MethodVisitor
|
||||
-dontwarn org.objectweb.asm.Type
|
||||
|
||||
# 保留R文件
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
# 保留servicing模块中的所有model类
|
||||
-keep class com.za.servicing.model.** { *; }
|
||||
-keep class com.za.bean.** { *; }
|
||||
-keep class com.za.bean.db.** { *; }
|
||||
-keep class com.za.bean.request.** { *; }
|
||||
|
||||
# 保留servicing模块中的所有接口
|
||||
-keep interface com.za.servicing.** { *; }
|
||||
-keep interface com.za.net.** { *; }
|
||||
|
||||
# 保留servicing模块中的所有枚举
|
||||
-keepclassmembers enum com.za.servicing.** { *; }
|
||||
-keepclassmembers enum com.za.** { *; }
|
||||
|
||||
# 保留Room数据库相关类
|
||||
-keep class com.za.room.** { *; }
|
||||
-keep class com.za.room.db.** { *; }
|
||||
-keep class * extends androidx.room.RoomDatabase
|
||||
-keep @androidx.room.Entity class *
|
||||
-keep @androidx.room.Dao interface *
|
||||
|
||||
# 保留Parcelable实现类
|
||||
-keep class * implements android.os.Parcelable {
|
||||
@ -58,6 +83,10 @@
|
||||
void set*(***); *** get*();
|
||||
}
|
||||
|
||||
# CameraX相关
|
||||
-keep class androidx.camera.** { *; }
|
||||
-dontwarn androidx.camera.**
|
||||
|
||||
# Coil图片加载库
|
||||
-keep class coil.** { *; }
|
||||
-dontwarn coil.**
|
||||
@ -75,7 +104,6 @@
|
||||
|
||||
# JPush相关
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
-dontwarn cn.jpush.**
|
||||
-keep class cn.jpush.** { *; }
|
||||
-dontwarn cn.jcore.**
|
||||
@ -105,13 +133,12 @@
|
||||
long consumerIndex;
|
||||
}
|
||||
|
||||
#blankJ
|
||||
# BlankJ工具库
|
||||
-dontwarn com.blankj.utilcode.**
|
||||
|
||||
-keep class com.blankj.utilcode.** { *; }
|
||||
-keepclassmembers class * {
|
||||
@com.blankj.utilcode.util.BusUtils$Bus <methods>;
|
||||
}
|
||||
|
||||
-keep public class * extends com.blankj.utilcode.util.ApiUtils$BaseApi
|
||||
-keep,allowobfuscation @interface com.blankj.utilcode.util.ApiUtils$Api
|
||||
-keep @com.blankj.utilcode.util.ApiUtils$Api class *
|
||||
@ -122,41 +149,27 @@
|
||||
-keep public class * {
|
||||
public protected *;
|
||||
}
|
||||
# Preserve all .class method names.
|
||||
|
||||
# 保留所有类的方法名
|
||||
-keepclassmembernames class * {
|
||||
java.lang.Class class$(java.lang.String);
|
||||
java.lang.Class class$(java.lang.String, boolean);
|
||||
}
|
||||
|
||||
# Preserve all native method names and the names of their classes.
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# Preserve the special static methods that are required in all enumeration
|
||||
# classes.
|
||||
|
||||
# 保留枚举类中的特殊静态方法
|
||||
-keepclassmembers class * extends java.lang.Enum {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
# MQTT相关
|
||||
-keep class org.eclipse.paho.** { *; }
|
||||
-dontwarn org.eclipse.paho.**
|
||||
|
||||
# Gson
|
||||
-keep class com.google.gson.** { *; }
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
-keep class * implements com.google.gson.JsonSerializer
|
||||
-keep class * implements com.google.gson.JsonDeserializer
|
||||
@ -192,7 +205,7 @@
|
||||
public ** component*();
|
||||
public ** copy(...);
|
||||
}
|
||||
|
||||
#
|
||||
# 保留Kotlin数据类的toString/hashCode/equals方法
|
||||
-keepclassmembers class ** {
|
||||
public java.lang.String toString();
|
||||
@ -200,4 +213,45 @@
|
||||
public boolean equals(java.lang.Object);
|
||||
}
|
||||
|
||||
# 保留Compose相关
|
||||
-keep class androidx.compose.** { *; }
|
||||
-dontwarn androidx.compose.**
|
||||
|
||||
# 保留自定义签名相关类
|
||||
-keep class com.za.signature.** { *; }
|
||||
|
||||
# 保留Face Detection相关
|
||||
-keep class com.google.mlkit.** { *; }
|
||||
-dontwarn com.google.mlkit.**
|
||||
|
||||
# 保留ZXing相关
|
||||
-keep class com.google.zxing.** { *; }
|
||||
-dontwarn com.google.zxing.**
|
||||
|
||||
# 保留Glide相关
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep class * extends com.bumptech.glide.module.AppGlideModule {
|
||||
<init>(...);
|
||||
}
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
|
||||
*** rewind();
|
||||
}
|
||||
|
||||
# 保留FastJSON相关
|
||||
-keep class com.alibaba.fastjson.** { *; }
|
||||
-dontwarn com.alibaba.fastjson.**
|
||||
|
||||
# 保留Bugly相关
|
||||
-keep class com.tencent.bugly.** { *; }
|
||||
-dontwarn com.tencent.bugly.**
|
||||
#
|
||||
# 保留自定义UI组件
|
||||
-keep class com.za.ui.** { *; }
|
||||
-keep class com.za.base.** { *; }
|
||||
|
||||
# 保留Java 8 Lambda表达式
|
||||
-dontwarn java.lang.invoke.StringConcatFactory
|
@ -61,6 +61,7 @@ object Const {
|
||||
const val RE_DISPATCH = "reDispatch"
|
||||
const val MODIFY = "modify"
|
||||
const val REVOKE = "revoke"
|
||||
const val REPORT_HANDLE = "report_handle"
|
||||
const val GO_MAIN_PAGE = "goMainPage"
|
||||
}
|
||||
}
|
@ -40,9 +40,7 @@ abstract class IServicingVm<T, U> : BaseVm<T, U>() {
|
||||
getCurrentOrder()?.getTaskNode() ?: 0,
|
||||
getCurrentOrder()?.userOrderId ?: 0)
|
||||
success(data)
|
||||
}, failed = {
|
||||
failure(it)
|
||||
})
|
||||
}, failed = {})
|
||||
} else {
|
||||
success(photoTemplateList)
|
||||
}
|
||||
|
@ -39,6 +39,12 @@ open class PushMessageActivity : AppCompatActivity() {
|
||||
context = this@PushMessageActivity)
|
||||
}
|
||||
|
||||
override fun reportHandle(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(type = Const.PushMessageType.REPORT_HANDLE,
|
||||
message = Gson().toJson(jpushBean),
|
||||
context = this@PushMessageActivity)
|
||||
}
|
||||
|
||||
override fun newOrderMsg(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(type = Const.PushMessageType.NEW_ORDER,
|
||||
message = Gson().toJson(jpushBean),
|
||||
|
@ -15,7 +15,10 @@ import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
@ -61,12 +64,17 @@ fun DealerTheme(darkTheme : Boolean = isSystemInDarkTheme(), content : @Composab
|
||||
}
|
||||
}
|
||||
}
|
||||
val fontScale = LocalDensity.current.fontScale
|
||||
val displayMetrics = LocalContext.current.resources.displayMetrics
|
||||
val widthPixels = displayMetrics.widthPixels
|
||||
|
||||
MaterialTheme(colorScheme = colorScheme) {
|
||||
CompositionLocalProvider(LocalRippleConfiguration provides RippleConfiguration(rippleAlpha = RippleAlpha(
|
||||
0f,
|
||||
0f,
|
||||
0f,
|
||||
0f))) {
|
||||
0f)),
|
||||
LocalDensity provides Density(fontScale = 1f, density = widthPixels / 360f)) {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.bodyLarge, content = content)
|
||||
}
|
||||
}
|
||||
|
@ -174,9 +174,6 @@ data class HistoryPhotoTemplateItem(
|
||||
|
||||
//获取拍照时间
|
||||
fun getPhotoTakeTime(taskState : String, historyTaskBean : HistoryTaskBean?) : String? {
|
||||
if (! takePhotoTime.isNullOrBlank()) {
|
||||
return takePhotoTime
|
||||
}
|
||||
return when (taskState) {
|
||||
"13001", "15001" -> historyTaskBean?.arriveTime
|
||||
"17001" -> {
|
||||
@ -197,9 +194,6 @@ data class HistoryPhotoTemplateItem(
|
||||
}
|
||||
|
||||
fun getPhotoLat(taskState : String, historyTaskBean : HistoryTaskBean?) : Double? {
|
||||
if (! lat.isNullOrBlank()) {
|
||||
return lat.toDouble()
|
||||
}
|
||||
return when (taskState) {
|
||||
"13001", "15001" -> historyTaskBean?.lat
|
||||
"17001", "18001" -> {
|
||||
@ -216,9 +210,6 @@ data class HistoryPhotoTemplateItem(
|
||||
}
|
||||
|
||||
fun getPhotoLng(taskState : String, historyTaskBean : HistoryTaskBean?) : Double? {
|
||||
if (! lon.isNullOrBlank()) {
|
||||
return lon.toDouble()
|
||||
}
|
||||
return when (taskState) {
|
||||
"13001", "15001" -> historyTaskBean?.lng
|
||||
"17001", "18001" -> {
|
||||
@ -235,9 +226,6 @@ data class HistoryPhotoTemplateItem(
|
||||
}
|
||||
|
||||
fun getPhotoAddress(taskState : String, historyTaskBean : HistoryTaskBean?) : String? {
|
||||
if (! takeAddress?.replace("[", "")?.replace("]", "").isNullOrBlank()) {
|
||||
return takeAddress
|
||||
}
|
||||
return when (taskState) {
|
||||
"13001", "15001" -> historyTaskBean?.address
|
||||
"17001", "18001" -> {
|
||||
|
@ -32,3 +32,13 @@ data class TaskNotesBean(val taskNotes : String? = null, //救援要求
|
||||
val otherNotes : String? = null, //特殊提醒
|
||||
val modelVinNo : String? = null, //车型
|
||||
val contract : String? = null) //车型
|
||||
|
||||
|
||||
data class UnifiedOCRWithCompressRequest(
|
||||
val ocrType : Int? = null, // 4为车架号识别 5为车牌号识别
|
||||
val imageUrl : String? = null, // 图片地址
|
||||
val cardSide : String? = null, // FRONT:正面 BACK:反面 默认:FRONT
|
||||
)
|
||||
|
||||
|
||||
data class SaveSignatureRequest(val signatureUrl : String? = null, val driverId : Int? = null)
|
@ -22,6 +22,7 @@ data class PhotoTemplateInfo(
|
||||
val numbering : String? = null, // 图片编号
|
||||
val recognizeType : Int? = null, //orc 识别类型 0 无 1 车牌号 2 车架号
|
||||
//以下属性非后台返回属性
|
||||
val serviceTypeName : String? = null, //服务类型名称
|
||||
val userOrderId : Int? = null,
|
||||
val taskCode : String? = null,
|
||||
val taskId : Int? = null,
|
||||
|
@ -7,6 +7,7 @@ import com.tencent.mmkv.MMKV
|
||||
import com.za.base.AppConfig
|
||||
import com.za.base.Const
|
||||
import com.za.bean.db.order.OrderInfo
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.room.RoomHelper
|
||||
import com.za.room.db.user.DriverInfoBean
|
||||
import com.za.service.location.ZdLocationManager
|
||||
@ -49,14 +50,26 @@ object GlobalData : GlobalLocalData() {
|
||||
|
||||
var driverInfoBean : DriverInfoBean? = null
|
||||
get() {
|
||||
if (field == null) {
|
||||
field = localDriverInfoBean
|
||||
return try {
|
||||
val driverInfo = MMKV.defaultMMKV()
|
||||
.decodeParcelable("driverInfoBean", DriverInfoBean::class.java)
|
||||
field = driverInfo
|
||||
field
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("local_driverInfoBean", "获取司机信息失败: ${e.message}")
|
||||
null
|
||||
}
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
localDriverInfoBean = value
|
||||
try {
|
||||
MMKV.defaultMMKV().encode("driverInfoBean", value)
|
||||
if (value != null) {
|
||||
lastLoginBean = value
|
||||
}
|
||||
field = value
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("set local_driverInfoBean", "保存司机信息失败: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -139,6 +152,45 @@ object GlobalData : GlobalLocalData() {
|
||||
mmkv.encode("isShowKeepAlive", value)
|
||||
}
|
||||
|
||||
|
||||
var lastUploadLogTime : Long
|
||||
get() {
|
||||
return mmkv.decodeLong("lastUploadLogTime", 0)
|
||||
}
|
||||
set(value) {
|
||||
mmkv.encode("lastUploadLogTime", value)
|
||||
}
|
||||
|
||||
var vehicleId : Int? = null
|
||||
get() {
|
||||
field = mmkv.decodeInt("vehicleId")
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
mmkv.encode("vehicleId", value ?: 0)
|
||||
field = value
|
||||
}
|
||||
|
||||
var driverId : Int? = null
|
||||
get() {
|
||||
field = mmkv.decodeInt("driverId")
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
mmkv.encode("driverId", value ?: 0)
|
||||
field = value
|
||||
}
|
||||
|
||||
var deviceId : String? = null
|
||||
get() {
|
||||
field = mmkv.decodeString("deviceId")
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
mmkv.encode("deviceId", value)
|
||||
field = value
|
||||
}
|
||||
|
||||
fun clearUserCache() {
|
||||
token = null
|
||||
aesKey = null
|
||||
@ -147,6 +199,10 @@ object GlobalData : GlobalLocalData() {
|
||||
loginTime = null
|
||||
isLoginRecognition = null
|
||||
isHasShowKeepAlive = false
|
||||
lastUploadLogTime = 0
|
||||
deviceId = null
|
||||
vehicleId = null
|
||||
driverId = null
|
||||
|
||||
if (AppConfig.isRelease) {
|
||||
networkEnv = if (AppConfig.isRelease) {
|
||||
|
@ -2,69 +2,72 @@ package com.za.common.log
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.work.Configuration
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.blankj.utilcode.constant.MemoryConstants
|
||||
import com.blankj.utilcode.util.AppUtils
|
||||
import com.blankj.utilcode.util.DeviceUtils
|
||||
import com.blankj.utilcode.util.FileUtils
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import com.blankj.utilcode.util.TimeUtils
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.util.AppFileManager
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
object LogUtil {
|
||||
private var context : Application? = null
|
||||
private var logDestinationPath : String? = null
|
||||
private var orderLogDirPath : String? = null
|
||||
private var executors : ExecutorService? = null
|
||||
private var normalLogDirPath : String? = null
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
private val logBuffer = StringBuilder()
|
||||
private val isWriting = AtomicBoolean(false)
|
||||
|
||||
//日志上报时间间隔
|
||||
private const val uploadTimeInterval = (30 * 60 * 1000).toLong()
|
||||
|
||||
fun init(context : Application) {
|
||||
this.context = context
|
||||
|
||||
logDestinationPath = AppFileManager.getLogPath(context).also { path ->
|
||||
createDirectoryIfNotExists(path)
|
||||
orderLogDirPath =
|
||||
"$path${File.separator}order_log".also { createDirectoryIfNotExists(it) }
|
||||
normalLogDirPath =
|
||||
"$path${File.separator}normal_log".also { createDirectoryIfNotExists(it) }
|
||||
executors = Executors.newSingleThreadExecutor()
|
||||
val logDestinationPath : String = context.filesDir.absolutePath + File.separator + "Log"
|
||||
val logDesFile = File(logDestinationPath)
|
||||
if (! logDesFile.exists()) {
|
||||
logDesFile.mkdir()
|
||||
}
|
||||
val orderLogDirPath = logDestinationPath + File.separator + "order_log"
|
||||
val orderLogFile = File(orderLogDirPath)
|
||||
if (! orderLogFile.exists()) {
|
||||
orderLogFile.mkdir()
|
||||
}
|
||||
normalLogDirPath = logDestinationPath + File.separator + "normal_log"
|
||||
|
||||
val normalLogFile = File(normalLogDirPath)
|
||||
LogUtils.getConfig().setDir(normalLogDirPath)
|
||||
LogUtils.getConfig().setBorderSwitch(false)
|
||||
LogUtils.getConfig().setLog2FileSwitch(true)
|
||||
LogUtils.getConfig().setStackDeep(1)
|
||||
LogUtils.getConfig().setLogHeadSwitch(false)
|
||||
|
||||
if (! normalLogFile.exists()) {
|
||||
normalLogFile.mkdir()
|
||||
}
|
||||
initializeWorkManager(context)
|
||||
}
|
||||
|
||||
private fun createDirectoryIfNotExists(path : String) {
|
||||
File(path).apply { if (! exists()) mkdir() }
|
||||
}
|
||||
|
||||
private fun initializeWorkManager(context : Application) {
|
||||
if (! WorkManager.isInitialized()) {
|
||||
WorkManager.initialize(context,
|
||||
@ -73,183 +76,157 @@ object LogUtil {
|
||||
|
||||
WorkManager.getInstance(context).apply {
|
||||
cancelAllWorkByTag("logWorkRequest")
|
||||
enqueue(PeriodicWorkRequest.Builder(LogTask::class.java, 20, TimeUnit.MINUTES)
|
||||
enqueue(PeriodicWorkRequest.Builder(LogTask::class.java, 80, TimeUnit.MINUTES)
|
||||
.addTag("logWorkRequest").build())
|
||||
}
|
||||
}
|
||||
|
||||
fun print(tag : String, content : String) {
|
||||
val time = getCurrentTime()
|
||||
val logEntry = "$time---$tag---$content\n"
|
||||
Log.e("normal", "$tag---$content")
|
||||
synchronized(logBuffer) {
|
||||
logBuffer.append(logEntry)
|
||||
fun print(tag : String?, throwable : Throwable?) {
|
||||
if (throwable == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (logBuffer.length > 4096) {
|
||||
coroutineScope.launch {
|
||||
flushBuffer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun print(tag : String, throwable : Throwable) {
|
||||
val content = StringWriter()
|
||||
val printWriter = PrintWriter(content)
|
||||
try {
|
||||
val stringWriter = StringWriter()
|
||||
val printWriter = PrintWriter(stringWriter)
|
||||
throwable.printStackTrace(printWriter)
|
||||
print(tag, content.toString())
|
||||
if (System.currentTimeMillis() - GlobalData.lastUploadLogTime > uploadTimeInterval) {
|
||||
updateNormalLog()
|
||||
}
|
||||
|
||||
private suspend fun flushBuffer() = withContext(Dispatchers.IO) {
|
||||
if (! isWriting.compareAndSet(false, true)) return@withContext
|
||||
|
||||
val logContent : String
|
||||
synchronized(logBuffer) {
|
||||
if (logBuffer.isEmpty()) {
|
||||
isWriting.set(false)
|
||||
return@withContext
|
||||
}
|
||||
logContent = logBuffer.toString()
|
||||
logBuffer.clear()
|
||||
}
|
||||
|
||||
try {
|
||||
val fileName = "normal_log.txt"
|
||||
val logFile = File("$normalLogDirPath${File.separator}$fileName")
|
||||
|
||||
logFile.parentFile?.mkdirs()
|
||||
|
||||
if (! logFile.exists()) {
|
||||
logFile.createNewFile()
|
||||
addLogHead(logFile, getCurrentTime())
|
||||
}
|
||||
|
||||
BufferedWriter(FileWriter(logFile, true)).use { writer ->
|
||||
writer.write(logContent)
|
||||
writer.flush()
|
||||
}
|
||||
|
||||
if (logFile.length() >= 8 * MemoryConstants.MB) {
|
||||
rotateLogFile(logFile)
|
||||
}
|
||||
} catch (e : IOException) {
|
||||
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
|
||||
LogUtils.getConfig().setFilePrefix(this.vehicleName)
|
||||
LogUtils.e("$tag---$stringWriter")
|
||||
} catch (e : Exception) {
|
||||
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
|
||||
} finally {
|
||||
isWriting.set(false)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun rotateLogFile(file : File) {
|
||||
if (! file.exists()) return
|
||||
|
||||
val newFileName = buildString {
|
||||
append(AppUtils.getAppVersionCode())
|
||||
append("_")
|
||||
append(GlobalData.driverInfoBean?.vehicleName ?: "unknown")
|
||||
append("_")
|
||||
append(GlobalData.driverInfoBean?.userName ?: "unknown")
|
||||
append("_")
|
||||
append(TimeUtils.getNowString())
|
||||
append(".txt")
|
||||
fun print(tag : String?, content : String?) {
|
||||
if (content == null || content.isEmpty()) {
|
||||
return
|
||||
}
|
||||
if (GlobalData.driverInfoBean == null || GlobalData.driverInfoBean?.vehicleName.isNullOrBlank()) {
|
||||
Log.e(tag, content)
|
||||
return
|
||||
}
|
||||
|
||||
val newFile = File("$normalLogDirPath${File.separator}$newFileName")
|
||||
|
||||
try {
|
||||
if (file.renameTo(newFile)) {
|
||||
compressAndUploadLog(newFile) // 创建新的日志文件
|
||||
file.createNewFile()
|
||||
addLogHead(file, getCurrentTime())
|
||||
} else {
|
||||
print("LogUtil", "Failed to rename log file")
|
||||
if (System.currentTimeMillis() - GlobalData.lastUploadLogTime > uploadTimeInterval) {
|
||||
updateNormalLog()
|
||||
}
|
||||
LogUtils.getConfig().setFilePrefix(this.vehicleName)
|
||||
LogUtils.e("$tag---$content")
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private val vehicleName : String
|
||||
get() {
|
||||
var name : String? = "未知"
|
||||
if (! GlobalData.driverInfoBean?.vehicleName.isNullOrBlank()) {
|
||||
try {
|
||||
name = buildString {
|
||||
append(GlobalData.driverInfoBean?.vehicleName?.replace("/", "")
|
||||
?.replace(" ", ""))
|
||||
append("_")
|
||||
append(GlobalData.driverInfoBean?.userName ?: "未知")
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
print("LogUtil", "Error during log rotation: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun compressAndUploadLog(logFile : File) = coroutineScope.launch {
|
||||
try {
|
||||
val compressedFile = File("${logFile.absolutePath}.7z")
|
||||
compress(logFile, compressedFile.absolutePath)
|
||||
upload(logFile, compressedFile)
|
||||
} catch (e : Exception) {
|
||||
print("LogUtil", e.toString())
|
||||
}
|
||||
return name ?: "未知"
|
||||
}
|
||||
|
||||
private fun deleteLog(file : File) {
|
||||
try {
|
||||
FileUtils.delete(file.absolutePath)
|
||||
file.delete()
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateNormalLog() {
|
||||
thread {
|
||||
if (GlobalData.token.isNullOrBlank()) {
|
||||
return@thread
|
||||
GlobalData.lastUploadLogTime = System.currentTimeMillis()
|
||||
val files = File(normalLogDirPath).listFiles()
|
||||
if (files.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
val fileName = "normal_log.txt"
|
||||
val file = File("$normalLogDirPath${File.separator}$fileName")
|
||||
val reName =
|
||||
"${AppUtils.getAppVersionCode()}_${GlobalData.driverInfoBean?.vehicleName}_${GlobalData.driverInfoBean?.userName}_${TimeUtils.getNowString()}.txt"
|
||||
val reNamePath = "$normalLogDirPath${File.separator}$reName"
|
||||
file.renameTo(File(reNamePath))
|
||||
normalLogDirPath?.let { it ->
|
||||
File(it).listFiles()?.forEach {
|
||||
if (it.length() / MemoryConstants.MB >= 10) {
|
||||
deleteLog(it)
|
||||
return@thread
|
||||
}
|
||||
if (it.exists() && ! it.name.contains("normal_log")) {
|
||||
if (it.name.contains("7z")) {
|
||||
upload(null, desFile = it)
|
||||
for (file in files) {
|
||||
try {
|
||||
if (file.isDirectory()) {
|
||||
file.delete()
|
||||
FileUtils.deleteAllInDir(file)
|
||||
} else if (file.getName().endsWith("7z")) {
|
||||
uploadFile(null, File(file.absolutePath))
|
||||
} else {
|
||||
val zipNamePath = it.absolutePath + ".7z"
|
||||
executors?.submit {
|
||||
val vehicleName = vehicleName
|
||||
val zipNamePath =
|
||||
normalLogDirPath + File.separator + AppUtils.getAppVersionCode() + "_" + vehicleName + "_" + this.currentTime + ".txt.7z"
|
||||
val zipFile = File(zipNamePath)
|
||||
if (! zipFile.exists()) {
|
||||
try {
|
||||
zipFile.createNewFile()
|
||||
compress(file, zipNamePath)
|
||||
} catch (e : IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
compress(it, zipNamePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compress(srcFile : File, desFilePath : String) {
|
||||
try {
|
||||
val out = XZCompressorOutputStream(FileOutputStream(desFilePath))
|
||||
val out = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
XZCompressorOutputStream(Files.newOutputStream(Paths.get(desFilePath)))
|
||||
} else {
|
||||
XZCompressorOutputStream(FileOutputStream(desFilePath))
|
||||
}
|
||||
addToArchiveCompression(out, srcFile, File(desFilePath))
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadFile(srcFile : File?, desFile : File) {
|
||||
val requestBody : RequestBody = desFile.asRequestBody("multipart/form-data".toMediaType())
|
||||
val part = MultipartBody.Part.createFormData("file", desFile.name, requestBody)
|
||||
|
||||
val disposable =
|
||||
LogRetrofitHelper.getDefaultService().uploadLog(part, desFile.name, "rescue-app")
|
||||
.subscribeOn(Schedulers.io()).subscribe({ it ->
|
||||
if (it.code == 200) {
|
||||
deleteLog(desFile);
|
||||
}
|
||||
if (srcFile != null) {
|
||||
deleteLog(srcFile);
|
||||
}
|
||||
}, {
|
||||
if (srcFile != null) {
|
||||
deleteLog(srcFile);
|
||||
}
|
||||
}, {})
|
||||
}
|
||||
|
||||
private fun addToArchiveCompression(sevenZOutputFile : XZCompressorOutputStream,
|
||||
srcFile : File,
|
||||
desFile : File) {
|
||||
if (srcFile.isFile) {
|
||||
if (srcFile.isFile()) {
|
||||
var inputStream : FileInputStream? = null
|
||||
try {
|
||||
inputStream = FileInputStream(srcFile)
|
||||
val b = ByteArray(2048)
|
||||
var count : Int
|
||||
while (inputStream.read(b).also { count = it } != - 1) {
|
||||
while ((inputStream.read(b).also { count = it }) != - 1) {
|
||||
sevenZOutputFile.write(b, 0, count)
|
||||
}
|
||||
sevenZOutputFile.close()
|
||||
inputStream.close()
|
||||
upload(srcFile, desFile)
|
||||
uploadFile(srcFile, desFile)
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
@ -263,42 +240,8 @@ object LogUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private fun upload(srcFile : File?, desFile : File) {
|
||||
val requestBody : RequestBody = desFile.asRequestBody("multipart/form-data".toMediaType())
|
||||
val part = MultipartBody.Part.createFormData("file", desFile.name, requestBody)
|
||||
|
||||
val disposable =
|
||||
LogRetrofitHelper.getDefaultService().uploadLog(part, desFile.name, "rescue-app")
|
||||
.subscribeOn(Schedulers.io()).subscribe({ it ->
|
||||
if (it.code == 200) {
|
||||
deleteLog(desFile)
|
||||
}
|
||||
srcFile?.let {
|
||||
deleteLog(it)
|
||||
}
|
||||
}, {}, {})
|
||||
}
|
||||
|
||||
private fun addLogHead(file : File, time : String) {
|
||||
file.appendBytes("${time}---应用版本---${AppUtils.getAppVersionName()}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---系统版本---Android${DeviceUtils.getSDKVersionName()} ${DeviceUtils.getSDKVersionCode()}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---ROM---${DeviceUtils.getManufacturer()} ${DeviceUtils.getModel()}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---build---${AppUtils.getAppVersionCode()}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---APP名称---中道救援-司机端".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---车辆名称---${GlobalData.driverInfoBean?.vehicleName}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
file.appendBytes("$time---司机名称---${GlobalData.driverInfoBean?.userName ?: GlobalData.driverInfoBean?.userName}".toByteArray())
|
||||
file.appendBytes("\n".toByteArray())
|
||||
}
|
||||
|
||||
private fun getCurrentTime() : String {
|
||||
return TimeUtils.millis2String(System.currentTimeMillis(), "yyyy/MM/dd HH:mm:ss.SSS")
|
||||
}
|
||||
private val currentTime : String?
|
||||
get() = TimeUtils.millis2String(System.currentTimeMillis(), "yyyy_MM_dd HH:mm:ss:SS")
|
||||
|
||||
class LogTask(appContext : Context, workerParams : WorkerParameters) :
|
||||
Worker(appContext, workerParams) {
|
||||
@ -307,4 +250,11 @@ object LogUtil {
|
||||
return Result.success()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,6 @@ import android.media.AudioAttributes
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.za.base.AppConfig
|
||||
import com.za.bean.request.AppNewOrderVoiceRequest
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
@ -61,18 +60,21 @@ object SpeechManager {
|
||||
|
||||
}
|
||||
|
||||
private var originVolume = 0
|
||||
private var defaultVolume = 10
|
||||
private var originVolume = defaultVolume
|
||||
private var audioManager : AudioManager? = null
|
||||
private fun setMaxAudioVolume() {
|
||||
try {
|
||||
if (! AppConfig.isRelease) {
|
||||
audioManager =
|
||||
ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java)
|
||||
|
||||
if (audioManager == null) {
|
||||
return
|
||||
}
|
||||
val audioManager =
|
||||
ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java)
|
||||
originVolume = audioManager?.getStreamVolume(AudioManager.STREAM_MUSIC) ?: 0
|
||||
originVolume = audioManager?.getStreamVolume(AudioManager.STREAM_MUSIC) ?: defaultVolume
|
||||
val maxVolume = audioManager?.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC,
|
||||
maxVolume ?: 1,
|
||||
maxVolume ?: defaultVolume,
|
||||
AudioManager.FLAG_PLAY_SOUND)
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("setMaxAudioVolume", e)
|
||||
@ -80,15 +82,12 @@ object SpeechManager {
|
||||
}
|
||||
|
||||
private fun resetAudioVolume() {
|
||||
try {
|
||||
if (! AppConfig.isRelease) {
|
||||
return
|
||||
}
|
||||
val audioManager =
|
||||
ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java)
|
||||
audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC,
|
||||
originVolume,
|
||||
AudioManager.FLAG_PLAY_SOUND)
|
||||
try { // val audioManager =
|
||||
// ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java)
|
||||
// audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC,
|
||||
// originVolume,
|
||||
// AudioManager.FLAG_PLAY_SOUND)
|
||||
LogUtil.print("resetAudioVolume", "resetAudioVolume")
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("resetAudioVolume", e)
|
||||
}
|
||||
@ -153,9 +152,7 @@ object SpeechManager {
|
||||
}
|
||||
|
||||
// 设置最大音量
|
||||
setMaxAudioVolume()
|
||||
|
||||
// 开始播放
|
||||
setMaxAudioVolume() // 开始播放
|
||||
mediaPlayer?.start()
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("playNewOrder", "播放出错: ${e.message}")
|
||||
@ -174,7 +171,7 @@ object SpeechManager {
|
||||
|
||||
mediaPlayer?.setDataSource(url)
|
||||
mediaPlayer?.setOnPreparedListener { // 设置最大音量
|
||||
setMaxAudioVolume() // 准备完成后开始播放
|
||||
// 准备完成后开始播放
|
||||
it.start()
|
||||
}
|
||||
mediaPlayer?.setOnCompletionListener { // 播放完成后释放资源
|
||||
@ -185,8 +182,7 @@ object SpeechManager {
|
||||
releaseMediaPlayer()
|
||||
true
|
||||
}
|
||||
|
||||
// 异步准备,避免阻塞UI线程
|
||||
setMaxAudioVolume() // 异步准备,避免阻塞UI线程
|
||||
mediaPlayer?.prepareAsync()
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("playNewOrderFromNet", "播放出错: ${e.message}")
|
||||
|
@ -2,11 +2,15 @@ package com.za.common.speech
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import android.os.Bundle
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.speech.tts.TextToSpeech.Engine.KEY_PARAM_VOLUME
|
||||
import android.speech.tts.UtteranceProgressListener
|
||||
import com.za.common.log.LogUtil
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object TTSManager {
|
||||
private var tts : TextToSpeech? = null
|
||||
@ -55,8 +59,13 @@ object TTSManager {
|
||||
}
|
||||
|
||||
fun speak(text : String?) {
|
||||
if (tts != null && tts?.isSpeaking == false) {
|
||||
tts?.speak(text, TextToSpeech.QUEUE_FLUSH, null, "uniqueId")
|
||||
if (tts != null && tts?.isSpeaking == false) { //设置最大音量
|
||||
val am = context?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val sb2value = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
am.setStreamVolume(AudioManager.STREAM_MUSIC, sb2value, 0)
|
||||
val bundle = Bundle()
|
||||
bundle.putFloat(KEY_PARAM_VOLUME, 1.0f)
|
||||
tts?.speak(text, TextToSpeech.QUEUE_FLUSH, bundle, "uniqueId")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,11 @@ import com.za.bean.ReportHistoryBean
|
||||
import com.za.bean.ReportHistoryRequest
|
||||
import com.za.bean.ReportInfoRequest
|
||||
import com.za.bean.ReportItem
|
||||
import com.za.bean.SaveSignatureRequest
|
||||
import com.za.bean.SettleInfoRequest
|
||||
import com.za.bean.TaskNotesBean
|
||||
import com.za.bean.TaskSettlementAndTraceBean
|
||||
import com.za.bean.UnifiedOCRWithCompressRequest
|
||||
import com.za.bean.UpdateVersionBean
|
||||
import com.za.bean.UpdateVersionRequest
|
||||
import com.za.bean.UploadChangeBatteryRequest
|
||||
@ -289,4 +291,12 @@ interface ApiService {
|
||||
|
||||
@POST("driverApp/task/getTaskNotes")
|
||||
fun getTaskNotes(@Body request : TaskNotesRequest) : Observable<BaseResponse<TaskNotesBean>>
|
||||
|
||||
@POST("driverApp/supplier/unifiedOCRWithCompress")
|
||||
fun unifiedOCRWithCompress(@Body request : UnifiedOCRWithCompressRequest) : Observable<BaseResponse<String>>
|
||||
|
||||
@POST("driverApp/v2/user/saveSignature")
|
||||
fun saveSignature(@Body request : SaveSignatureRequest) : Observable<BaseResponse<String>>
|
||||
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import com.za.base.view.warnBean
|
||||
import com.za.bean.BaseResponse
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.offline.OfflineService
|
||||
import com.za.service.location.ZdLocationManager
|
||||
import io.reactivex.rxjava3.core.Observer
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
@ -128,6 +129,7 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
|
||||
ToastUtils.showShort("登陆信息已过期,请重新登录")
|
||||
ZdLocationManager.stopContinuousLocation()
|
||||
GlobalData.clearUserCache()
|
||||
OfflineService.stop()
|
||||
ActivityUtils.startLauncherActivity()
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("handlerTokenExpired", e)
|
||||
|
@ -113,16 +113,15 @@ object CommonMethod {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private var lastFetchGenerateInfoTime : Long = 0L
|
||||
fun getGenerateInfo(vehicleId : Int? = null,
|
||||
userId : Int? = null,
|
||||
success : (DriverInfoBean) -> Unit = {},
|
||||
failed : (String?) -> Unit = {}) {
|
||||
fun getGenerateInfo(success : (DriverInfoBean) -> Unit = {}, failed : (String?) -> Unit = {}) {
|
||||
val generalInfoRequest =
|
||||
GeneralInfoRequest(vehicleId = vehicleId ?: GlobalData.driverInfoBean?.vehicleId,
|
||||
driverId = userId ?: GlobalData.driverInfoBean?.userId,
|
||||
deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity()))
|
||||
GeneralInfoRequest(vehicleId = GlobalData.vehicleId.takeIf { it != null && it != 0 }
|
||||
?: GlobalData.driverInfoBean?.vehicleId,
|
||||
driverId = GlobalData.driverId.takeIf { it != null && it != 0 }
|
||||
?: GlobalData.driverInfoBean?.userId,
|
||||
deviceId = GlobalData.deviceId
|
||||
?: DeviceUtil.getAndroidId(ActivityUtils.getTopActivity()))
|
||||
|
||||
LogUtil.print("getGenerateInfo", "request=${generalInfoRequest.toJson()}")
|
||||
RetrofitHelper.getDefaultService().generalInfo(generalInfoRequest)
|
||||
@ -130,21 +129,39 @@ object CommonMethod {
|
||||
.subscribe(object : BaseObserver<DriverInfoBean>() {
|
||||
override fun doSuccess(it : DriverInfoBean?) {
|
||||
if (it == null) {
|
||||
if (GlobalData.driverInfoBean != null) {
|
||||
success(GlobalData.driverInfoBean !!)
|
||||
} else {
|
||||
failed("获取车辆信息失败")
|
||||
}
|
||||
|
||||
LogUtil.print("getGenerateInfo", "获取车辆信息失败")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (GlobalData.driverId == null || GlobalData.driverId == 0) {
|
||||
GlobalData.driverId = it.userId
|
||||
}
|
||||
|
||||
if (GlobalData.vehicleId == null || GlobalData.vehicleId == 0) {
|
||||
GlobalData.vehicleId = it.vehicleId
|
||||
}
|
||||
|
||||
if (GlobalData.deviceId.isNullOrBlank()) {
|
||||
GlobalData.deviceId = it.deviceId
|
||||
}
|
||||
|
||||
if (GlobalData.driverInfoBean != null && (System.currentTimeMillis() - lastFetchGenerateInfoTime < 1000 * 10)) {
|
||||
LogUtil.print("getGenerateInfo",
|
||||
"获取车辆信息成功,但是时间间隔小于10秒,不更新车辆信息")
|
||||
success(it)
|
||||
return
|
||||
}
|
||||
GlobalData.driverInfoBean = it
|
||||
lastFetchGenerateInfoTime = System.currentTimeMillis()
|
||||
LogUtil.print("GlobalData.driverInfoBean",
|
||||
"${GlobalData.driverInfoBean?.toJson()}}")
|
||||
|
||||
GlobalData.driverInfoBean = it
|
||||
|
||||
|
||||
lastFetchGenerateInfoTime = System.currentTimeMillis()
|
||||
LogUtil.print("GlobalData.driverInfoBean", "${it.toJson()}}")
|
||||
success(it)
|
||||
}
|
||||
|
||||
@ -197,7 +214,7 @@ object CommonMethod {
|
||||
}
|
||||
|
||||
override fun doFailure(code : Int, msg : String?) {
|
||||
|
||||
LogUtil.print("getNewOrder", "doFailure=$msg")
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -233,92 +250,45 @@ object CommonMethod {
|
||||
?.getOfflineTaskFromTaskId(inServicingOrder.taskId ?: 0).isNullOrEmpty()
|
||||
) {
|
||||
LogUtil.print("queryOrderList", "走离线任务逻辑")
|
||||
inServicingOrder = inServicingOrder.copy(taskState = RoomHelper.db?.orderDao()
|
||||
?.getCurrentOrder()?.taskState)
|
||||
val offlineTaskState =
|
||||
RoomHelper.db?.orderDao()?.getCurrentOrder()?.taskState
|
||||
?: inServicingOrder.taskState
|
||||
inServicingOrder = inServicingOrder.copy(taskState = offlineTaskState)
|
||||
}
|
||||
|
||||
if (GlobalData.currentOrder?.serviceTypeName != inServicingOrder.serviceTypeName) {
|
||||
LogUtil.print("queryOrderList", "订单类型发生变化")
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
|
||||
|
||||
val listData = RoomHelper.db?.photoTemplateDao()
|
||||
?.queryCurrentOrderHasTaskNode(inServicingOrder.userOrderId ?: 0)
|
||||
LogUtil.print("queryOrderList", "listData=${listData.toJson()}")
|
||||
if (listData.isNullOrEmpty() || (! listData[0].serviceTypeName.isNullOrBlank() && listData[0].serviceTypeName != inServicingOrder.serviceTypeName)) {
|
||||
RoomHelper.db?.photoTemplateDao()
|
||||
?.deleteOrderPhotoTemplateFromTaskId(taskId = inServicingOrder.taskId
|
||||
?: 0)
|
||||
fetchPhotoTemplate(orderInfo = inServicingOrder,
|
||||
isNeedUpload = true,
|
||||
success = {
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
|
||||
OfflineManager.start(GlobalData.currentOrder?.taskId)
|
||||
|
||||
context?.let {
|
||||
ReportFloatingManager.startService(it)
|
||||
}
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
},
|
||||
failed = {
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
|
||||
OfflineManager.start(GlobalData.currentOrder?.taskId)
|
||||
|
||||
context?.let {
|
||||
ReportFloatingManager.startService(it)
|
||||
}
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
})
|
||||
}
|
||||
return
|
||||
fetchPhotoTemplate(orderInfo = inServicingOrder)
|
||||
LogUtil.print("queryOrderList", "照片模版为空,重新获取照片模版")
|
||||
}
|
||||
|
||||
if (GlobalData.currentOrder?.serviceTypeName != inServicingOrder.serviceTypeName) {
|
||||
LogUtil.print("queryOrderList", "订单类型发生变化")
|
||||
RoomHelper.db?.photoTemplateDao()
|
||||
?.deleteOrderPhotoTemplateFromTaskId(taskId = inServicingOrder.taskId
|
||||
?: 0)
|
||||
fetchPhotoTemplate(orderInfo = inServicingOrder,
|
||||
isNeedUpload = true,
|
||||
success = {
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
|
||||
OfflineManager.start(GlobalData.currentOrder?.taskId)
|
||||
|
||||
context?.let {
|
||||
ReportFloatingManager.startService(it)
|
||||
}
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
},
|
||||
failed = {
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
|
||||
OfflineManager.start(GlobalData.currentOrder?.taskId)
|
||||
|
||||
context?.let {
|
||||
ReportFloatingManager.startService(it)
|
||||
}
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
GlobalData.currentOrder = inServicingOrder
|
||||
it.forEach {
|
||||
if (RoomHelper.db?.orderDao()
|
||||
?.getOrderInfoFromTaskId(it.taskId ?: 0) != null
|
||||
) {
|
||||
RoomHelper.db?.orderDao()?.update(orderInfo = it)
|
||||
val task = RoomHelper.db?.orderDao()?.getOrderInfoFromTaskId(it.taskId ?: 0)
|
||||
if (task != null) {
|
||||
RoomHelper.db?.orderDao()
|
||||
?.update(orderInfo = it.copy(taskState = task.taskState))
|
||||
} else {
|
||||
RoomHelper.db?.orderDao()?.insertOrder(orderInfo = it)
|
||||
}
|
||||
}
|
||||
fetchPhotoTemplate(inServicingOrder)
|
||||
|
||||
queryElectronOrder(orderInfo = inServicingOrder)
|
||||
WaterMarkerTemplateManager.fetchWaterTemplate(inServicingOrder.taskCode ?: "",
|
||||
taskId = inServicingOrder.taskId ?: 0,
|
||||
inServicingOrder.userOrderId ?: 0)
|
||||
OfflineManager.start(GlobalData.currentOrder?.taskId)
|
||||
|
||||
context?.let {
|
||||
ReportFloatingManager.startService(it)
|
||||
}
|
||||
|
||||
success(inServicingOrder, waitServiceOrders)
|
||||
}
|
||||
|
||||
override fun doFailure(code : Int, msg : String?) {
|
||||
@ -334,7 +304,6 @@ object CommonMethod {
|
||||
}
|
||||
|
||||
fun fetchPhotoTemplate(orderInfo : OrderInfo?,
|
||||
isNeedUpload : Boolean? = false,
|
||||
success : () -> Unit = {},
|
||||
failed : (String?) -> Unit = {}) {
|
||||
val photoTemplateRequest = PhotoTemplateRequest(orderInfo?.userOrderId)
|
||||
@ -343,13 +312,6 @@ object CommonMethod {
|
||||
.subscribe(object : BaseObserver<List<PhotoTemplateInfo>>() {
|
||||
override fun doSuccess(it : List<PhotoTemplateInfo>?) {
|
||||
if (it.isNullOrEmpty()) {
|
||||
LogUtil.print("fetchPhotoTemplate",
|
||||
"模板为null ${photoTemplateRequest.toJson()}")
|
||||
failed("未找到模版")
|
||||
return
|
||||
}
|
||||
|
||||
if (isNeedUpload == false) {
|
||||
val listData = RoomHelper.db?.photoTemplateDao()
|
||||
?.queryCurrentOrderHasTaskNode(orderInfo?.userOrderId ?: 0)
|
||||
if (! listData.isNullOrEmpty()) {
|
||||
@ -358,6 +320,31 @@ object CommonMethod {
|
||||
success()
|
||||
return
|
||||
}
|
||||
|
||||
val list = LocalPhotoTemplateControl.buildPhotoTemplate(orderInfo)
|
||||
list.forEachIndexed { _, item ->
|
||||
val photoTemplateInfo = item.copy(userOrderId = orderInfo?.userOrderId,
|
||||
taskCode = orderInfo?.taskCode,
|
||||
myCustomPhotoType = Const.PhotoType.InServicing,
|
||||
advanceTime = orderInfo?.advanceTime,
|
||||
taskId = orderInfo?.taskId,
|
||||
serviceTypeName = orderInfo?.serviceTypeName,
|
||||
needWaterMarker = orderInfo?.needWaterMarker,
|
||||
needShowPhoneBrand = orderInfo?.needShowPhoneBrand,
|
||||
photoSource = 0)
|
||||
RoomHelper.db?.photoTemplateDao()?.insert(photoTemplateInfo)
|
||||
}
|
||||
LogUtil.print("queryPhotoTemplate", "使用本地模版==${listData.toJson()}")
|
||||
success()
|
||||
return
|
||||
}
|
||||
|
||||
val listData = RoomHelper.db?.photoTemplateDao()
|
||||
?.queryCurrentOrderHasTaskNode(orderInfo?.userOrderId ?: 0)
|
||||
if (! listData.isNullOrEmpty()) {
|
||||
LogUtil.print("queryPhotoTemplate", "模板已经存在==${listData.toJson()}")
|
||||
success()
|
||||
return
|
||||
}
|
||||
|
||||
it.forEachIndexed { _, item ->
|
||||
@ -365,6 +352,7 @@ object CommonMethod {
|
||||
taskCode = orderInfo?.taskCode,
|
||||
myCustomPhotoType = Const.PhotoType.InServicing,
|
||||
advanceTime = orderInfo?.advanceTime,
|
||||
serviceTypeName = orderInfo?.serviceTypeName,
|
||||
taskId = orderInfo?.taskId,
|
||||
needWaterMarker = orderInfo?.needWaterMarker,
|
||||
needShowPhoneBrand = orderInfo?.needShowPhoneBrand,
|
||||
@ -377,7 +365,30 @@ object CommonMethod {
|
||||
|
||||
override fun doFailure(code : Int, msg : String?) {
|
||||
LogUtil.print("fetchPhotoTemplate", "err==$msg")
|
||||
failed(msg)
|
||||
val listData = RoomHelper.db?.photoTemplateDao()
|
||||
?.queryCurrentOrderHasTaskNode(orderInfo?.userOrderId ?: 0)
|
||||
if (! listData.isNullOrEmpty()) {
|
||||
LogUtil.print("queryPhotoTemplate", "模板已经存在==${listData.toJson()}")
|
||||
success()
|
||||
return
|
||||
}
|
||||
|
||||
val list = LocalPhotoTemplateControl.buildPhotoTemplate(orderInfo)
|
||||
list.forEachIndexed { _, item ->
|
||||
val photoTemplateInfo = item.copy(userOrderId = orderInfo?.userOrderId,
|
||||
taskCode = orderInfo?.taskCode,
|
||||
myCustomPhotoType = Const.PhotoType.InServicing,
|
||||
advanceTime = orderInfo?.advanceTime,
|
||||
serviceTypeName = orderInfo?.serviceTypeName,
|
||||
taskId = orderInfo?.taskId,
|
||||
needWaterMarker = orderInfo?.needWaterMarker,
|
||||
needShowPhoneBrand = orderInfo?.needShowPhoneBrand,
|
||||
photoSource = 0)
|
||||
RoomHelper.db?.photoTemplateDao()?.insert(photoTemplateInfo)
|
||||
}
|
||||
LogUtil.print("queryPhotoTemplate", "使用本地模版==${listData.toJson()}")
|
||||
success()
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -406,7 +417,8 @@ object CommonMethod {
|
||||
carVin = it?.vinNo,
|
||||
serviceContent = it?.serviceTerm,
|
||||
serverAcceptCarSignPath = it?.recipientSignPath,
|
||||
serverServicePeopleSignPath = it?.waitstaffSignPath,
|
||||
serverServicePeopleSignPath = it?.waitstaffSignPath
|
||||
?: GlobalData.driverInfoBean?.signatureUrl,
|
||||
orderType = it?.serviceName)
|
||||
it?.damageFileList?.forEach { item ->
|
||||
val damagePhotoBean = EleCarDamagePhotoBean(userOrderId = it.userOrderId,
|
||||
@ -417,6 +429,7 @@ object CommonMethod {
|
||||
RoomHelper.db?.eleCarDamagePhotoDao()?.insert(damagePhotoBean)
|
||||
}
|
||||
RoomHelper.db?.eleWorkOrderDao()?.insertEleWorkOrder(temp)
|
||||
LogUtil.print("queryElectronOrder", "插入成功 ${temp.toJson()}")
|
||||
success(temp)
|
||||
}
|
||||
|
||||
|
1121
servicing/src/main/java/com/za/net/LocalPhotoTemplateControl.kt
Normal file
@ -91,7 +91,7 @@ object OfflineManager {
|
||||
}
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
fun stop() {
|
||||
uploadDispose?.dispose()
|
||||
uploadDispose = null
|
||||
isUploading = false
|
||||
|
@ -11,7 +11,7 @@ import com.za.room.db.GlobalRoom
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object RoomHelper {
|
||||
const val VERSION: Int = 41
|
||||
const val VERSION: Int = 43
|
||||
private lateinit var mContext: Context
|
||||
var db: GlobalRoom? = null
|
||||
|
||||
|
@ -16,6 +16,9 @@ interface OrderDao {
|
||||
@Query("select * from order_info where taskId =:taskId")
|
||||
fun getOrderInfoFromTaskId(taskId: Int): OrderInfo?
|
||||
|
||||
@Query("select * from order_info where taskCode =:taskCode")
|
||||
fun getOrderInfoFromTaskCode(taskCode: String): OrderInfo?
|
||||
|
||||
//获取当前正在执行的订单
|
||||
@Query("select * from order_info where isCurrent ==1")
|
||||
fun getCurrentOrder(): OrderInfo?
|
||||
|
@ -23,4 +23,5 @@ data class DriverInfoBean(
|
||||
val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌
|
||||
val plateNumber : String? = null, //车牌号
|
||||
val deviceId : String? = null,
|
||||
val signatureUrl : String? = null, //手写签名照地址
|
||||
) : Parcelable
|
@ -30,6 +30,7 @@ interface PushListener {
|
||||
fun reDispatchOrder(jpushBean : JpushBean)
|
||||
fun broadcast(string : String)
|
||||
fun importantTip(jpushBean : JpushBean)
|
||||
fun reportHandle(jpushBean : JpushBean)
|
||||
}
|
||||
|
||||
data class LastJPushBean(val msg : String, val time : Long = System.currentTimeMillis())
|
||||
@ -67,33 +68,49 @@ object ServiceManager {
|
||||
private fun setupPushMessageReceiver(context : Context) { // 注册推送消息接收器
|
||||
registerPushListener(object : PushListener {
|
||||
override fun broadcast(msg : String) {
|
||||
sendMessageToMainProcess(context = context, "broadcast", msg)
|
||||
sendMessageToMainProcess(context = context, Const.PushMessageType.BROADCAST, msg)
|
||||
}
|
||||
|
||||
override fun giveUpOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, "giveUp", Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.GIVE_UP,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun importantTip(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context,
|
||||
"importantTip",
|
||||
Const.PushMessageType.IMPORTANT_TIP,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun newOrderMsg(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, "newOrder", Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.NEW_ORDER,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun reDispatchOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, "reDispatch", Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.RE_DISPATCH,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun revokeOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, "revoke", Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.REVOKE,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun modifyOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, "modify", Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.MODIFY,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun reportHandle(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.REPORT_HANDLE,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -145,6 +162,7 @@ object ServiceManager {
|
||||
1 -> handleTypeOneMessage(jpushOrderInfoBean)
|
||||
2 -> handlerModifyOrderMessage(jpushOrderInfoBean)
|
||||
3 -> importantTip(jpushOrderInfoBean)
|
||||
4 -> reportHandler(jpushOrderInfoBean)
|
||||
else -> LogUtil.print("JpushMessage",
|
||||
"Unknown push type: ${jpushOrderInfoBean.pushType}")
|
||||
}
|
||||
@ -171,9 +189,9 @@ object ServiceManager {
|
||||
// Handle type one messages
|
||||
private fun handleTypeOneMessage(jpushOrderBean : JpushBean) {
|
||||
when (jpushOrderBean.typeDesc) {
|
||||
"giveUp" -> giveUpOrder(jpushOrderBean)
|
||||
"revoke" -> revokeOrder(jpushOrderBean)
|
||||
"reDispatch" -> reDispatchOrder(jpushOrderBean)
|
||||
Const.PushMessageType.GIVE_UP -> giveUpOrder(jpushOrderBean)
|
||||
Const.PushMessageType.REVOKE -> revokeOrder(jpushOrderBean)
|
||||
Const.PushMessageType.RE_DISPATCH -> reDispatchOrder(jpushOrderBean)
|
||||
else -> LogUtil.print("JpushMessage", "Unknown typeDesc: ${jpushOrderBean.typeDesc}")
|
||||
}
|
||||
}
|
||||
@ -218,6 +236,10 @@ object ServiceManager {
|
||||
pushListener?.importantTip(jpushOrderBean)
|
||||
}
|
||||
|
||||
private fun reportHandler(jpushOrderBean : JpushBean) {
|
||||
pushListener?.reportHandle(jpushOrderBean)
|
||||
}
|
||||
|
||||
// Disconnect from JPush and MQTT
|
||||
fun disconnect(context : Context) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
@ -259,13 +281,13 @@ object ServiceManager {
|
||||
|
||||
1 -> {
|
||||
when (jpushOrderInfoBean.typeDesc) {
|
||||
"giveUp" -> sendNotification(GlobalData.application,
|
||||
Const.PushMessageType.GIVE_UP -> sendNotification(GlobalData.application,
|
||||
"订单:${jpushOrderInfoBean.taskCode ?: ""}已被放弃!")
|
||||
|
||||
"revoke" -> sendNotification(GlobalData.application,
|
||||
Const.PushMessageType.REVOKE -> sendNotification(GlobalData.application,
|
||||
"订单:${jpushOrderInfoBean.taskCode ?: ""}已被撤回!")
|
||||
|
||||
"reDispatch" -> sendNotification(GlobalData.application,
|
||||
Const.PushMessageType.RE_DISPATCH -> sendNotification(GlobalData.application,
|
||||
"订单:${jpushOrderInfoBean.taskCode ?: ""}被改派!")
|
||||
|
||||
else -> {}
|
||||
|
@ -22,7 +22,9 @@ import com.za.bean.JpushBean
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.common.speech.SpeechManager
|
||||
import com.za.room.RoomHelper
|
||||
import com.za.servicing.R
|
||||
import com.za.ui.order_report.ReportFloatingManager
|
||||
import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
|
||||
import com.za.ui.view.CommonDialogFragment
|
||||
|
||||
@ -113,6 +115,20 @@ class ZdPushServiceReceive : BroadcastReceiver() {
|
||||
}
|
||||
}
|
||||
|
||||
Const.PushMessageType.REPORT_HANDLE -> {
|
||||
try {
|
||||
val jpushBean = Gson().fromJson(message, JpushBean::class.java)
|
||||
val activity = BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()
|
||||
?: ActivityUtils.getTopActivity()
|
||||
if (activity is AppCompatActivity) {
|
||||
handeReportMessage(jpushBean = jpushBean)
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
LogUtil.print("PushActivityLifecycleCallbacks",
|
||||
"处理重要提示消息失败: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,6 +199,24 @@ class ZdPushServiceReceive : BroadcastReceiver() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handeReportMessage(jpushBean : JpushBean) {
|
||||
SpeechManager.speech("您提交的报批已经处理!")
|
||||
BaseActivityLifecycleCallbacks.getCurrentActivity()?.let { currentActivity ->
|
||||
if (currentActivity is AppCompatActivity) {
|
||||
AlertDialog.Builder(currentActivity).setTitle("提醒")
|
||||
.setMessage("您提交的报批已经处理,是否前往查看?")
|
||||
.setPositiveButton("确定") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
currentActivity.finish()
|
||||
val order = RoomHelper.db?.orderDao()
|
||||
?.getOrderInfoFromTaskCode(taskCode = jpushBean.taskCode ?: "")
|
||||
ReportFloatingManager.goReportPage(context = currentActivity,
|
||||
orderInfo = order)
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle broadcast messages
|
||||
private fun handleBroadcast(msg : String) {
|
||||
try {
|
||||
|
@ -21,6 +21,7 @@ class ConnectionOptionWrapper(
|
||||
isCleanSession = true
|
||||
keepAliveInterval = 90 // Keep alive interval in seconds
|
||||
isAutomaticReconnect = true
|
||||
maxInflight = 1000
|
||||
mqttVersion = MqttConnectOptions.MQTT_VERSION_3_1_1
|
||||
connectionTimeout = 30 // Connection timeout in seconds
|
||||
}
|
||||
|
@ -1,68 +1,55 @@
|
||||
package com.za.service.mqtt
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.annotation.SuppressLint
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.common.util.DeviceUtil
|
||||
import com.za.common.util.Tools.macSignature
|
||||
import com.za.service.ServiceManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.paho.android.service.MqttAndroidClient
|
||||
import org.eclipse.paho.client.mqttv3.IMqttActionListener
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient
|
||||
import org.eclipse.paho.client.mqttv3.IMqttToken
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
|
||||
import org.eclipse.paho.client.mqttv3.MqttException
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
|
||||
import kotlin.concurrent.Volatile
|
||||
|
||||
|
||||
object MyMqttClient {
|
||||
private lateinit var clientId : String
|
||||
private lateinit var topic : String
|
||||
|
||||
private val mqttClient : MqttClient by lazy {
|
||||
MqttClient("tcp://${MqttConfig.END_POINT}:1883", clientId, MemoryPersistence())
|
||||
}
|
||||
|
||||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private val _connectionState = MutableStateFlow(false)
|
||||
private val connectionState : StateFlow<Boolean> = _connectionState
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private var mqttClient : MqttAndroidClient? = null
|
||||
|
||||
fun initialize(deviceId : String?) {
|
||||
clientId = "${MqttConfig.GROUP_ID}@@@$deviceId"
|
||||
topic = "${MqttConfig.TOPIC_PREFIX}/$clientId"
|
||||
mqttClient = MqttAndroidClient(GlobalData.application,
|
||||
"tcp://${MqttConfig.END_POINT}:1883",
|
||||
clientId,
|
||||
MemoryPersistence())
|
||||
setupMqttCallbacks()
|
||||
connect()
|
||||
LogUtil.print("MyMqttClient ", "initialize success")
|
||||
Log.e("MyMqttClient ", "initialize success")
|
||||
}
|
||||
|
||||
private fun setupMqttCallbacks() {
|
||||
mqttClient.setCallback(object : MqttCallbackExtended {
|
||||
override fun connectComplete(reconnect : Boolean, serverURI : String) {
|
||||
val status = if (reconnect) "Reconnected" else "Connected"
|
||||
LogUtil.print("MyMqttClient ", "$status to: $serverURI")
|
||||
_connectionState.value = true
|
||||
subscribeTopic()
|
||||
}
|
||||
mqttClient?.setCallback(object : MqttCallback {
|
||||
|
||||
override fun connectionLost(throwable : Throwable) {
|
||||
LogUtil.print("MyMqttClient ", "Connection lost: ${throwable.message}")
|
||||
_connectionState.value = false
|
||||
LogUtil.print("MyMqttClient ",
|
||||
"Connection lost: ${throwable.message}") // connect()
|
||||
}
|
||||
|
||||
override fun messageArrived(topic : String, mqttMessage : MqttMessage) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val message = String(mqttMessage.payload)
|
||||
LogUtil.print("MyMqttClient ", "Message arrived: $message")
|
||||
ServiceManager.handlerPushMsg(message)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deliveryComplete(token : IMqttDeliveryToken) {
|
||||
LogUtil.print("MyMqttClient ", "Message delivery complete")
|
||||
@ -70,64 +57,102 @@ object MyMqttClient {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@Volatile
|
||||
private var isConnecting : Boolean? = null
|
||||
private fun connect() {
|
||||
if (connectionState.value && mqttClient.isConnected) {
|
||||
LogUtil.print("MyMqttClient ", "Already connected")
|
||||
if (isConnecting == true) {
|
||||
return
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
val options = ConnectionOptionWrapper(MqttConfig.INSTANCE_ID,
|
||||
MqttConfig.ACCESS_KEY,
|
||||
clientId,
|
||||
MqttConfig.SECRET_KEY).mqttConnectOptions
|
||||
isConnecting = true
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
mqttClient.connect(options)
|
||||
val mqttConnectOption = MqttConnectOptions()
|
||||
mqttConnectOption.userName =
|
||||
"Signature|" + MqttConfig.ACCESS_KEY + "|" + MqttConfig.INSTANCE_ID
|
||||
mqttConnectOption.password = macSignature(clientId, MqttConfig.SECRET_KEY).toCharArray()
|
||||
mqttConnectOption.isCleanSession = true
|
||||
mqttConnectOption.keepAliveInterval = 90
|
||||
mqttConnectOption.isAutomaticReconnect = true
|
||||
mqttConnectOption.maxInflight = 1000
|
||||
mqttConnectOption.maxReconnectDelay = 30 * 1000
|
||||
mqttConnectOption.mqttVersion = MqttConnectOptions.MQTT_VERSION_3_1_1
|
||||
mqttConnectOption.connectionTimeout = 30
|
||||
|
||||
mqttClient?.connect(mqttConnectOption, null, object : IMqttActionListener {
|
||||
override fun onSuccess(asyncActionToken : IMqttToken?) {
|
||||
isConnecting = false
|
||||
LogUtil.print("MyMqttClient ", "connect success==")
|
||||
subscribeTopic()
|
||||
}
|
||||
_connectionState.value = true // Update connection state after successful connection
|
||||
|
||||
override fun onFailure(asyncActionToken : IMqttToken?, exception : Throwable?) {
|
||||
isConnecting = false
|
||||
LogUtil.print("MyMqttClient ", "connect failed== ${exception?.message}")
|
||||
}
|
||||
})
|
||||
} catch (e : MqttException) {
|
||||
LogUtil.print("MyMqttClient ", "Connection failed: ${e.message}")
|
||||
_connectionState.value = false // Update connection state on failure
|
||||
}
|
||||
LogUtil.print("MyMqttClient ", "Connection failed2: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//检测mqtt连接状态
|
||||
fun publishMessage() {
|
||||
if (mqttClient.isConnected) {
|
||||
|
||||
if (mqttClient == null) {
|
||||
initialize(deviceId = DeviceUtil.getAndroidId(GlobalData.application))
|
||||
return
|
||||
}
|
||||
|
||||
if (mqttClient?.isConnected == true) {
|
||||
LogUtil.print("MyMqttClient ", "mqttClient.hasConnected")
|
||||
return
|
||||
}
|
||||
|
||||
connect()
|
||||
LogUtil.print("MyMqttClient ", "mqttClient 断开重新初始化")
|
||||
ServiceManager.initialize(GlobalData.application)
|
||||
}
|
||||
|
||||
private fun subscribeTopic() {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
mqttClient.subscribe(topic, MqttConfig.QOS_LEVEL)
|
||||
if (mqttClient?.isConnected == true) {
|
||||
mqttClient?.subscribe(topic,
|
||||
MqttConfig.QOS_LEVEL,
|
||||
null,
|
||||
object : IMqttActionListener {
|
||||
override fun onSuccess(asyncActionToken : IMqttToken?) {
|
||||
LogUtil.print("MyMqttClient ", "Subscribed to topic: $topic")
|
||||
} catch (e : MqttException) {
|
||||
LogUtil.print("MyMqttClient ", "Subscribe failed: ${e.message}")
|
||||
}
|
||||
|
||||
override fun onFailure(asyncActionToken : IMqttToken?,
|
||||
exception : Throwable) {
|
||||
LogUtil.print("MyMqttClient ", "Subscribe failed: ${exception.message}")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
LogUtil.print("MyMqttClient ", "Cannot subscribe: MQTT client is not connected")
|
||||
}
|
||||
} catch (e : MqttException) {
|
||||
LogUtil.print("MyMqttClient ", "Subscribe failed2: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
fun disconnect() {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
if (connectionState.value) {
|
||||
mqttClient.disconnect()
|
||||
_connectionState.value = false
|
||||
LogUtil.print("MyMqttClient ", "Disconnected successfully")
|
||||
if (mqttClient?.isConnected == true) {
|
||||
mqttClient?.disconnect(null, object : IMqttActionListener {
|
||||
override fun onSuccess(asyncActionToken : IMqttToken?) {
|
||||
LogUtil.print("MyMqttClient ", "Disconnected")
|
||||
}
|
||||
|
||||
override fun onFailure(asyncActionToken : IMqttToken?, exception : Throwable) {
|
||||
LogUtil.print("MyMqttClient ", "Disconnect failed")
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (e : MqttException) {
|
||||
LogUtil.print("MyMqttClient ", "Disconnect failed: ${e.message}")
|
||||
} finally {
|
||||
coroutineScope.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,13 @@ import android.graphics.Color
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -23,6 +25,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.net.toUri
|
||||
import coil.compose.AsyncImage
|
||||
import com.blankj.utilcode.util.ToastUtils
|
||||
import com.tencent.smtt.sdk.WebChromeClient
|
||||
import com.tencent.smtt.sdk.WebSettings
|
||||
@ -35,6 +39,7 @@ import com.za.base.view.HeadView
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.ext.finish
|
||||
import com.za.servicing.R
|
||||
|
||||
class CommonH5Activity : BaseActivity() {
|
||||
private var webView : WebView? = null
|
||||
@ -45,7 +50,6 @@ class CommonH5Activity : BaseActivity() {
|
||||
val url = intent.getStringExtra(EXTRA_URL)
|
||||
val title = intent.getStringExtra(EXTRA_TITLE)
|
||||
val isCanBack = intent.getBooleanExtra(EXTRA_CAN_BACK, true)
|
||||
|
||||
if (url.isNullOrBlank()) {
|
||||
ToastUtils.showLong("无效的URL")
|
||||
finish()
|
||||
@ -165,7 +169,15 @@ private fun CommonH5Screen(url : String,
|
||||
|
||||
Scaffold(topBar = {
|
||||
if (title.isNotBlank()) {
|
||||
HeadView(title = title, onBack = { handleBackPress(context, webView) })
|
||||
HeadView(title = title, onBack = { handleBackPress(context, webView) }, action = {
|
||||
AsyncImage(model = R.drawable.sv_browth,
|
||||
contentDescription = "",
|
||||
modifier = Modifier.size(24.dp).clickable{
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setData(url.toUri())
|
||||
context.startActivity(intent)
|
||||
})
|
||||
})
|
||||
}
|
||||
}) { paddingValues ->
|
||||
Box(modifier = Modifier
|
||||
@ -186,6 +198,7 @@ private fun CommonH5Screen(url : String,
|
||||
webView = this
|
||||
onWebViewCreated(this)
|
||||
loadUrl(url)
|
||||
LogUtil.print("H5Activity url", url)
|
||||
}
|
||||
})
|
||||
|
||||
@ -228,6 +241,7 @@ private fun setupWebViewClients(webView : WebView,
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(p0 : WebView?, p1 : String?) : Boolean {
|
||||
LogUtil.print("H5Activity url", "$p1")
|
||||
p0?.loadUrl(p1)
|
||||
return false
|
||||
}
|
||||
|
@ -104,20 +104,34 @@ class ServicingMainActivity : BaseActivity() {
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun reportHandle(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.REPORT_HANDLE,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun newOrderMsg(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, Const.PushMessageType.NEW_ORDER, Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.NEW_ORDER,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun reDispatchOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, Const.PushMessageType.RE_DISPATCH, Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.RE_DISPATCH,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun revokeOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, Const.PushMessageType.REVOKE, Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.REVOKE,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
|
||||
override fun modifyOrder(jpushBean : JpushBean) {
|
||||
sendMessageToMainProcess(context = context, Const.PushMessageType.MODIFY, Gson().toJson(jpushBean))
|
||||
sendMessageToMainProcess(context = context,
|
||||
Const.PushMessageType.MODIFY,
|
||||
Gson().toJson(jpushBean))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -87,9 +87,7 @@ class ServicingMainVm : BaseVm<ServicingMainVm.Action, ServicingMainVm.UiState>(
|
||||
return
|
||||
}
|
||||
GlobalData.token = it.token
|
||||
CommonMethod.getGenerateInfo(vehicleId = it.vehicleId,
|
||||
userId = it.userId,
|
||||
success = { success() },
|
||||
CommonMethod.getGenerateInfo(success = { success() },
|
||||
failed = { failure(it ?: "") })
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,12 @@ import android.widget.ImageView
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.blankj.utilcode.util.ActivityUtils
|
||||
import com.blankj.utilcode.util.ServiceUtils
|
||||
import com.za.base.AppConfig
|
||||
import com.za.bean.db.order.OrderInfo
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.servicing.R
|
||||
import com.za.ui.h5.CommonH5Activity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -183,7 +187,7 @@ class ReportFloatingManager : Service() {
|
||||
|
||||
if (! isMoving && System.currentTimeMillis() - startClickTime < CLICK_THRESHOLD) {
|
||||
openMainActivity()
|
||||
} else if (isDragging) { // 只保存位置,不执行吸附
|
||||
} else if (isDragging) {
|
||||
savePosition()
|
||||
}
|
||||
|
||||
@ -195,6 +199,8 @@ class ReportFloatingManager : Service() {
|
||||
if (ActivityUtils.getTopActivity() is OrderReportActivity) {
|
||||
return
|
||||
}
|
||||
|
||||
// goReportPage(orderInfo = GlobalData.currentOrder, context = this)
|
||||
val intent = Intent(this, OrderReportActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
}
|
||||
@ -296,6 +302,13 @@ class ReportFloatingManager : Service() {
|
||||
ServiceUtils.stopService(ReportFloatingManager::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun goReportPage(orderInfo : OrderInfo?, context : Context) {
|
||||
val url =
|
||||
"${AppConfig.Resource_URL.replace("/res","")}/h5/supplier/dispatch/reportIndex?userOrderId=${orderInfo?.userOrderId}&type=2&userOrderCode=${orderInfo?.taskCode}&driverId=${GlobalData.driverInfoBean?.userId}"
|
||||
CommonH5Activity.goH5Activity(context, url, "")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -392,7 +393,11 @@ fun InServicingPhotoView(modifier : Modifier = Modifier,
|
||||
Text(text = photoTemplateInfo.imageTitle ?: "其他",
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
color = Color.Black)
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = Color.Black,
|
||||
modifier = Modifier.wrapContentWidth().takeIf { photoTemplateInfo.doHaveFilm == 1 }
|
||||
?: Modifier.fillMaxWidth(0.7f))
|
||||
Spacer(modifier = Modifier.width(5.dp))
|
||||
if (photoTemplateInfo.doHaveFilm == 1) {
|
||||
Text(text = "* 必拍",
|
||||
@ -474,10 +479,12 @@ fun InServicingPhotoViewIsCanClick(modifier : Modifier = Modifier,
|
||||
|
||||
Text(text = photoTemplateInfo.imageTitle ?: "其他",
|
||||
fontWeight = FontWeight.Medium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
fontSize = 14.sp,
|
||||
color = Color.Black)
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = Color.Black,
|
||||
modifier = Modifier.wrapContentWidth().takeIf { photoTemplateInfo.doHaveFilm == 1 }
|
||||
?: Modifier.fillMaxWidth(0.7f))
|
||||
Spacer(modifier = Modifier.width(5.dp))
|
||||
if (photoTemplateInfo.doHaveFilm == 1 && isCanClick) {
|
||||
Text(text = "* 必拍",
|
||||
@ -722,7 +729,8 @@ fun InServicingPhotoItemView(modifier : Modifier = Modifier,
|
||||
.clip(shape = RoundedCornerShape(3.dp)),
|
||||
contentScale = ContentScale.FillBounds)
|
||||
} else {
|
||||
AsyncImage(model = photoTemplateInfo.getFormatPhotoUrl(),
|
||||
AsyncImage(model = photoTemplateInfo.getFormatPhotoUrl()?.toIntOrNull()
|
||||
?: photoTemplateInfo.getFormatPhotoUrl(),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@ -746,16 +754,16 @@ fun InServicingPhotoItemView(modifier : Modifier = Modifier,
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable {
|
||||
.noDoubleClick {
|
||||
if (! isCanClick) {
|
||||
return@clickable
|
||||
return@noDoubleClick
|
||||
}
|
||||
if (photoTemplateInfo.photoLocalPath.isNullOrBlank()) {
|
||||
if (! PermissionX.isGranted(context,
|
||||
android.Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
) {
|
||||
ToastUtils.showShort("定位权限未开启!")
|
||||
return@clickable
|
||||
return@noDoubleClick
|
||||
}
|
||||
LoadingManager.showLoading()
|
||||
ZdLocationManager.getSingleLocation(isNeedAddress = true, success = {
|
||||
@ -771,7 +779,7 @@ fun InServicingPhotoItemView(modifier : Modifier = Modifier,
|
||||
LogUtil.print("上传图片定位获取失败",
|
||||
"使用全局定位,location==${GlobalData.currentLocation.toJson()}")
|
||||
})
|
||||
return@clickable
|
||||
return@noDoubleClick
|
||||
}
|
||||
showReTakePhotoDialog.value = true
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class CheckVehicleVm : IServicingVm<CheckVehicleVm.Action, CheckVehicleVm.UiStat
|
||||
LoadingManager.showLoading()
|
||||
ZdLocationManager.getSingleLocation(isNeedAddress = true, success = {
|
||||
LoadingManager.hideLoading()
|
||||
doUploadOfflineTask(it, tempPhotoList = tempPhotoList)
|
||||
}, failed = {
|
||||
LoadingManager.hideLoading()
|
||||
if (GlobalData.currentLocation != null) {
|
||||
@ -114,7 +115,6 @@ class CheckVehicleVm : IServicingVm<CheckVehicleVm.Action, CheckVehicleVm.UiStat
|
||||
address = it?.address,
|
||||
templatePhotoInfoList = tempPhotoList.toList())
|
||||
|
||||
if (! getCurrentOrderOfflineTask().isNullOrEmpty()) {
|
||||
val offlineUpdateTaskBean = OfflineUpdateTaskBean(type = taskRequest.type,
|
||||
taskId = taskRequest.taskId,
|
||||
userId = taskRequest.userId,
|
||||
@ -136,7 +136,6 @@ class CheckVehicleVm : IServicingVm<CheckVehicleVm.Action, CheckVehicleVm.UiStat
|
||||
updateState(uiState.value.copy(goNextPage = UpdateTaskBean(nextState = getCurrentOrder()?.taskState),
|
||||
orderInfo = getCurrentOrder()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTemplate() {
|
||||
getCurrentPhotoTemplate(success = {
|
||||
|
@ -39,6 +39,7 @@ import com.za.ext.finish
|
||||
import com.za.ext.navigationActivity
|
||||
import com.za.ext.noDoubleClick
|
||||
import com.za.ui.order_report.OrderReportActivity
|
||||
import com.za.ui.order_report.ReportFloatingManager
|
||||
import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@ -58,10 +59,8 @@ fun OrderDetailScreen(orderInfo : OrderInfo?) {
|
||||
Box(modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(60.dp)
|
||||
.noDoubleClick { // val url =
|
||||
// "${AppConfig.BASE_URL}/h5/supplier/dispatch/reportIndex?userOrderId=${GlobalData.currentOrder?.userOrderId}&type=2&userOrderCode=${GlobalData.currentOrder?.taskCode}&driverId=${GlobalData.driverInfoBean?.userId}"
|
||||
//
|
||||
// CommonH5Activity.goH5Activity(context, url, "")
|
||||
.noDoubleClick {
|
||||
// ReportFloatingManager.goReportPage(orderInfo = orderInfo, context = context)
|
||||
|
||||
context.navigationActivity(OrderReportActivity::class.java)
|
||||
}
|
||||
|
@ -121,7 +121,6 @@ class InOperationVm : IServicingVm<InOperationVm.Action, InOperationVm.UiState>(
|
||||
address = it?.address,
|
||||
templatePhotoInfoList = tempPhotoList.toList())
|
||||
|
||||
if (! getCurrentOrderOfflineTask().isNullOrEmpty()) {
|
||||
val offlineUpdateTaskBean = OfflineUpdateTaskBean(type = taskRequest.type,
|
||||
taskId = taskRequest.taskId,
|
||||
userId = taskRequest.userId,
|
||||
@ -140,12 +139,10 @@ class InOperationVm : IServicingVm<InOperationVm.Action, InOperationVm.UiState>(
|
||||
offlineTitle = "准备拖车",
|
||||
offlineType = 1)
|
||||
insertOfflineTask(offlineUpdateTaskBean)
|
||||
|
||||
updateOrder(getCurrentOrder()?.copy(taskState = getCurrentOrder()?.getNextStatus()))
|
||||
updateState(uiState.value.copy(goNextPage = UpdateTaskBean(nextState = getCurrentOrder()?.taskState),
|
||||
orderInfo = getCurrentOrder()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTask() {
|
||||
if (uiState.value.photoTemplateList.isNullOrEmpty()) {
|
||||
|
@ -50,7 +50,6 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.blankj.utilcode.util.FileUtils
|
||||
import com.blankj.utilcode.util.TimeUtils
|
||||
import com.blankj.utilcode.util.ToastUtils
|
||||
import com.za.base.Const
|
||||
@ -64,14 +63,12 @@ import com.za.base.view.HeadView
|
||||
import com.za.bean.db.ele.EleCarDamagePhotoBean
|
||||
import com.za.bean.db.ele.EleWorkOrderBean
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.util.AppFileManager
|
||||
import com.za.common.util.ServicingSpeechManager
|
||||
import com.za.ext.finish
|
||||
import com.za.ext.getLastSix
|
||||
import com.za.ext.goNextPage
|
||||
import com.za.servicing.R
|
||||
import com.za.ui.view.SignatureView
|
||||
import java.io.File
|
||||
import kotlin.math.ceil
|
||||
|
||||
@Preview
|
||||
@ -127,33 +124,6 @@ fun ConfirmEleScreen(vm : ConfirmEleVm = viewModel()) {
|
||||
})
|
||||
}
|
||||
|
||||
if (uiState.value.showServicePeopleSignDialog == true) {
|
||||
CommonDialog(cancelText = "取消",
|
||||
confirmText = "保存",
|
||||
title = "是否将签名保存,以后的工单中默认使用此签名",
|
||||
cancelEnable = true,
|
||||
cancel = {
|
||||
vm.dispatch(ConfirmEleVm.Action.UpdateState(uiState.value.copy(
|
||||
showServicePeopleSignDialog = false)))
|
||||
},
|
||||
dismiss = {
|
||||
vm.dispatch(ConfirmEleVm.Action.UpdateState(uiState.value.copy(
|
||||
showServicePeopleSignDialog = false)))
|
||||
},
|
||||
confirm = {
|
||||
if (uiState.value.eleWorkOrderBean?.localServicePeopleSignPath.isNullOrEmpty()) {
|
||||
ToastUtils.showShort("请先进行签名")
|
||||
vm.dispatch(ConfirmEleVm.Action.UpdateState(uiState.value.copy(
|
||||
showServicePeopleSignDialog = false)))
|
||||
return@CommonDialog
|
||||
}
|
||||
File(uiState.value.eleWorkOrderBean?.localServicePeopleSignPath ?: "").copyTo(File(
|
||||
AppFileManager.getDriverSignPath(context)), true)
|
||||
vm.dispatch(ConfirmEleVm.Action.UpdateState(uiState.value.copy(
|
||||
showServicePeopleSignDialog = false)))
|
||||
})
|
||||
}
|
||||
|
||||
if (uiState.value.showServiceSignatureUploadFailedDialog == true) {
|
||||
CommonDialog(cancelText = "取消",
|
||||
confirmText = "离线上传",
|
||||
@ -408,8 +378,8 @@ fun ConfirmEleScreen(vm : ConfirmEleVm = viewModel()) {
|
||||
}
|
||||
vm.dispatch(ConfirmEleVm.Action.UpdateAcceptSignature(it))
|
||||
},
|
||||
serverPath = uiState.value.eleWorkOrderBean?.serverAcceptCarSignPath
|
||||
?: uiState.value.eleWorkOrderBean?.localAcceptCarSignPath)
|
||||
serverPath = uiState.value.eleWorkOrderBean?.localAcceptCarSignPath
|
||||
?: uiState.value.eleWorkOrderBean?.serverAcceptCarSignPath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,15 +412,9 @@ fun ConfirmEleScreen(vm : ConfirmEleVm = viewModel()) {
|
||||
return@SignatureView
|
||||
}
|
||||
vm.dispatch(ConfirmEleVm.Action.UploadServiceSignature(it))
|
||||
|
||||
if (! FileUtils.isFileExists(File(AppFileManager.getDriverSignPath(
|
||||
context)))
|
||||
) {
|
||||
vm.updateState(uiState.value.copy(showServicePeopleSignDialog = true))
|
||||
}
|
||||
},
|
||||
serverPath = uiState.value.eleWorkOrderBean?.serverServicePeopleSignPath
|
||||
?: uiState.value.eleWorkOrderBean?.localServicePeopleSignPath)
|
||||
serverPath = uiState.value.eleWorkOrderBean?.localServicePeopleSignPath
|
||||
?: uiState.value.eleWorkOrderBean?.serverServicePeopleSignPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package com.za.ui.servicing.order_confirm
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.amap.api.location.AMapLocation
|
||||
import com.blankj.utilcode.util.ActivityUtils
|
||||
import com.blankj.utilcode.util.FileUtils
|
||||
import com.blankj.utilcode.util.NetworkUtils
|
||||
import com.blankj.utilcode.util.ToastUtils
|
||||
import com.za.base.Const
|
||||
@ -17,7 +15,6 @@ import com.za.bean.request.SaveEleOrderRequest
|
||||
import com.za.bean.request.UpdateTaskBean
|
||||
import com.za.common.GlobalData
|
||||
import com.za.common.log.LogUtil
|
||||
import com.za.common.util.AppFileManager
|
||||
import com.za.ext.toJson
|
||||
import com.za.net.BaseObserver
|
||||
import com.za.net.CommonMethod
|
||||
@ -186,7 +183,8 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
} else null,
|
||||
hasSuccess = eleWorkOrderBean.isSuccess,
|
||||
recipientSignPath = eleWorkOrderBean.serverAcceptCarSignPath,
|
||||
waitstaffSignPath = eleWorkOrderBean.serverServicePeopleSignPath,
|
||||
waitstaffSignPath = eleWorkOrderBean.serverServicePeopleSignPath
|
||||
?: GlobalData.driverInfoBean?.signatureUrl,
|
||||
eleState = 3,
|
||||
userOrderId = getCurrentOrder()?.userOrderId)
|
||||
insertOfflineTask(offlineUpdateTaskBean)
|
||||
@ -206,7 +204,8 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
} else null,
|
||||
hasSuccess = eleWorkOrderBean.isSuccess,
|
||||
recipientSignPath = eleWorkOrderBean.serverAcceptCarSignPath,
|
||||
waitstaffSignPath = eleWorkOrderBean.serverServicePeopleSignPath,
|
||||
waitstaffSignPath = eleWorkOrderBean.serverServicePeopleSignPath
|
||||
?: GlobalData.driverInfoBean?.signatureUrl,
|
||||
eleState = 3,
|
||||
userOrderId = getCurrentOrder()?.userOrderId)
|
||||
insertOfflineTask(offlineUpdateTaskBean)
|
||||
@ -223,11 +222,12 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
return
|
||||
}
|
||||
|
||||
if (getCurrentOrder()?.flowType != 2 && eleWorkOrderBean.isSuccess == null) {
|
||||
if (getCurrentOrder()?.flowType != Const.TUO_CHE && eleWorkOrderBean.isSuccess == null) {
|
||||
showTipDialog("请选择服务是否成功!")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (uiState.value.isAddSmallWheel == true && uiState.value.wheelNum == null || uiState.value.wheelNum == 0) {
|
||||
showTipDialog("请输入辅助轮个数")
|
||||
return
|
||||
@ -243,11 +243,16 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
return
|
||||
}
|
||||
|
||||
if (eleWorkOrderBean.localAcceptCarSignPath.isNullOrBlank() || eleWorkOrderBean.localServicePeopleSignPath.isNullOrBlank()) {
|
||||
if (eleWorkOrderBean.localAcceptCarSignPath.isNullOrBlank()) {
|
||||
showTipDialog("请先上传签名!")
|
||||
return
|
||||
}
|
||||
|
||||
if (eleWorkOrderBean.serverServicePeopleSignPath.isNullOrBlank() && eleWorkOrderBean.localServicePeopleSignPath.isNullOrBlank()) {
|
||||
showTipDialog("请上传服务人员签名!")
|
||||
return
|
||||
}
|
||||
|
||||
LoadingManager.showLoading()
|
||||
ZdLocationManager.getSingleLocation(success = {
|
||||
LoadingManager.hideLoading()
|
||||
@ -314,14 +319,7 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
orderInfo = getCurrentOrder()))
|
||||
|
||||
LogUtil.print("电子表单更新车辆损伤照片", "eleWorkOrderBean==${photoList.toJson()}")
|
||||
|
||||
if (! it.localServicePeopleSignPath.isNullOrBlank() || ! it.serverServicePeopleSignPath.isNullOrBlank()) {
|
||||
return@queryElectronOrder
|
||||
}
|
||||
|
||||
if (FileUtils.isFileExists(File(AppFileManager.getDriverSignPath(context = ActivityUtils.getTopActivity())))) {
|
||||
updateServiceSignature(AppFileManager.getDriverSignPath(context = ActivityUtils.getTopActivity()))
|
||||
}
|
||||
LogUtil.print("电子表单", "eleWorkOrderBean==${it.toJson()}")
|
||||
|
||||
}, failed = {
|
||||
LoadingManager.hideLoading()
|
||||
@ -354,6 +352,5 @@ class ConfirmEleVm : IServicingVm<ConfirmEleVm.Action, ConfirmEleVm.UiState>() {
|
||||
val showOfflineDialog : Boolean? = null,
|
||||
val showAcceptCarSignUploadFailedDialog : Boolean? = null,
|
||||
val showServiceSignatureUploadFailedDialog : Boolean? = null,
|
||||
val showServicePeopleSignDialog : Boolean? = null, //服务人员签名弹窗
|
||||
)
|
||||
}
|
@ -21,9 +21,12 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@ -35,7 +38,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
@ -44,6 +49,7 @@ import coil.compose.AsyncImage
|
||||
import com.blankj.utilcode.util.ConvertUtils
|
||||
import com.blankj.utilcode.util.ToastUtils
|
||||
import com.za.base.BaseActivity
|
||||
import com.za.base.theme.bgColor
|
||||
import com.za.base.theme.black65
|
||||
import com.za.base.theme.buttonBgColor
|
||||
import com.za.base.view.CommonDialog
|
||||
@ -195,6 +201,9 @@ fun VerifyOrderScreen(vm : VerifyOrderVm = viewModel()) {
|
||||
VerifyCarView(orderInfo = uiState.value.orderInfo,
|
||||
newCarVin = uiState.value.newCarVin,
|
||||
newCarVinPath = uiState.value.newCarPhotoPath,
|
||||
newCarChanged = {
|
||||
vm.updateState(uiState.value.copy(newCarVin = it))
|
||||
},
|
||||
recognize = {
|
||||
vm.dispatch(VerifyOrderVm.Action.Recognize(it))
|
||||
})
|
||||
@ -237,6 +246,7 @@ fun VerifyOrderScreen(vm : VerifyOrderVm = viewModel()) {
|
||||
private fun VerifyCarView(
|
||||
orderInfo : OrderInfo?,
|
||||
newCarVin : String? = null,
|
||||
newCarChanged : (String?) -> Unit,
|
||||
newCarVinPath : String? = null,
|
||||
recognize : (String) -> Unit,
|
||||
) {
|
||||
@ -298,10 +308,19 @@ private fun VerifyCarView(
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.Medium)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
Text(text = newCarVin ?: "",
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 16.sp,
|
||||
color = Color.Black)
|
||||
TextField(value = newCarVin ?: "",
|
||||
onValueChange = { newCarChanged(it) },
|
||||
modifier = Modifier.background(color = bgColor,
|
||||
shape = RoundedCornerShape(4.dp)),
|
||||
colors = TextFieldDefaults.colors()
|
||||
.copy(focusedContainerColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
unfocusedContainerColor = Color.Transparent),
|
||||
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Text),
|
||||
textStyle = TextStyle.Default.copy(fontSize = 16.sp,
|
||||
color = Color.Black,
|
||||
fontWeight = FontWeight.Medium))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
|
@ -5,6 +5,7 @@ import com.blankj.utilcode.util.ToastUtils
|
||||
import com.za.base.Const
|
||||
import com.za.base.IServicingVm
|
||||
import com.za.base.view.LoadingManager
|
||||
import com.za.bean.UnifiedOCRWithCompressRequest
|
||||
import com.za.bean.db.order.OrderInfo
|
||||
import com.za.bean.request.OrderPhotoOcrRecognizeRequest
|
||||
import com.za.bean.request.UpdateTaskBean
|
||||
@ -45,7 +46,7 @@ class VerifyOrderVm : IServicingVm<VerifyOrderVm.Action, VerifyOrderVm.UiState>(
|
||||
LoadingManager.showLoading()
|
||||
CommonMethod.uploadImage(file = File(localPath), success = {
|
||||
LoadingManager.hideLoading()
|
||||
if (it.isNullOrBlank() == true) {
|
||||
if (it.isNullOrBlank()) {
|
||||
return@uploadImage
|
||||
}
|
||||
doRecognize(it)
|
||||
@ -60,7 +61,8 @@ class VerifyOrderVm : IServicingVm<VerifyOrderVm.Action, VerifyOrderVm.UiState>(
|
||||
val orderPhotoOcrRecognizeRequest =
|
||||
OrderPhotoOcrRecognizeRequest(GlobalData.currentOrder?.userOrderId, 2, uploadPath)
|
||||
LogUtil.print("$tag doRecognize", "请求参数==${orderPhotoOcrRecognizeRequest.toJson()}")
|
||||
RetrofitHelper.getDefaultService().orderPhotoOcrRecognize(orderPhotoOcrRecognizeRequest)
|
||||
val unifiedOCRWithCompressRequest= UnifiedOCRWithCompressRequest(ocrType = 4, imageUrl = uploadPath)
|
||||
RetrofitHelper.getDefaultService().unifiedOCRWithCompress(unifiedOCRWithCompressRequest)
|
||||
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BaseObserver<String>() {
|
||||
override fun doSuccess(it : String?) {
|
||||
|
@ -13,12 +13,13 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowLeft
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -27,6 +28,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@ -40,7 +42,6 @@ import com.za.base.view.CommonDialog
|
||||
import com.za.bean.db.order.OrderInfo
|
||||
import com.za.common.util.MapUtil
|
||||
import com.za.ext.callPhone
|
||||
import com.za.ext.finish
|
||||
import com.za.servicing.R
|
||||
import com.za.ui.servicing.in_servicing_setting.OrderRequirementsActivity
|
||||
import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
|
||||
@ -207,23 +208,25 @@ fun InServicingHeadView(title : String,
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
CenterAlignedTopAppBar(modifier = Modifier.fillMaxWidth(),
|
||||
colors = TopAppBarDefaults.centerAlignedTopAppBarColors()
|
||||
.copy(containerColor = headBgColor, titleContentColor = Color.White),
|
||||
title = { Text(text = title, fontSize = 15.sp, fontWeight = FontWeight.Medium) },
|
||||
navigationIcon = {
|
||||
Column {
|
||||
Box(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = headBgColor)
|
||||
.padding(horizontal = 10.dp, vertical = 5.dp), contentAlignment = Alignment.Center) {
|
||||
|
||||
Row(modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
|
||||
if (isCanBack) {
|
||||
AsyncImage(model = R.drawable.sv_back,
|
||||
Icon(Icons.Default.KeyboardArrowLeft,
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clickable { onBack() }
|
||||
.padding(10.dp))
|
||||
.padding(5.dp),
|
||||
tint = Color.White)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
Box(modifier = Modifier
|
||||
.size(46.dp)
|
||||
.clickable {
|
||||
@ -236,7 +239,16 @@ fun InServicingHeadView(title : String,
|
||||
contentDescription = "",
|
||||
modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
||||
Text(text = title,
|
||||
fontSize = 16.sp,
|
||||
color = Color.White.copy(alpha = 0.95f),
|
||||
fontWeight = FontWeight.Medium,
|
||||
style = TextStyle.Default.copy())
|
||||
}
|
||||
}
|
||||
|
||||
AppTipsView()
|
||||
}
|
||||
|
12
servicing/src/main/res/drawable/sv_browth.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="128dp"
|
||||
android:height="128dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M664.9,359.1a35.2,35.2 0,0 1,8.5 36l-64,192a35.2,35.2 0,0 1,-22.3 22.3l-192,64a35.2,35.2 0,0 1,-44.5 -44.5l64,-192a35.2,35.2 0,0 1,22.3 -22.3l192,-64a35.2,35.2 0,0 1,36 8.5zM475.8,475.8L439.7,584.3l108.5,-36.2 36.2,-108.5 -108.5,36.2z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M512,819.2a307.2,307.2 0,1 0,0 -614.4,307.2 307.2,0 0,0 0,614.4zM896,512A384,384 0,1 1,128 512a384,384 0,0 1,768 0z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
BIN
servicing/src/main/res/mipmap-xhdpi/bg_car_left_back.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_car_left_front.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_car_right_back.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_car_right_front.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_dest_car_oil.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_dilemma_left_back.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_dilemma_left_front.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_dilemma_right_back.jpg
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_dilemma_right_front.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_licenses.jpg
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_water_tank_empty.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/bg_water_tank_full.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/car_and_driver.jpg
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/car_and_driver_pingan.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/car_front.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/dadian.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/dadian_device.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/dashboard_photo.jpg
Normal file
After Width: | Height: | Size: 212 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/ferry_sample.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/finish_loading.jpg
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/huantai_photo.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/huantai_success.jpg
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/invoice_sample.png
Normal file
After Width: | Height: | Size: 394 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/kunjing.jpg
Normal file
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 93 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/no_oil.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/plight_vehicle.png
Normal file
After Width: | Height: | Size: 153 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/trailer_3.jpg
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/tyre_inflate_ing.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/tyre_inflate_ing_success.jpg
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/tyre_inflate_pre.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/tyre_pre.jpg
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/vehicle_escape.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/vin_photo.jpg
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
servicing/src/main/res/mipmap-xhdpi/work_order1.png
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
servicing/src/main/res/mipmap-xxhdpi/bg_byd_dest_car_mans.jpg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
servicing/src/main/res/mipmap-xxhdpi/bg_underground.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
servicing/src/main/res/mipmap-xxhdpi/damage_photo.jpg
Normal file
After Width: | Height: | Size: 70 KiB |