From 863329d10741d21af9ab9b916021491a89f84976 Mon Sep 17 00:00:00 2001 From: songzhiling <17630035658@163.com> Date: Sun, 27 Apr 2025 17:49:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(servicing):=20=E6=B7=BB=E5=8A=A0=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E8=AF=AD=E9=9F=B3=E9=80=9A=E7=9F=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CustomerSpeechManager 对象,用于处理文本转语音功能 - 添加 AppForegroundListener 接口和 BaseActivityLifecycleCallbacks 类,用于监听应用前后台切换- 更新 BaseActivity,使其支持推送消息 - 新增 ServicePeopleConfirmActivity 活动 - 优化订单处理逻辑,过滤掉已接受的订单 - 更新版本号至 1.0.1.9.9.12 --- .../main/java/com/za/sdk/demo/MainActivity.kt | 2 +- servicing/build.gradle | 2 +- servicing/src/main/AndroidManifest.xml | 5 + .../java/com/za/base/AppForegroundListener.kt | 14 ++ .../src/main/java/com/za/base/BaseActivity.kt | 3 +- .../za/base/BaseActivityLifecycleCallbacks.kt | 95 ++++++++ .../java/com/za/base/PushMessageActivity.kt | 207 ++++++++++++++++ .../java/com/za/base/PushMessageLiveData.kt | 59 +++++ .../src/main/java/com/za/common/GlobalData.kt | 1 + .../src/main/java/com/za/common/ZDManager.kt | 2 + .../za/common/speech/CustomerSpeechManager.kt | 122 ++++++++++ .../com/za/common/speech/SpeechManager.kt | 221 ++++++++++++++++++ .../java/com/za/common/speech/TTSManager.kt | 81 +++++++ .../src/main/java/com/za/net/BaseObserver.kt | 2 +- .../src/main/java/com/za/net/CommonMethod.kt | 56 ++--- .../java/com/za/service/ServiceManager.kt | 105 ++------- .../za/service/location/ZdLocationManager.kt | 7 + .../InServicePeopleConfirmActivity.kt | 13 ++ .../InServicePeopleConfirmVm.kt | 138 +++++++++++ .../ServicePeopleConfirmScreen.kt | 165 +++++++++++++ .../wait_to_start/WaitToStartActivity.kt | 43 +--- .../servicing/wait_to_start/WaitToStartVm.kt | 61 ----- .../src/main/res/drawable/sv_face_face.xml | 25 ++ .../src/main/res/drawable/sv_face_light.xml | 54 +++++ .../src/main/res/drawable/sv_face_phone.xml | 25 ++ .../src/main/res/drawable/sv_facea_verify.xml | 220 +++++++++++++++++ servicing/src/main/res/raw/cancel_order.mp3 | Bin 0 -> 5229 bytes .../src/main/res/raw/current_order_cancel.mp3 | Bin 0 -> 5661 bytes servicing/src/main/res/raw/face_center.mp3 | Bin 0 -> 12672 bytes servicing/src/main/res/raw/face_left.mp3 | Bin 0 -> 11376 bytes servicing/src/main/res/raw/face_right.mp3 | Bin 0 -> 11232 bytes servicing/src/main/res/raw/neworder.mp3 | Bin 0 -> 23328 bytes 32 files changed, 1505 insertions(+), 223 deletions(-) create mode 100644 servicing/src/main/java/com/za/base/AppForegroundListener.kt create mode 100644 servicing/src/main/java/com/za/base/BaseActivityLifecycleCallbacks.kt create mode 100644 servicing/src/main/java/com/za/base/PushMessageActivity.kt create mode 100644 servicing/src/main/java/com/za/base/PushMessageLiveData.kt create mode 100644 servicing/src/main/java/com/za/common/speech/CustomerSpeechManager.kt create mode 100644 servicing/src/main/java/com/za/common/speech/SpeechManager.kt create mode 100644 servicing/src/main/java/com/za/common/speech/TTSManager.kt create mode 100644 servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmActivity.kt create mode 100644 servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmVm.kt create mode 100644 servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/ServicePeopleConfirmScreen.kt create mode 100644 servicing/src/main/res/drawable/sv_face_face.xml create mode 100644 servicing/src/main/res/drawable/sv_face_light.xml create mode 100644 servicing/src/main/res/drawable/sv_face_phone.xml create mode 100644 servicing/src/main/res/drawable/sv_facea_verify.xml create mode 100644 servicing/src/main/res/raw/cancel_order.mp3 create mode 100644 servicing/src/main/res/raw/current_order_cancel.mp3 create mode 100644 servicing/src/main/res/raw/face_center.mp3 create mode 100644 servicing/src/main/res/raw/face_left.mp3 create mode 100644 servicing/src/main/res/raw/face_right.mp3 create mode 100644 servicing/src/main/res/raw/neworder.mp3 diff --git a/app/src/main/java/com/za/sdk/demo/MainActivity.kt b/app/src/main/java/com/za/sdk/demo/MainActivity.kt index 1bfa70d..0c417dc 100644 --- a/app/src/main/java/com/za/sdk/demo/MainActivity.kt +++ b/app/src/main/java/com/za/sdk/demo/MainActivity.kt @@ -27,7 +27,7 @@ class MainActivity : ComponentActivity() { .fillMaxSize() .clickable { val uri = - "zd.assist://app?taskCode=ZD250425100361&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri() + "zd.assist://app?taskCode=ZD250427100009&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri() val intent = Intent(Intent.ACTION_VIEW, uri) startActivity(intent) } diff --git a/servicing/build.gradle b/servicing/build.gradle index 5f2558b..61bf4fd 100644 --- a/servicing/build.gradle +++ b/servicing/build.gradle @@ -73,7 +73,7 @@ publishing { release(MavenPublication) { groupId = 'io.github.szl9' artifactId = 'zd_servicing' - version = "1.0.1.9.9.4" + version = "1.0.1.9.9.12" pom { packaging = "aar" diff --git a/servicing/src/main/AndroidManifest.xml b/servicing/src/main/AndroidManifest.xml index ccc5ed1..bdcd282 100644 --- a/servicing/src/main/AndroidManifest.xml +++ b/servicing/src/main/AndroidManifest.xml @@ -80,6 +80,11 @@ android:networkSecurityConfig="@xml/network_security_config" android:usesCleartextTraffic="true" tools:targetApi="24"> + + // 处理推送消息 + LogUtil.print("PushMessageActivity", "Received push message: $message") + handlePushMessage(msg = message) + } + } + } + + override fun onPause() { + super.onPause() + dismissCurrentDialog() + } + + private fun handlePushMessage(msg : String) { + if (msg.startsWith("broadcast:")) { + handleBroadcast(msg) + return + } + try { + val jpushOrderInfoBean = Gson().fromJson(msg, JpushBean::class.java) + when (jpushOrderInfoBean.pushType) { + 1 -> handleTypeOneMessage(jpushOrderInfoBean) + 3 -> handleImportantTip(jpushOrderInfoBean) + else -> LogUtil.print("JpushMessage", + "Unknown push type: ${jpushOrderInfoBean.pushType}") + } + } catch (e : Exception) { + if (msg.startsWith("broadcast:")) { + handleBroadcast(msg) + } + LogUtil.print("JpushMessage", "Error handling message: ${e.message}") + } + } + + private fun handleTypeOneMessage(jpushOrderBean : JpushBean) { + when (jpushOrderBean.typeDesc) { + "giveUp" -> handleGiveUpOrder(jpushOrderBean) + "revoke" -> handleRevokeOrder() + "reDispatch" -> handleReDispatchOrder(jpushOrderBean) + else -> LogUtil.print("JpushMessage", "Unknown typeDesc: ${jpushOrderBean.typeDesc}") + } + } + + // Handle broadcast messages + private fun handleBroadcast(msg : String) { + try { + val content = msg.substring(10) + sendNotification(GlobalData.application, content) + LogUtil.print("JpushMessage", "Broadcast content: $content") + } catch (e : Exception) { + LogUtil.print("JpushMessage", "Broadcast failed: ${e.message}") + } + } + + + private fun dismissCurrentDialog() { + try { + currentDialog?.dismiss() + currentDialog = null + } catch (e : Exception) { + LogUtil.print("PushActivityLifecycleCallbacks", "关闭对话框失败: ${e.message}") + } + } + + private fun handleGiveUpOrder(jpushBean : JpushBean) { // 播放提示音 + playNotificationSound(this) + + if (GlobalData.currentOrder != null && GlobalData.currentOrder?.taskId == jpushBean.taskId) { + SpeechManager.playCurrentOrderCanceled() + CommonDialogFragment(title = "订单放弃", + message = buildGiveUpMessage(jpushBean), + confirmText = "去拍照", + cancelText = "我已了解", + confirm = { + OrderGiveUpActivity.goOrderGiveUpActivity(this, + giveUpType = GIVE_UP_TYPE_NORMAL, + taskId = jpushBean.taskId) + }).show(this.supportFragmentManager, DIALOG_TAG_GIVE_UP) + } else { + SpeechManager.playOrderCanceled() + } + } + + private fun handleRevokeOrder() { + playNotificationSound(this) + SpeechManager.speech("订单被撤回") // 获取当前Activity进行处理 + this.finish() + } + + private fun handleReDispatchOrder(jpushBean : JpushBean) { + playNotificationSound(this) + currentDialog = AlertDialog.Builder(this).setTitle("订单重新派发") + .setMessage(buildReDispatchMessage(jpushBean)).setCancelable(false) + .setPositiveButton("确定") { dialog, _ -> + dialog.dismiss() + }.show() + + } + + private fun handleImportantTip(jpushBean : JpushBean) { + playNotificationSound(this) + SpeechManager.speech("重要提醒:${jpushBean.tipContent ?: ""}") + currentDialog = + AlertDialog.Builder(this).setTitle("重要提醒").setMessage(jpushBean.tipContent) + .setNegativeButton("我已了解") { dialog : DialogInterface, _ : Int -> dialog.dismiss() } + .show() + } + + private fun buildGiveUpMessage(jpushBean : JpushBean) : String { + return buildString { + append("该工单已放弃") + jpushBean.taskCode?.let { append("\n\n订单号:$it") } + jpushBean.address?.let { append("\n地址:$it") } + append("\n\n是否需要拍放空照片?") + } + } + + private fun buildReDispatchMessage(jpushBean : JpushBean) : String { + return buildString { + append("该订单已重新派发") + jpushBean.taskCode?.let { append("\n\n订单号:$it") } + jpushBean.address?.let { append("\n地址:$it") } + jpushBean.addressRemark?.let { + if (it.isNotBlank()) { + append("\n\n备注:$it") + } + } + } + } + + private fun playNotificationSound(activity : Activity) { + try { + val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) + RingtoneManager.getRingtone(activity, notification)?.play() + } catch (e : Exception) { + LogUtil.print("PushActivityLifecycleCallbacks", "播放提示音失败: ${e.message}") + } + } + + private val CHANNEL_ID = "ImportantMessagesChannel" + private val NOTIFICATION_ID = 1003 + + // Initialize notification channel + private fun createNotificationChannel(context : Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel(CHANNEL_ID, + "订单通知", + NotificationManager.IMPORTANCE_HIGH).apply { + description = "用于接收重要消息通知" + setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), + Notification.AUDIO_ATTRIBUTES_DEFAULT) + enableVibration(true) + } + val notificationManager = + context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager + notificationManager.createNotificationChannel(channel) + } + } + + // Send notification + private fun sendNotification(context : Context, message : String) { + createNotificationChannel(context) + val notification = + NotificationCompat.Builder(context, CHANNEL_ID).setContentTitle("重要通知") + .setContentText(message).setSmallIcon(R.mipmap.ic_launcher) // 替换为你的应用图标 + .setPriority(NotificationCompat.PRIORITY_HIGH).setAutoCancel(true) // 点击后自动取消通知 + .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) + .setVibrate(longArrayOf(0, 100, 200, 300)).build() + + val notificationManager = + context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager + notificationManager.notify(NOTIFICATION_ID, notification) + } + + companion object { + internal const val GIVE_UP_TYPE_NORMAL = 1 + internal const val DIALOG_TAG_GIVE_UP = "giveUp" + } +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/base/PushMessageLiveData.kt b/servicing/src/main/java/com/za/base/PushMessageLiveData.kt new file mode 100644 index 0000000..849c8ef --- /dev/null +++ b/servicing/src/main/java/com/za/base/PushMessageLiveData.kt @@ -0,0 +1,59 @@ +package com.za.base + +import android.util.Log +import androidx.annotation.MainThread +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer +import cn.jpush.android.api.JPushMessage +import java.util.concurrent.atomic.AtomicBoolean + +object PushMessageLiveData { + // 使用 SingleLiveEvent 或类似机制避免粘性事件问题 + private val _pushMessage = SingleLiveEvent() + + // 对外暴露不可变的 LiveData + val pushMessage : LiveData = _pushMessage + + // 发送推送消息 + fun postPushMessage(message : String) { + _pushMessage.postValue(message) + } +} + +class SingleLiveEvent : MutableLiveData() { + private val pending = AtomicBoolean(false) + + @MainThread + override fun observe(owner : LifecycleOwner, observer : Observer) { + if (hasActiveObservers()) { + Log.w(TAG, "多个观察者注册了 SingleLiveEvent,但只有一个会收到更新通知") + } + + // 观察 LiveData 内部值 + super.observe(owner) { t -> + if (pending.compareAndSet(true, false)) { + observer.onChanged(t) + } + } + } + + @MainThread + override fun setValue(t : T?) { + pending.set(true) + super.setValue(t) + } + + /** + * 用于主线程外调用 + */ + override fun postValue(value : T) { + pending.set(true) + super.postValue(value) + } + + companion object { + private const val TAG = "SingleLiveEvent" + } +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/common/GlobalData.kt b/servicing/src/main/java/com/za/common/GlobalData.kt index bac37af..aeedcc1 100644 --- a/servicing/src/main/java/com/za/common/GlobalData.kt +++ b/servicing/src/main/java/com/za/common/GlobalData.kt @@ -117,6 +117,7 @@ object GlobalData : GlobalLocalData() { currentLocation = null driverInfoBean = null loginTime = null + isLoginRecognition = null } fun clearAllOrderCache() { diff --git a/servicing/src/main/java/com/za/common/ZDManager.kt b/servicing/src/main/java/com/za/common/ZDManager.kt index 6efd24e..5301d89 100644 --- a/servicing/src/main/java/com/za/common/ZDManager.kt +++ b/servicing/src/main/java/com/za/common/ZDManager.kt @@ -5,6 +5,7 @@ import com.tencent.bugly.Bugly import com.tencent.mmkv.MMKV import com.za.base.AppConfig import com.za.common.log.LogUtil +import com.za.common.speech.SpeechManager import com.za.room.RoomHelper import com.za.service.location.ZdLocationManager @@ -28,5 +29,6 @@ object ZDManager { LogUtil.init(application) RoomHelper.init(application) ZdLocationManager.init(application) + SpeechManager.init(application) } } diff --git a/servicing/src/main/java/com/za/common/speech/CustomerSpeechManager.kt b/servicing/src/main/java/com/za/common/speech/CustomerSpeechManager.kt new file mode 100644 index 0000000..1f7c715 --- /dev/null +++ b/servicing/src/main/java/com/za/common/speech/CustomerSpeechManager.kt @@ -0,0 +1,122 @@ +package com.za.common.speech + +import android.media.MediaPlayer +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.za.common.log.LogUtil +import okhttp3.OkHttpClient +import okhttp3.ResponseBody +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.Body +import retrofit2.http.POST +import java.io.File +import java.io.FileOutputStream +import java.io.IOException + +interface SpeechApiService { + @POST("v1/audio/speech") + fun textToSpeech(@Body request: JsonObject): Call +} + +object CustomerSpeechManager { + + private const val BASE_URL = "http://192.168.3.129:8880/" + + private val gson: Gson by lazy { + Gson().newBuilder() + .setLenient() + .create() + } + + private val retrofit: Retrofit by lazy { + val loggingInterceptor = HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + + val client = OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .build() + + Retrofit.Builder() + .baseUrl(BASE_URL) + .client(client) + .addConverterFactory(GsonConverterFactory.create(gson)) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .build() + } + + private val speechApiService: SpeechApiService by lazy { + retrofit.create(SpeechApiService::class.java) + } + + fun textToSpeech(input: String, destinationFile: File): Boolean { + val requestBody = JsonObject().apply { + addProperty("input", input) + addProperty("voice", "zf_xiaoxiao") + addProperty("response_format", "mp3") + addProperty("stream", true) + addProperty("speed", 1) + addProperty("return_download_link", false) // Set to false to get the stream directly + addProperty("lang_code", "z") + } + + val call = speechApiService.textToSpeech(requestBody) + try { + val response = call.execute() + LogUtil.print("CustomerSpeechManager", "response: $response") + if (response.isSuccessful) { + val responseBody = response.body() + if (responseBody != null) { + saveToFile(responseBody, destinationFile) + playAudio(destinationFile) + return true + } + } else { + LogUtil.print("CustomerSpeechManager", "Request failed: ${response.code()}") + } + } catch (e: IOException) { + e.printStackTrace() + } + return false + } + + private fun saveToFile(body: ResponseBody, destinationFile: File) { + body.byteStream().use { + FileOutputStream(destinationFile).buffered().use { outputStream -> + val buffer = ByteArray(4096) + var bytesRead: Int + while (it.read(buffer).also { bytesRead = it } != -1) { + outputStream.write(buffer, 0, bytesRead) + } + } + } + } + + private fun playAudio(file: File) { + val mediaPlayer = MediaPlayer().apply { + try { + setDataSource(file.absolutePath) + prepare() + start() + } catch (e: IOException) { + e.printStackTrace() + release() + } + } + + mediaPlayer.setOnCompletionListener { + it.release() + } + + mediaPlayer.setOnErrorListener { mp, what, extra -> + mp.release() + false + } + } +} + + diff --git a/servicing/src/main/java/com/za/common/speech/SpeechManager.kt b/servicing/src/main/java/com/za/common/speech/SpeechManager.kt new file mode 100644 index 0000000..3af5863 --- /dev/null +++ b/servicing/src/main/java/com/za/common/speech/SpeechManager.kt @@ -0,0 +1,221 @@ +package com.za.common.speech + +import android.app.Application +import android.media.AudioManager +import android.media.MediaPlayer +import androidx.core.content.ContextCompat +import com.blankj.utilcode.util.ThreadUtils +import com.za.base.AppConfig +import com.za.bean.request.AppNewOrderVoiceRequest +import com.za.common.GlobalData +import com.za.common.log.LogUtil +import com.za.net.BaseObserver +import com.za.net.RetrofitHelper +import com.za.room.RoomHelper +import com.za.room.db.user.LocalResourceBean +import com.za.servicing.R +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +object SpeechManager { + private var mContext : Application? = null + + + fun init(context : Application?) { + mContext = context //语音合成初始化| + + TTSManager.init(context, object : OnTTSListener { + override fun onTTSInitialized() { // TTS初始化成功,可以开始播放语音 + LogUtil.print("TTS", "TTS initialized successfully") + } + + override fun onTTSSuccess() { + LogUtil.print("TTS", "TTS speech completed successfully") + resetAudioVolume() + } + + override fun onTTSFailed(errorMessage : String?) { + resetAudioVolume() // TTS初始化失败或语音播放失败,使用科大讯飞进行播放 + LogUtil.print("TTS", "TTS failed: $errorMessage") + if (lastFailedText != null && ! lastFailedText.isNullOrBlank()) { + speechKDXF(lastFailedText) + lastFailedText = null + } + } + }) + } + + private var lastFailedText : String? = null + fun speech(msg : String?) { + setMaxAudioVolume() + lastFailedText = msg + TTSManager.speak(msg) + } + + private fun speechKDXF(msg : String?) { + + } + + private var originVolume = 0 + private fun setMaxAudioVolume() { + try { + if (! AppConfig.isRelease) { + return + } + val audioManager = + ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java) + val maxVolume = audioManager?.getStreamMaxVolume(AudioManager.STREAM_MUSIC) + audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC, + maxVolume ?: 1, + AudioManager.FLAG_PLAY_SOUND) + } catch (e : Exception) { + LogUtil.print("setMaxAudioVolume", e) + } + } + + 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) + } catch (e : Exception) { + LogUtil.print("resetAudioVolume", e) + } + } + + fun stopSpeech() { + TTSManager.stop() + lastFailedText = null + } + + private var mediaPlayer : MediaPlayer? = null + + // 当前订单被取消 + fun playCurrentOrderCanceled() { + mediaPlayer = MediaPlayer.create(mContext, R.raw.current_order_cancel) + mediaPlayer?.start() + } + + // 订单被取消 + fun playOrderCanceled() { + mediaPlayer = MediaPlayer.create(mContext, R.raw.cancel_order) + mediaPlayer?.start() + } + + // 面部居中 + fun playFaceCenter() { + mediaPlayer = MediaPlayer.create(mContext, R.raw.face_center) + mediaPlayer?.start() + } + + // 面部居中 + fun playFaceLeft() { + mediaPlayer = MediaPlayer.create(mContext, R.raw.face_left) + mediaPlayer?.start() + } + + // 面部居中 + fun playFaceRight() { + mediaPlayer = MediaPlayer.create(mContext, R.raw.face_right) + mediaPlayer?.start() + } + + private fun playNewOrder() { + stopPlayMedia() + setMaxAudioVolume() + mediaPlayer = MediaPlayer.create(mContext, R.raw.neworder) + mediaPlayer?.start() + mediaPlayer?.setOnCompletionListener { + resetAudioVolume() + } + } + + private fun playNewOrderFromNet(url : String) { + try { + stopPlayMedia() + setMaxAudioVolume() + mediaPlayer = MediaPlayer() + mediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC) // 设置音频流类型 + mediaPlayer?.setDataSource(url) // 设置音频文件的 URL + mediaPlayer?.prepareAsync() // 异步准备音频 + // 准备完成后开始播放 + mediaPlayer?.setOnPreparedListener { obj : MediaPlayer -> obj.start() } + mediaPlayer?.setOnErrorListener { mp : MediaPlayer?, what : Int, extra : Int -> + playNewOrder() + false + } + mediaPlayer?.setOnCompletionListener { + resetAudioVolume() + } + } catch (e : Exception) { + playNewOrder() + LogUtil.print("播放新订单失败", e) + } + } + + fun stopPlayMedia() { + ThreadUtils.runOnUiThread { + if (null != mediaPlayer) { + mediaPlayer?.stop() + mediaPlayer?.release() + mediaPlayer = null + } + } + } + + fun speechNewOrderSound(content : String?) { + if (content.isNullOrBlank()) { + speechNewOrderLooper("您有新的中道救援订单,请尽快接单!") { playNewOrder() } + return + } + + val localResourceDao = RoomHelper.db?.localResourceDao() + val localUrlResource = localResourceDao?.getLocalResourceByName(content) + if (localUrlResource != null && ! localUrlResource.resourceUrl.isNullOrBlank()) { + speechNewOrderLooper(content) { + playNewOrderFromNet(localUrlResource.resourceUrl ?: "") + } + LogUtil.print("handlerNewOrderVoice", "播放本地语音"); + return + } + + val appNewOrderVoiceRequest = AppNewOrderVoiceRequest(content) + RetrofitHelper.getDefaultService().getVoiceUrl(appNewOrderVoiceRequest) + .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BaseObserver() { + override fun doSuccess(it : String?) { + if (it == null) { + speechNewOrderLooper(content) { playNewOrder() } + return + } + localResourceDao?.insert(LocalResourceBean(resourceName = content, + resourceType = 1, + resourceUrl = it)) + speechNewOrderLooper(content) { playNewOrderFromNet(it) } + } + + override fun doFailure(code : Int, msg : String?) { + speechNewOrderLooper("您有新的中道救援订单,请尽快接单!") { playNewOrder() } + } + }) + } + + private fun speechNewOrderLooper(content : String, play : () -> Unit) { + CoroutineScope(Dispatchers.IO).launch { + val startTime = System.currentTimeMillis() + while (System.currentTimeMillis() - startTime < 1000 * 60 * 3 && GlobalData.isHandlerNewOrder == false) { + play() + delay(250L * content.length) + } + } + } +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/common/speech/TTSManager.kt b/servicing/src/main/java/com/za/common/speech/TTSManager.kt new file mode 100644 index 0000000..c0a27f5 --- /dev/null +++ b/servicing/src/main/java/com/za/common/speech/TTSManager.kt @@ -0,0 +1,81 @@ +package com.za.common.speech + +import android.annotation.SuppressLint +import android.content.Context +import android.speech.tts.TextToSpeech +import android.speech.tts.UtteranceProgressListener +import com.za.common.log.LogUtil +import java.util.Locale + +@SuppressLint("StaticFieldLeak") +object TTSManager { + private var tts: TextToSpeech? = null + private var context: Context? = null + private var listener: OnTTSListener? = null + + + fun init(context: Context?, onTTSListener: OnTTSListener) { + this.context = context + this.listener = onTTSListener + initTTS() + } + + private fun initTTS() { + tts = TextToSpeech(context) { status -> + if (status == TextToSpeech.SUCCESS) { + val result = tts?.setLanguage(Locale.getDefault()) + if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { + LogUtil.print("TTS", "Language not supported") + listener?.onTTSFailed("Language not supported") + } else { + LogUtil.print("TTS", "TTS initialized successfully") + listener?.onTTSInitialized() + } + } else { + LogUtil.print("TTS", "Initialization failed") + listener?.onTTSFailed("Initialization failed") + } + } + + tts?.setOnUtteranceProgressListener(object : UtteranceProgressListener() { + override fun onStart(utteranceId: String) { + LogUtil.print("TTS", "Speech started") + } + + override fun onDone(utteranceId: String) { + LogUtil.print("TTS", "Speech completed") + listener?.onTTSSuccess() + } + + override fun onError(utteranceId: String) { + LogUtil.print("TTS", "Speech error") + listener?.onTTSFailed("Speech error") + } + }) + } + + fun speak(text: String?) { + if (tts != null && tts?.isSpeaking == false) { + tts?.speak(text, TextToSpeech.QUEUE_FLUSH, null, "uniqueId") + } + } + + fun stop() { + tts?.takeIf { it.isSpeaking }?.stop() + } + + fun shutdown() { + tts?.apply { + stop() + shutdown() + } + tts = null + } + +} + +interface OnTTSListener { + fun onTTSInitialized() + fun onTTSSuccess() + fun onTTSFailed(errorMessage: String?) +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/net/BaseObserver.kt b/servicing/src/main/java/com/za/net/BaseObserver.kt index f216c7e..bf1ac48 100644 --- a/servicing/src/main/java/com/za/net/BaseObserver.kt +++ b/servicing/src/main/java/com/za/net/BaseObserver.kt @@ -106,8 +106,8 @@ abstract class BaseObserver : Observer> { ThreadUtils.runOnUiThread { try { ToastUtils.showShort("登陆信息已过期,请重新登录") - GlobalData.clearUserCache() ZdLocationManager.stopContinuousLocation() + GlobalData.clearUserCache() ActivityUtils.startLauncherActivity() } catch (e : Exception) { LogUtil.print("handlerTokenExpired", e) diff --git a/servicing/src/main/java/com/za/net/CommonMethod.kt b/servicing/src/main/java/com/za/net/CommonMethod.kt index 9c89c69..9b32a98 100644 --- a/servicing/src/main/java/com/za/net/CommonMethod.kt +++ b/servicing/src/main/java/com/za/net/CommonMethod.kt @@ -138,7 +138,7 @@ object CommonMethod { success(it) return } - GlobalData.driverInfoBean=it + GlobalData.driverInfoBean = it lastFetchGenerateInfoTime = System.currentTimeMillis() LogUtil.print("GlobalData.driverInfoBean", "${GlobalData.driverInfoBean?.toJson()}}") @@ -160,31 +160,34 @@ object CommonMethod { .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BaseObserver() { override fun doSuccess(order : JpushBean?) { + if (order == null) { + return + } NewOrderActivity.goNewOrderActivity(context, - jpushBean = JpushBean(taskId = order?.taskId, - taskCode = order?.taskCode, - customerName = order?.customerName, - customerPhone = order?.customerPhone, - carBrand = order?.carBrand, - carModel = order?.carModel, - carNo = order?.carNo, - taskState = order?.taskState, - address = order?.address, - addressProperty = order?.addressProperty, - hotline = order?.hotline, - expectArriveTime = order?.expectArriveTime, - serviceTypeName = order?.serviceTypeName, - dispatchTime = order?.dispatchTime, - lat = order?.lat, - lng = order?.lng, - distLat = order?.distLat, - distLng = order?.distLng, - importantTip = order?.importantTip, - hasReplaceBatteryCapable = order?.hasReplaceBatteryCapable, - distAddress = order?.distAddress, - distAddressRemark = order?.distAddressRemark, - addressRemark = order?.addressRemark, - voiceType = order?.voiceType)) + jpushBean = JpushBean(taskId = order.taskId, + taskCode = order.taskCode, + customerName = order.customerName, + customerPhone = order.customerPhone, + carBrand = order.carBrand, + carModel = order.carModel, + carNo = order.carNo, + taskState = order.taskState, + address = order.address, + addressProperty = order.addressProperty, + hotline = order.hotline, + expectArriveTime = order.expectArriveTime, + serviceTypeName = order.serviceTypeName, + dispatchTime = order.dispatchTime, + lat = order.lat, + lng = order.lng, + distLat = order.distLat, + distLng = order.distLng, + importantTip = order.importantTip, + hasReplaceBatteryCapable = order.hasReplaceBatteryCapable, + distAddress = order.distAddress, + distAddressRemark = order.distAddressRemark, + addressRemark = order.addressRemark, + voiceType = order.voiceType)) } override fun doFailure(code : Int, msg : String?) { @@ -211,7 +214,8 @@ object CommonMethod { } val inServicingOrder = it.find { it.isCurrent == true } - val waitServiceOrders = it.filter { it.isCurrent == false } + val waitServiceOrders = + it.filter { it.isCurrent == false && it.taskState != "ACCEPT" } if (inServicingOrder == null) { success(null, waitServiceOrders) diff --git a/servicing/src/main/java/com/za/service/ServiceManager.kt b/servicing/src/main/java/com/za/service/ServiceManager.kt index 4d347e4..13c1532 100644 --- a/servicing/src/main/java/com/za/service/ServiceManager.kt +++ b/servicing/src/main/java/com/za/service/ServiceManager.kt @@ -10,6 +10,7 @@ import androidx.core.app.NotificationCompat import cn.jiguang.api.utils.JCollectionAuth import cn.jpush.android.api.JPushInterface import com.google.gson.Gson +import com.za.base.PushMessageLiveData import com.za.bean.JpushBean import com.za.common.GlobalData import com.za.common.log.LogUtil @@ -17,19 +18,9 @@ import com.za.common.util.DeviceUtil import com.za.service.mqtt.MyMqttClient import com.za.servicing.R -interface PushListener { - fun newOrderMsg(jpushBean : JpushBean) - fun giveUpOrder(jpushBean : JpushBean) - fun revokeOrder(jpushBean : JpushBean) - fun reDispatchOrder(jpushBean : JpushBean) - fun broadcast(string : String) - fun importantTip(jpushBean : JpushBean) -} - data class LastJPushBean(val msg : Int, val time : Long = System.nanoTime()) object ServiceManager { - private var pushListener : PushListener? = null private var lastJPushBean : LastJPushBean? = null private const val DUPLICATE_MSG_THRESHOLD = 3000L // 3秒 @@ -53,13 +44,6 @@ object ServiceManager { } } - // Register push listener - fun registerPushListener(listener : PushListener?) { - this.pushListener = listener - LogUtil.print("ServiceManager", - "Registered push listener: ${pushListener?.javaClass?.simpleName}") - } - // Handle incoming push messages @Synchronized fun handlerPushMsg(msg : String) { @@ -75,93 +59,22 @@ object ServiceManager { if (msg.startsWith("broadcast:")) { lastJPushBean = LastJPushBean(msg = msg.hashCode()) - handleBroadcast(msg) + PushMessageLiveData.postPushMessage(msg) return } try { lastJPushBean = LastJPushBean(msg = msg.hashCode()) val jpushOrderInfoBean = Gson().fromJson(msg, JpushBean::class.java) sendSystemNotificationFromMessage(jpushOrderInfoBean) - when (jpushOrderInfoBean.pushType) { - 0 -> newOrderMsg(jpushOrderInfoBean) - 1 -> handleTypeOneMessage(jpushOrderInfoBean) - 3 -> importantTip(jpushOrderInfoBean) - else -> LogUtil.print("JpushMessage", - "Unknown push type: ${jpushOrderInfoBean.pushType}") - } + PushMessageLiveData.postPushMessage(msg) } catch (e : Exception) { if (msg.startsWith("broadcast:")) { - handleBroadcast(msg) + PushMessageLiveData.postPushMessage(msg) } LogUtil.print("JpushMessage", "Error handling message: ${e.message}") } } - // Handle broadcast messages - private fun handleBroadcast(msg : String) { - try { - val content = msg.substring(10) - pushListener?.broadcast(content) - sendNotification(GlobalData.application, content) - LogUtil.print("JpushMessage", "Broadcast content: $content") - } catch (e : Exception) { - LogUtil.print("JpushMessage", "Broadcast failed: ${e.message}") - } - } - - // Handle type one messages - private fun handleTypeOneMessage(jpushOrderBean : JpushBean) { - when (jpushOrderBean.typeDesc) { - "giveUp" -> giveUpOrder(jpushOrderBean) - "revoke" -> revokeOrder(jpushOrderBean) - "reDispatch" -> reDispatchOrder(jpushOrderBean) - else -> LogUtil.print("JpushMessage", "Unknown typeDesc: ${jpushOrderBean.typeDesc}") - } - } - - // Handle new order messages - private fun newOrderMsg(jpushOrderBean : JpushBean) { - try { - LogUtil.print("JpushMessage", - "Handling new order message: $pushListener ${pushListener?.javaClass?.simpleName}") - pushListener?.newOrderMsg(jpushOrderBean) - } catch (e : Exception) { - LogUtil.print("JpushMessage", "Failed to handle new order message: ${e.message}") - } - } - - // Handle give up order messages - private fun giveUpOrder(jpushOrderBean : JpushBean) { - pushListener?.giveUpOrder(jpushOrderBean) - } - - // Handle revoke order messages - private fun revokeOrder(jpushOrderBean : JpushBean) { - pushListener?.revokeOrder(jpushOrderBean) - } - - // Handle re-dispatch order messages - private fun reDispatchOrder(jpushOrderBean : JpushBean) { - pushListener?.reDispatchOrder(jpushOrderBean) - } - - // Handle important tip messages - private fun importantTip(jpushOrderBean : JpushBean) { - pushListener?.importantTip(jpushOrderBean) - } - - // Disconnect from JPush and MQTT - fun disconnect(context : Context) { - try { - JPushInterface.stopPush(context) // Stop JPush - MyMqttClient.disconnect() // Disconnect MQTT - LogUtil.print("ServiceManager", "Disconnected from JPush and MQTT successfully") - } catch (e : Exception) { - LogUtil.print("ServiceManager", "Error during disconnection: ${e.message}") - } - } - - private const val CHANNEL_ID = "ImportantMessagesChannel" private const val NOTIFICATION_ID = 1003 @@ -224,5 +137,15 @@ object ServiceManager { notificationManager.notify(NOTIFICATION_ID, notification) } + // Disconnect from JPush and MQTT + fun disconnect(context : Context) { + try { + JPushInterface.stopPush(context) // Stop JPush + MyMqttClient.disconnect() // Disconnect MQTT + LogUtil.print("ServiceManager", "Disconnected from JPush and MQTT successfully") + } catch (e : Exception) { + LogUtil.print("ServiceManager", "Error during disconnection: ${e.message}") + } + } } \ No newline at end of file diff --git a/servicing/src/main/java/com/za/service/location/ZdLocationManager.kt b/servicing/src/main/java/com/za/service/location/ZdLocationManager.kt index adc7136..9d63370 100644 --- a/servicing/src/main/java/com/za/service/location/ZdLocationManager.kt +++ b/servicing/src/main/java/com/za/service/location/ZdLocationManager.kt @@ -98,6 +98,9 @@ object ZdLocationManager : AMapLocationListener { fun stopContinuousLocation() { try { aMapLocationClient?.stopLocation() + aMapLocationClient?.onDestroy() + aMapLocationClient?.unRegisterLocationListener(this) + aMapLocationClient = null LogUtil.print(TAG, "关闭持续定位成功") } catch (e : Exception) { LogUtil.print(TAG, "关闭持续定位失败: ${e.message}") @@ -134,6 +137,10 @@ object ZdLocationManager : AMapLocationListener { } private fun uploadGps(uploadGpsRequest : UploadGpsRequest) { + if (GlobalData.token.isNullOrBlank()) { + LogUtil.print(TAG, "定位上传失败: token is null,request=$uploadGpsRequest") + return + } CommonMethod.uploadGps(uploadGpsRequest, success = { LogUtil.print(TAG, "定位上传成功: ${uploadGpsRequest.toJson()}") MyMqttClient.publishMessage() // if (ActivityUtils.getTopActivity()==null) { diff --git a/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmActivity.kt b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmActivity.kt new file mode 100644 index 0000000..6ba3ee4 --- /dev/null +++ b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmActivity.kt @@ -0,0 +1,13 @@ +package com.za.ui.servicing.inservice_people_confirm + +import androidx.compose.runtime.Composable +import com.za.base.BaseActivity + + +class ServicePeopleConfirmActivity : BaseActivity() { + + @Composable + override fun ContentView() { + ServicePeopleConfirmScreen() + } +} diff --git a/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmVm.kt b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmVm.kt new file mode 100644 index 0000000..9b94bc8 --- /dev/null +++ b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/InServicePeopleConfirmVm.kt @@ -0,0 +1,138 @@ +package com.za.ui.servicing.inservice_people_confirm + +import com.blankj.utilcode.util.ToastUtils +import com.za.base.IServicingVm +import com.za.base.view.LoadingManager +import com.za.bean.db.order.OrderInfo +import com.za.bean.request.DriverFaceCompareRequest +import com.za.bean.request.IaiCompareFaceBean +import com.za.bean.request.UpdateTaskBean +import com.za.bean.request.UpdateTaskRequest +import com.za.common.GlobalData +import com.za.common.log.LogUtil +import com.za.ext.toJson +import com.za.net.BaseObserver +import com.za.net.CommonMethod +import com.za.net.RetrofitHelper +import com.za.service.location.ZdLocationManager +import com.za.ui.servicing.inservice_people_confirm.InServicePeopleConfirmVm.Action +import com.za.ui.servicing.inservice_people_confirm.InServicePeopleConfirmVm.Action.CompilePeople +import com.za.ui.servicing.inservice_people_confirm.InServicePeopleConfirmVm.UiState +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import java.io.File + +class InServicePeopleConfirmVm : IServicingVm() { + private val _uiState = MutableStateFlow(UiState()) + val uiState get() = _uiState as StateFlow + override fun updateState(uiState : UiState) { + _uiState.value = uiState + } + + override fun dispatch(action : Action) { + when (action) { + is Action.Init -> init() + is Action.UpdateTask -> updateTask() + is CompilePeople -> comparePeople(action.url) + + } + } + + + private fun updateTask() { + LoadingManager.showLoading() + ZdLocationManager.getSingleLocation(success = { + LoadingManager.hideLoading() + val taskRequest = UpdateTaskRequest(type = "START", + taskId = getCurrentOrder()?.taskId, + userId = GlobalData.driverInfoBean?.userId, + vehicleId = GlobalData.driverInfoBean?.vehicleId, + currentState = getCurrentOrder()?.taskState, + offlineMode = 0, + operateTime = System.currentTimeMillis().toString(), + lat = it.latitude, + lng = it.longitude) + doUploadTask(request = taskRequest) + }, failed = { + LoadingManager.hideLoading() + ToastUtils.showShort(it) + }) + } + + private fun doUploadTask(request : UpdateTaskRequest) { + LoadingManager.showLoading() + CommonMethod.updateTask(request, success = { data -> + LoadingManager.hideLoading() + updateOrder(getCurrentOrder()?.copy(taskState = data?.nextState)) + updateState(uiState.value.copy(goNextPage = data, orderInfo = getCurrentOrder())) + }, failed = { msg, _ -> + LoadingManager.hideLoading() + ToastUtils.showShort(msg) + LogUtil.print("$tag doUploadTask", "状态更新失败==${request.toJson()} msg==$msg") + }) + } + + + private fun comparePeople(url : String?) { + if (url.isNullOrBlank()) { + ToastUtils.showLong("图片路径为空!") + return + } + LoadingManager.showLoading() + CommonMethod.uploadImage(file = File(url), success = { it -> + LoadingManager.hideLoading() + doComparePeople(it) + }, failed = { + LoadingManager.hideLoading() + updateState(uiState.value.copy(showCompareFailedDialog = "$it", compareResult = false)) + }) + } + + private fun doComparePeople(url : String?) { + val driverFaceCompareRequest = + DriverFaceCompareRequest(vehicleId = GlobalData.driverInfoBean?.vehicleId, + driverId = GlobalData.driverInfoBean?.userId, + photoUrl = url) + LoadingManager.showLoading() + RetrofitHelper.getDefaultService().iaiCompareFace(driverFaceCompareRequest) + .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BaseObserver() { + override fun doSuccess(it : IaiCompareFaceBean?) { + LoadingManager.hideLoading() + if (it?.compareResult == true) { + updateState(uiState.value.copy(compareResult = true)) + LogUtil.print("face", "人脸对比成功:$it") + return + } + updateState(uiState.value.copy(showCompareFailedDialog = "人脸对比失败", + compareResult = false)) + } + + override fun doFailure(code : Int, msg : String?) { + LoadingManager.hideLoading() + updateState(uiState.value.copy(showCompareFailedDialog = "$msg", + compareResult = false)) + LogUtil.print("face", "人脸对比失败:$msg") + } + }) + } + + private fun init() { + + } + + sealed class Action { + object Init : Action() + data class CompilePeople(val url : String? = null) : Action() + object UpdateTask : Action() + } + + data class UiState( + val orderInfo : OrderInfo? = null, + val goNextPage : UpdateTaskBean? = null, + val compareResult : Boolean? = null, + val showCompareFailedDialog : String? = null, + ) +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/ServicePeopleConfirmScreen.kt b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/ServicePeopleConfirmScreen.kt new file mode 100644 index 0000000..552ef24 --- /dev/null +++ b/servicing/src/main/java/com/za/ui/servicing/inservice_people_confirm/ServicePeopleConfirmScreen.kt @@ -0,0 +1,165 @@ +package com.za.ui.servicing.inservice_people_confirm + +import android.app.Activity +import android.content.Intent +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +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.foundation.layout.width +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +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.font.FontWeight +import androidx.compose.ui.unit.dp +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.ToastUtils +import com.za.base.view.CommonButton +import com.za.base.view.CommonDialog +import com.za.base.view.HeadView +import com.za.common.GlobalData +import com.za.common.log.LogUtil +import com.za.ext.goNextPage +import com.za.servicing.R +import com.za.ui.camera.ZdCameraXActivity + +@Composable +fun ServicePeopleConfirmScreen(vm : InServicePeopleConfirmVm = viewModel(), + success : () -> Unit = {}) { + val context = LocalContext.current + val uiState = vm.uiState.collectAsStateWithLifecycle() + val getResult = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { it -> + if (it.resultCode == Activity.RESULT_OK) { + val value = it.data?.getStringExtra("path") + LogUtil.print("takePhoto", "path==$value") + if (value.isNullOrBlank()) { + ToastUtils.showLong("照片路径为空,请重新拍摄!") + return@rememberLauncherForActivityResult + } + vm.dispatch(InServicePeopleConfirmVm.Action.CompilePeople(value)) + } + } + + if (uiState.value.compareResult == true) { + vm.updateState(uiState.value.copy(compareResult = null)) + if (GlobalData.isMaster) { + success() + } else { + vm.dispatch(InServicePeopleConfirmVm.Action.UpdateTask) + } + } + + if (uiState.value.goNextPage != null) { + goNextPage(uiState.value.goNextPage?.nextState, context) + vm.updateState(uiState.value.copy(goNextPage = null, compareResult = null)) + } + + + if (! uiState.value.showCompareFailedDialog.isNullOrBlank()) { + CommonDialog(title = uiState.value.showCompareFailedDialog, + confirmText = "重新认证", + confirm = { + vm.updateState(uiState.value.copy(showCompareFailedDialog = null)) + val intent = Intent(context, ZdCameraXActivity::class.java) + intent.putExtra("isBack", false) + getResult.launch(intent) + }, + cancelText = "关闭", + cancel = { + vm.updateState(uiState.value.copy(showCompareFailedDialog = null)) + }, + dismiss = { + vm.updateState(uiState.value.copy(showCompareFailedDialog = null)) + }) + } + + Scaffold(topBar = { HeadView(title = "身份验证") }) { + Column(modifier = Modifier + .fillMaxSize() + .background(color = Color.White) + .padding(it), + horizontalAlignment = Alignment.CenterHorizontally) { + Spacer(modifier = Modifier.height(60.dp)) + + Box { + Text(text = "为了确保服务技师信息的准确", + fontWeight = FontWeight.SemiBold, + color = Color.DarkGray, + fontSize = 18.sp) + } + + Spacer(modifier = Modifier.height(10.dp)) + + Box { + Text(text = "需要进行人脸核验", + color = Color.Gray, + fontWeight = FontWeight.Normal, + fontSize = 14.sp) + } + + Spacer(modifier = Modifier.height(30.dp)) + + + AsyncImage(model = R.drawable.sv_facea_verify, + contentDescription = "", + modifier = Modifier + .background(color = Color.White) + .padding(30.dp)) + + Spacer(modifier = Modifier.height(30.dp)) + + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center) { + AsyncImage(model = R.drawable.sv_face_light, + contentDescription = "", + modifier = Modifier.size(20.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "保持光线充足", fontSize = 10.sp, color = Color.Gray) + } + Spacer(modifier = Modifier.width(30.dp)) + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center) { + AsyncImage(model = R.drawable.sv_face_phone, + contentDescription = "", + modifier = Modifier.size(20.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "需正对手机", fontSize = 10.sp, color = Color.Gray) + } + Spacer(modifier = Modifier.width(30.dp)) + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center) { + AsyncImage(model = R.drawable.sv_face_face, + contentDescription = "", + modifier = Modifier.size(20.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "确保面部无遮挡", fontSize = 10.sp, color = Color.Gray) + } + } + + Spacer(modifier = Modifier.height(60.dp)) + CommonButton(text = "开始核验", onClick = { + val intent = Intent(context, ZdCameraXActivity::class.java) + intent.putExtra("isBack", false) + getResult.launch(intent) + }) + } + } +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt index 109bf42..203205a 100644 --- a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt +++ b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt @@ -1,12 +1,8 @@ package com.za.ui.servicing.wait_to_start -import android.app.Activity -import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.Looper -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -63,14 +59,14 @@ import com.za.base.BaseActivity import com.za.base.theme.headBgColor import com.za.base.view.CommonDialog import com.za.common.GlobalData -import com.za.common.log.LogUtil import com.za.common.util.ImageUtil import com.za.common.util.ServicingSpeechManager import com.za.ext.copy import com.za.ext.finish import com.za.ext.goNextPage +import com.za.ext.navigationActivity import com.za.servicing.R -import com.za.ui.camera.ZdCameraXActivity +import com.za.ui.servicing.inservice_people_confirm.ServicePeopleConfirmActivity import com.za.ui.servicing.view.InServicingHeadView @@ -89,19 +85,6 @@ fun WaitToStartScreen(vm : WaitToStartVm = viewModel()) { val lifecycleOwner = LocalLifecycleOwner.current val mapView = remember { MapView(context) } - val getResult = - rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { it -> - if (it.resultCode == Activity.RESULT_OK) { - val value = it.data?.getStringExtra("path") - LogUtil.print("takePhoto", "path==$value") - if (value.isNullOrBlank()) { - vm.updateState(uiState.value.copy(comparableFailedStr = "照片路径为空,请重新认证!")) - return@rememberLauncherForActivityResult - } - vm.dispatch(WaitToStartVm.Action.CompareServicePeople(value)) - } - } - // 添加 BottomSheet 状态 val bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.Expanded) val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) @@ -166,27 +149,7 @@ fun WaitToStartScreen(vm : WaitToStartVm = viewModel()) { confirm = { vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy( showServicePeopleConfirmDialog = false))) - val intent = Intent(context, ZdCameraXActivity::class.java) - intent.putExtra("isBack", false) - getResult.launch(intent) - }) - } - - if (! uiState.value.comparableFailedStr.isNullOrBlank()) { - CommonDialog(title = uiState.value.comparableFailedStr, - confirmText = "重新核验", - confirm = { - vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(comparableFailedStr = null))) - val intent = Intent(context, ZdCameraXActivity::class.java) - intent.putExtra("isBack", false) - getResult.launch(intent) - }, - cancelText = "关闭", - cancel = { - vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(comparableFailedStr = null))) - }, - dismiss = { - vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(comparableFailedStr = null))) + context.navigationActivity(ServicePeopleConfirmActivity::class.java, true) }) } diff --git a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt index 9049d2c..bc046a5 100644 --- a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt +++ b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt @@ -1,6 +1,5 @@ package com.za.ui.servicing.wait_to_start -import androidx.lifecycle.viewModelScope import com.amap.api.maps.AMapUtils import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng @@ -15,27 +14,16 @@ import com.blankj.utilcode.util.ToastUtils import com.za.base.IServicingVm import com.za.base.view.LoadingManager import com.za.bean.db.order.OrderInfo -import com.za.bean.request.DriverFaceCompareRequest -import com.za.bean.request.IaiCompareFaceBean import com.za.bean.request.UpdateTaskBean import com.za.bean.request.UpdateTaskRequest import com.za.common.GlobalData import com.za.common.log.LogUtil import com.za.ext.toJson -import com.za.net.BaseObserver import com.za.net.CommonMethod -import com.za.net.RetrofitHelper import com.za.service.location.ZdLocationManager import com.za.servicing.R -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.schedulers.Schedulers import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import java.io.File import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date @@ -55,7 +43,6 @@ class WaitToStartVm : IServicingVm( is Action.UpdateState -> updateState(action.uiState) is Action.StartTimer -> startTimer() is Action.UpdateTimer -> updateTimer() - is Action.CompareServicePeople -> compareServicePeople(action.localPath) } } @@ -231,52 +218,6 @@ class WaitToStartVm : IServicingVm( private fun updateTimer() { // 在这里处理倒计时更新逻辑 } - private fun compareServicePeople(localPath : String) { - LoadingManager.showLoading() - CommonMethod.uploadImage(file = File(localPath), success = { it -> - compilePeople(it, success = { - LoadingManager.hideLoading() - updateTask() - }, failed = { - LoadingManager.hideLoading() - updateState(uiState.value.copy(comparableFailedStr = it)) - }) - }, failed = { - LoadingManager.hideLoading() - updateState(uiState.value.copy(comparableFailedStr = it)) - }) - } - - private fun compilePeople(url : String?, - success : (IaiCompareFaceBean?) -> Unit, - failed : (String) -> Unit) { - if (url.isNullOrBlank()) { - ToastUtils.showLong("图片路径为空!") - return - } - val driverFaceCompareRequest = - DriverFaceCompareRequest(vehicleId = GlobalData.driverInfoBean?.vehicleId, - driverId = GlobalData.driverInfoBean?.userId, - photoUrl = url) - RetrofitHelper.getDefaultService().iaiCompareFace(driverFaceCompareRequest) - .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : BaseObserver() { - override fun doSuccess(it : IaiCompareFaceBean?) { - if (it?.compareResult == true) { - success(it) - return - } - failed("人脸对比失败") - LogUtil.print("face", "人脸对比成功:$it") - } - - override fun doFailure(code : Int, msg : String?) { - failed(msg ?: "人脸对比失败") - LogUtil.print("face", "人脸对比失败:$msg") - } - }) - } - override fun onCleared() { super.onCleared() timerJob?.cancel() @@ -288,7 +229,6 @@ class WaitToStartVm : IServicingVm( data class UpdateState(val uiState : UiState) : Action() data object StartTimer : Action() data object UpdateTimer : Action() - data class CompareServicePeople(val localPath : String) : Action() } data class UiState(val orderInfo : OrderInfo? = null, @@ -299,6 +239,5 @@ class WaitToStartVm : IServicingVm( val routePoints : List? = null, val remainingDistance : Float = 0f, val showServicePeopleConfirmDialog : Boolean? = false, - val comparableFailedStr : String? = null, val estimatedArrivalTime : String = "") } \ No newline at end of file diff --git a/servicing/src/main/res/drawable/sv_face_face.xml b/servicing/src/main/res/drawable/sv_face_face.xml new file mode 100644 index 0000000..b36639e --- /dev/null +++ b/servicing/src/main/res/drawable/sv_face_face.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/servicing/src/main/res/drawable/sv_face_light.xml b/servicing/src/main/res/drawable/sv_face_light.xml new file mode 100644 index 0000000..326c052 --- /dev/null +++ b/servicing/src/main/res/drawable/sv_face_light.xml @@ -0,0 +1,54 @@ + + + + + + + + + diff --git a/servicing/src/main/res/drawable/sv_face_phone.xml b/servicing/src/main/res/drawable/sv_face_phone.xml new file mode 100644 index 0000000..13c3b0d --- /dev/null +++ b/servicing/src/main/res/drawable/sv_face_phone.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/servicing/src/main/res/drawable/sv_facea_verify.xml b/servicing/src/main/res/drawable/sv_facea_verify.xml new file mode 100644 index 0000000..b0d5729 --- /dev/null +++ b/servicing/src/main/res/drawable/sv_facea_verify.xml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicing/src/main/res/raw/cancel_order.mp3 b/servicing/src/main/res/raw/cancel_order.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0d5b623c34a4d159eae2a7bae221d5eb7bb26f88 GIT binary patch literal 5229 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 literal 0 HcmV?d00001 diff --git a/servicing/src/main/res/raw/current_order_cancel.mp3 b/servicing/src/main/res/raw/current_order_cancel.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1f1d398d9d25d5c2aadfe6c0e639456d7547c446 GIT binary patch literal 5661 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≥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 literal 0 HcmV?d00001 diff --git a/servicing/src/main/res/raw/face_left.mp3 b/servicing/src/main/res/raw/face_left.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..3ce663aed7af707fb9b297cbe557d9af704c80c8 GIT binary patch literal 11376 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 BHN5}; literal 0 HcmV?d00001 diff --git a/servicing/src/main/res/raw/face_right.mp3 b/servicing/src/main/res/raw/face_right.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..caa1f40fc778c26b5fd72403d921995d371f31a7 GIT binary patch literal 11232 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 Avj6}9 literal 0 HcmV?d00001 diff --git a/servicing/src/main/res/raw/neworder.mp3 b/servicing/src/main/res/raw/neworder.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..789c23bbe778942beebeb2ad5d92ec318c3963c4 GIT binary patch literal 23328 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 literal 0 HcmV?d00001