From 22b0f14236fab0702233e8258de070fe402a6b61 Mon Sep 17 00:00:00 2001
From: songzhiling <17630035658@163.com>
Date: Tue, 29 Apr 2025 17:37:46 +0800
Subject: [PATCH] =?UTF-8?q?refactor(servicing):=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E6=8E=A8=E9=80=81=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86=E6=9C=BA?=
=?UTF-8?q?=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 ZdPushServiceReceive 类用于集中处理推送消息
- 优化了消息处理逻辑,提高了代码的可维护性和可扩展性
-改进了消息在主进程中的广播发送方式
- 优化了语音播放逻辑,提高了播放的稳定性和流畅性
- 调整了通知渠道的创建和通知的发送方式
---
.idea/deploymentTargetSelector.xml | 8 +
.../main/java/com/za/sdk/demo/MainActivity.kt | 2 +-
servicing/build.gradle | 2 +-
servicing/src/main/AndroidManifest.xml | 8 +
.../java/com/za/base/PushMessageActivity.kt | 260 +++---------------
.../src/main/java/com/za/common/GlobalData.kt | 7 +-
.../com/za/common/speech/SpeechManager.kt | 145 +++++++---
.../java/com/za/service/ServiceManager.kt | 14 +-
.../com/za/service/ZdPushServiceReceive.kt | 237 ++++++++++++++++
.../service/mqtt/ConnectionOptionWrapper.kt | 2 +-
.../com/za/ui/main/ServicingMainActivity.kt | 47 ++++
.../modify_money/ModifyMoneyViewModel.kt | 2 +-
12 files changed, 453 insertions(+), 281 deletions(-)
create mode 100644 servicing/src/main/java/com/za/service/ZdPushServiceReceive.kt
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index b268ef3..f8dae00 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,6 +4,14 @@
+
+
+
+
+
+
+
+
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 0c417dc..9389713 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=ZD250427100009&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri()
+ "zd.assist://app?taskCode=ZD250429100095&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 99fe723..3e3a581 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.25"
+ version = "1.0.1.9.9.31"
pom {
packaging = "aar"
diff --git a/servicing/src/main/AndroidManifest.xml b/servicing/src/main/AndroidManifest.xml
index bdcd282..a0f1d51 100644
--- a/servicing/src/main/AndroidManifest.xml
+++ b/servicing/src/main/AndroidManifest.xml
@@ -256,6 +256,14 @@
+
+
+
+
+
+
handleBroadcast("broadcast:$message")
- "giveUp" -> {
- try {
- val jpushBean = Gson().fromJson(message, JpushBean::class.java)
- val activity =
- getCurrentActivity() ?: ActivityUtils.getTopActivity()
- if (activity is AppCompatActivity) {
- handleGiveUpOrder(activity, jpushBean)
- }
- } catch (e : Exception) {
- LogUtil.print("PushActivityLifecycleCallbacks",
- "处理订单放弃消息失败: ${e.message}")
- }
- }
-
- "importantTip" -> {
- try {
- val jpushBean = Gson().fromJson(message, JpushBean::class.java)
- val activity =
- getCurrentActivity() ?: ActivityUtils.getTopActivity()
- if (activity is AppCompatActivity) {
- handleImportantTip(activity, jpushBean)
- }
- } catch (e : Exception) {
- LogUtil.print("PushActivityLifecycleCallbacks",
- "处理重要提示消息失败: ${e.message}")
- }
- }
-
- "reDispatch" -> {
- try {
- val jpushBean = Gson().fromJson(message, JpushBean::class.java)
- val activity =
- getCurrentActivity() ?: ActivityUtils.getTopActivity()
- if (activity is AppCompatActivity) {
- handleReDispatchOrder(activity, jpushBean)
- }
- } catch (e : Exception) {
- LogUtil.print("PushActivityLifecycleCallbacks",
- "处理订单重新派发消息失败: ${e.message}")
- }
- }
-
- "revoke" -> {
- try {
- handleRevokeOrder()
- } catch (e : Exception) {
- LogUtil.print("PushActivityLifecycleCallbacks",
- "处理订单撤回消息失败: ${e.message}")
- }
- }
- }
- }
+ private fun setupPushMessageReceiver() { // 注册推送消息接收器
+ ServiceManager.registerPushListener(object : PushListener {
+ override fun broadcast(msg : String) {
+ sendMessageToMainProcess("broadcast", msg)
}
- }
- ContextCompat.registerReceiver(context,
- pushMessageReceiver,
- IntentFilter("com.za.rescue.dealer.PUSH_MESSAGE"),
- ContextCompat.RECEIVER_NOT_EXPORTED)
- LogUtil.print("PushActivityLifecycleCallbacks", "注册推送消息接收器")
- }
-
- override fun onDestroy() {
- super.onDestroy()
- if (isLastActivity()) {
- try {
- this.unregisterReceiver(pushMessageReceiver)
- pushMessageReceiver = null
- LogUtil.print("PushActivityLifecycleCallbacks", "注销推送消息接收器")
- } catch (e : Exception) {
- LogUtil.print("PushActivityLifecycleCallbacks",
- "注销推送消息接收器失败: ${e.message}")
+ override fun giveUpOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("giveUp", Gson().toJson(jpushBean))
}
- }
+
+ override fun importantTip(jpushBean : JpushBean) {
+ sendMessageToMainProcess("importantTip", Gson().toJson(jpushBean))
+ }
+
+ override fun newOrderMsg(jpushBean : JpushBean) {
+ sendMessageToMainProcess("newOrder", Gson().toJson(jpushBean))
+ }
+
+ override fun reDispatchOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("reDispatch", Gson().toJson(jpushBean))
+ }
+
+ override fun revokeOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("revoke", Gson().toJson(jpushBean))
+ }
+ })
}
- private fun isLastActivity() : Boolean { // 检查是否是最后一个活动的Activity
- return ActivityUtils.getActivityList().size <= 1
+ private fun sendMessageToMainProcess(type : String, message : String) { // 使用广播将消息发送到主进程
+ val intent = Intent(ZdPushServiceReceive.RECEIVE_ACTION).setPackage(packageName)
+ intent.putExtra("type", type)
+ intent.putExtra("message", message)
+ sendBroadcast(intent)
+ LogUtil.print("KeepAliveService", "发送消息到主进程: $type")
}
override fun onPause() {
@@ -132,18 +60,6 @@ open class PushMessageActivity : AppCompatActivity() {
dismissCurrentDialog()
}
- // 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()
@@ -153,116 +69,6 @@ open class PushMessageActivity : AppCompatActivity() {
}
}
- private fun handleGiveUpOrder(activity : AppCompatActivity,
- 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(activity : AppCompatActivity, jpushBean : JpushBean) {
- playNotificationSound(this)
- currentDialog = AlertDialog.Builder(this).setTitle("订单重新派发")
- .setMessage(buildReDispatchMessage(jpushBean)).setCancelable(false)
- .setPositiveButton("确定") { dialog, _ ->
- dialog.dismiss()
- }.show()
- }
-
- private fun handleImportantTip(activity : AppCompatActivity, 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"
diff --git a/servicing/src/main/java/com/za/common/GlobalData.kt b/servicing/src/main/java/com/za/common/GlobalData.kt
index b9e7d76..fe5ed19 100644
--- a/servicing/src/main/java/com/za/common/GlobalData.kt
+++ b/servicing/src/main/java/com/za/common/GlobalData.kt
@@ -95,10 +95,11 @@ object GlobalData : GlobalLocalData() {
var currentLocation : AMapLocation? = null
get() {
- return field
+ return mmkv.decodeParcelable("currentLocation", AMapLocation::class.java)
}
set(value) {
- value?.time = System.currentTimeMillis()
+ value?.time= System.currentTimeMillis()
+ mmkv.encode("currentLocation", value)
field = value
}
@@ -117,7 +118,7 @@ object GlobalData : GlobalLocalData() {
currentLocation = null
driverInfoBean = null
loginTime = null
-// isLoginRecognition = null
+ isLoginRecognition = null
}
fun clearAllOrderCache() {
diff --git a/servicing/src/main/java/com/za/common/speech/SpeechManager.kt b/servicing/src/main/java/com/za/common/speech/SpeechManager.kt
index 09631c8..ef8d239 100644
--- a/servicing/src/main/java/com/za/common/speech/SpeechManager.kt
+++ b/servicing/src/main/java/com/za/common/speech/SpeechManager.kt
@@ -1,10 +1,10 @@
package com.za.common.speech
import android.app.Application
+import android.media.AudioAttributes
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
@@ -16,7 +16,11 @@ 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 kotlin.concurrent.thread
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
object SpeechManager {
private var mContext : Application? = null
@@ -65,6 +69,7 @@ object SpeechManager {
}
val audioManager =
ContextCompat.getSystemService(GlobalData.application, AudioManager::class.java)
+ originVolume = audioManager?.getStreamVolume(AudioManager.STREAM_MUSIC) ?: 0
val maxVolume = audioManager?.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC,
maxVolume ?: 1,
@@ -127,60 +132,89 @@ object SpeechManager {
}
private fun playNewOrder() {
- stopPlayMedia()
- setMaxAudioVolume()
- mediaPlayer = MediaPlayer.create(mContext, R.raw.neworder)
- mediaPlayer?.start()
- mediaPlayer?.setOnCompletionListener {
- resetAudioVolume()
+ try { // 先释放之前的MediaPlayer实例,避免资源泄漏
+ releaseMediaPlayer()
+
+ // 创建新的MediaPlayer实例
+ mediaPlayer = MediaPlayer.create(GlobalData.application, R.raw.neworder)
+ mediaPlayer?.setOnCompletionListener { // 播放完成后释放资源
+ releaseMediaPlayer()
+ }
+ mediaPlayer?.setOnErrorListener { mp, what, extra ->
+ LogUtil.print("playNewOrder", "MediaPlayer错误: what=$what, extra=$extra")
+ releaseMediaPlayer()
+ true
+ }
+
+ // 设置最大音量
+ setMaxAudioVolume()
+
+ // 开始播放
+ mediaPlayer?.start()
+ } catch (e : Exception) {
+ LogUtil.print("playNewOrder", "播放出错: ${e.message}")
+ releaseMediaPlayer()
}
}
private fun playNewOrderFromNet(url : String) {
- try {
- stopPlayMedia()
- setMaxAudioVolume()
+ try { // 先释放之前的MediaPlayer实例
+ LogUtil.print("playNewOrderFromNet", "播放新订单语音: $url")
+ releaseMediaPlayer() // 创建新的MediaPlayer实例
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?.setAudioAttributes(AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
+ .setUsage(AudioAttributes.USAGE_MEDIA).build())
+
+ mediaPlayer?.setDataSource(url)
+ mediaPlayer?.setOnPreparedListener { // 设置最大音量
+ setMaxAudioVolume() // 准备完成后开始播放
+ it.start()
}
- mediaPlayer?.setOnCompletionListener {
- resetAudioVolume()
+ mediaPlayer?.setOnCompletionListener { // 播放完成后释放资源
+ releaseMediaPlayer()
}
+ mediaPlayer?.setOnErrorListener { mp, what, extra ->
+ LogUtil.print("playNewOrderFromNet", "MediaPlayer错误: what=$what, extra=$extra")
+ releaseMediaPlayer()
+ true
+ }
+
+ // 异步准备,避免阻塞UI线程
+ mediaPlayer?.prepareAsync()
} catch (e : Exception) {
- playNewOrder()
- LogUtil.print("播放新订单失败", e)
+ LogUtil.print("playNewOrderFromNet", "播放出错: ${e.message}")
+ releaseMediaPlayer()
}
}
- fun stopPlayMedia() {
- ThreadUtils.runOnUiThread {
- if (null != mediaPlayer) {
- mediaPlayer?.stop()
- mediaPlayer?.release()
- mediaPlayer = null
+ // 安全释放MediaPlayer资源
+ fun releaseMediaPlayer() {
+ try {
+ mediaPlayer?.let {
+ if (it.isPlaying) {
+ it.stop()
+ }
+ it.reset()
+ it.release()
}
+ mediaPlayer = null // 恢复原始音量
+ resetAudioVolume()
+ } catch (e : Exception) {
+ LogUtil.print("releaseMediaPlayer", "释放MediaPlayer出错: ${e.message}")
}
}
fun speechNewOrderSound(content : String?) {
if (content.isNullOrBlank()) {
- speechNewOrderLooper("您有新的中道救援订单,请尽快接单!") { playNewOrder() }
+ speechNewOrderLocalSoundLooper()
return
}
val localResourceDao = RoomHelper.db?.localResourceDao()
val localUrlResource = localResourceDao?.getLocalResourceByName(content)
if (localUrlResource != null && ! localUrlResource.resourceUrl.isNullOrBlank()) {
- speechNewOrderLooper(content) {
- playNewOrderFromNet(localUrlResource.resourceUrl)
- }
+ speechNewOrderNetLooper(content, localUrlResource.resourceUrl ?: "")
LogUtil.print("handlerNewOrderVoice", "播放本地语音");
return
}
@@ -191,28 +225,59 @@ object SpeechManager {
.subscribe(object : BaseObserver() {
override fun doSuccess(it : String?) {
if (it == null) {
- speechNewOrderLooper(content) { playNewOrder() }
+ speechNewOrderLocalSoundLooper()
return
}
localResourceDao?.insert(LocalResourceBean(resourceName = content,
resourceType = 1,
resourceUrl = it))
- speechNewOrderLooper(content) { playNewOrderFromNet(it) }
+ speechNewOrderNetLooper(content, it)
}
override fun doFailure(code : Int, msg : String?) {
- speechNewOrderLooper("您有新的中道救援订单,请尽快接单!") { playNewOrder() }
+ speechNewOrderLocalSoundLooper()
}
})
}
- private fun speechNewOrderLooper(content : String, play : () -> Unit) {
- thread {
+
+ private fun speechNewOrderLocalSoundLooper() {
+ CoroutineScope(Dispatchers.IO).launch {
val startTime = System.currentTimeMillis()
while (System.currentTimeMillis() - startTime < 1000 * 60 * 3 && GlobalData.isHandlerNewOrder == false) {
- play()
- Thread.sleep(250L * content.length)
+ try {
+ delay(250L * "您有新的中道救援订单,请尽快接单!".length)
+ withContext(Dispatchers.Main) {
+ playNewOrder()
+ }
+ } catch (e : Exception) {
+ LogUtil.print("speechNewOrderLooper",
+ "播放循环出错: ${e.message}") // 出错时也要等待一下,避免无限循环
+ delay(1000)
+ }
}
+ GlobalData.isHandlerNewOrder = false
+ }
+ }
+
+ private fun speechNewOrderNetLooper(content : String, url : String) {
+ val url = url.replace("http://", "https://")
+ GlobalData.isHandlerNewOrder = false
+ CoroutineScope(Dispatchers.IO).launch {
+ val startTime = System.currentTimeMillis()
+ while (System.currentTimeMillis() - startTime < 1000 * 60 * 3 && GlobalData.isHandlerNewOrder == false) {
+ try {
+ withContext(Dispatchers.Main) {
+ playNewOrderFromNet(url)
+ }
+ delay(250L * content.length)
+ } catch (e : Exception) {
+ LogUtil.print("speechNewOrderLooper",
+ "播放循环出错: ${e.message}") // 出错时也要等待一下,避免无限循环
+ delay(1000)
+ }
+ }
+ GlobalData.isHandlerNewOrder = false
}
}
}
\ No newline at end of file
diff --git a/servicing/src/main/java/com/za/service/ServiceManager.kt b/servicing/src/main/java/com/za/service/ServiceManager.kt
index decfa9a..3418f30 100644
--- a/servicing/src/main/java/com/za/service/ServiceManager.kt
+++ b/servicing/src/main/java/com/za/service/ServiceManager.kt
@@ -30,7 +30,7 @@ interface PushListener {
fun importantTip(jpushBean : JpushBean)
}
-data class LastJPushBean(val msg : Int, val time : Long = System.nanoTime())
+data class LastJPushBean(val msg : String, val time : Long = System.currentTimeMillis())
object ServiceManager {
@Volatile
@@ -115,21 +115,21 @@ object ServiceManager {
// 优化后的重复消息判断
lastJPushBean?.let {
- if (System.nanoTime() - it.time < DUPLICATE_MSG_THRESHOLD && it.msg == msg.hashCode()) {
+ if (System.currentTimeMillis() - it.time < DUPLICATE_MSG_THRESHOLD && it.msg == msg) {
LogUtil.print("MessageHandler", "Duplicate message detected (hash: ${msg})")
return
}
}
if (msg.startsWith("broadcast:")) {
- lastJPushBean = LastJPushBean(msg = msg.hashCode())
- handleBroadcast(msg) // PushMessageLiveData.postPushMessage(msg)
+ lastJPushBean = LastJPushBean(msg = msg)
+ handleBroadcast(msg)
return
}
try {
- lastJPushBean = LastJPushBean(msg = msg.hashCode())
+ lastJPushBean = LastJPushBean(msg = msg)
val jpushOrderInfoBean = Gson().fromJson(msg, JpushBean::class.java)
- sendSystemNotificationFromMessage(jpushOrderInfoBean) // PushMessageLiveData.postPushMessage(msg)
+ sendSystemNotificationFromMessage(jpushOrderInfoBean)
when (jpushOrderInfoBean.pushType) {
0 -> newOrderMsg(jpushOrderInfoBean)
1 -> handleTypeOneMessage(jpushOrderInfoBean)
@@ -138,7 +138,7 @@ object ServiceManager {
"Unknown push type: ${jpushOrderInfoBean.pushType}")
}
} catch (e : Exception) {
- if (msg.startsWith("broadcast:")) { // PushMessageLiveData.postPushMessage(msg)
+ if (msg.startsWith("broadcast:")) {
handleBroadcast(msg)
}
LogUtil.print("JpushMessage", "Error handling message: ${e.message}")
diff --git a/servicing/src/main/java/com/za/service/ZdPushServiceReceive.kt b/servicing/src/main/java/com/za/service/ZdPushServiceReceive.kt
new file mode 100644
index 0000000..fa80b55
--- /dev/null
+++ b/servicing/src/main/java/com/za/service/ZdPushServiceReceive.kt
@@ -0,0 +1,237 @@
+package com.za.service
+
+import android.app.Activity
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.DialogInterface
+import android.content.Intent
+import android.media.RingtoneManager
+import android.os.Build
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.NotificationCompat
+import com.blankj.utilcode.util.ActivityUtils
+import com.blankj.utilcode.util.AppUtils
+import com.google.gson.Gson
+import com.za.base.BaseActivityLifecycleCallbacks
+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.servicing.R
+import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
+import com.za.ui.view.CommonDialogFragment
+
+class ZdPushServiceReceive : BroadcastReceiver() {
+ companion object {
+ const val RECEIVE_ACTION = "com.zd.servicing.PUSH_MESSAGE"
+ private const val GIVE_UP_TYPE_NORMAL = 1
+ private const val DIALOG_TAG_GIVE_UP = "giveUp"
+ }
+
+ private fun handlerMessage(context : Context?, intent : Intent?) {
+ val activity = context ?: ActivityUtils.getTopActivity()
+ activity as? AppCompatActivity
+ if (intent?.action == RECEIVE_ACTION) {
+ val type = intent.getStringExtra("type") ?: return
+ val message = intent.getStringExtra("message") ?: return
+ if (ActivityUtils.getTopActivity() == null) {
+ AppUtils.launchApp(GlobalData.application.packageName)
+ }
+ LogUtil.print("PushActivityLifecycleCallbacks", "收到来自远程进程的消息: $type")
+ when (type) {
+ "broadcast" -> handleBroadcast("broadcast:$message")
+
+ "giveUp" -> {
+ try {
+ val jpushBean = Gson().fromJson(message, JpushBean::class.java)
+ val activity = BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()
+ ?: ActivityUtils.getTopActivity()
+ if (activity is AppCompatActivity) {
+ handleGiveUpOrder(activity, jpushBean)
+ }
+ } catch (e : Exception) {
+ LogUtil.print("PushActivityLifecycleCallbacks",
+ "处理订单放弃消息失败: ${e.message}")
+ }
+ } // 处理其他类型的消息...
+ "importantTip" -> {
+ try {
+ val jpushBean = Gson().fromJson(message, JpushBean::class.java)
+ val activity = BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()
+ ?: ActivityUtils.getTopActivity()
+ if (activity is AppCompatActivity) {
+ handleImportantTip(activity, jpushBean)
+ }
+ } catch (e : Exception) {
+ LogUtil.print("PushActivityLifecycleCallbacks",
+ "处理重要提示消息失败: ${e.message}")
+ }
+ }
+
+ "reDispatch" -> {
+ try {
+ val jpushBean = Gson().fromJson(message, JpushBean::class.java)
+ val activity = BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()
+ ?: ActivityUtils.getTopActivity()
+ if (activity is AppCompatActivity) {
+ handleReDispatchOrder(activity, jpushBean)
+ }
+ } catch (e : Exception) {
+ LogUtil.print("PushActivityLifecycleCallbacks",
+ "处理订单重新派发消息失败: ${e.message}")
+ }
+ }
+
+ "revoke" -> {
+ try {
+ val activity = BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()
+ ?: ActivityUtils.getTopActivity()
+ if (activity is AppCompatActivity) {
+ handleRevokeOrder(activity)
+ }
+ } catch (e : Exception) {
+ LogUtil.print("PushActivityLifecycleCallbacks",
+ "处理订单撤回消息失败: ${e.message}")
+ }
+ }
+
+ }
+ }
+ }
+
+ private fun handleGiveUpOrder(activity : Activity, jpushBean : JpushBean) {
+ if (activity !is AppCompatActivity) return
+
+ // 播放提示音
+ playNotificationSound(activity)
+
+ if (GlobalData.currentOrder != null && GlobalData.currentOrder?.taskId == jpushBean.taskId) {
+ SpeechManager.playCurrentOrderCanceled()
+ CommonDialogFragment(title = "订单放弃",
+ message = buildGiveUpMessage(jpushBean),
+ confirmText = "去拍照",
+ cancelText = "我已了解",
+ confirm = {
+ OrderGiveUpActivity.Companion.goOrderGiveUpActivity(activity,
+ giveUpType = GIVE_UP_TYPE_NORMAL,
+ taskId = jpushBean.taskId)
+ }).show(activity.supportFragmentManager, DIALOG_TAG_GIVE_UP)
+ } else {
+ SpeechManager.playOrderCanceled()
+ }
+ }
+
+ private fun handleRevokeOrder(activity : Activity) {
+ playNotificationSound(activity)
+ SpeechManager.speech("订单被撤回")
+ ActivityUtils.getTopActivity().finish()
+ }
+
+ private fun handleReDispatchOrder(activity : Activity, jpushBean : JpushBean) {
+ playNotificationSound(activity)
+ BaseActivityLifecycleCallbacks.Companion.getCurrentActivity()?.let { currentActivity ->
+ if (currentActivity is AppCompatActivity) {
+ AlertDialog.Builder(currentActivity).setTitle("订单重新派发")
+ .setMessage(buildReDispatchMessage(jpushBean)).setCancelable(false)
+ .setPositiveButton("确定") { dialog, _ ->
+ dialog.dismiss()
+ currentActivity.finish()
+ }.show()
+ }
+ }
+ }
+
+ private fun handleImportantTip(activity : Activity, jpushBean : JpushBean) {
+ playNotificationSound(activity)
+ SpeechManager.speech("重要提醒:${jpushBean.tipContent ?: ""}")
+ AlertDialog.Builder(activity).setTitle("重要提醒").setMessage(jpushBean.tipContent)
+ .setNegativeButton("我已了解") { dialog : DialogInterface, _ : Int -> dialog.dismiss() }
+ .show()
+ }
+
+ // 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 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 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 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(Context.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(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.notify(NOTIFICATION_ID, notification)
+ }
+
+ override fun onReceive(context : Context?, intent : Intent?) {
+ handlerMessage(context, intent)
+ }
+}
\ No newline at end of file
diff --git a/servicing/src/main/java/com/za/service/mqtt/ConnectionOptionWrapper.kt b/servicing/src/main/java/com/za/service/mqtt/ConnectionOptionWrapper.kt
index 572cd53..2f82ea9 100644
--- a/servicing/src/main/java/com/za/service/mqtt/ConnectionOptionWrapper.kt
+++ b/servicing/src/main/java/com/za/service/mqtt/ConnectionOptionWrapper.kt
@@ -18,7 +18,7 @@ class ConnectionOptionWrapper(
*/
@JvmField
val mqttConnectOptions: MqttConnectOptions = MqttConnectOptions().apply {
- isCleanSession = false
+ isCleanSession = true
keepAliveInterval = 90 // Keep alive interval in seconds
isAutomaticReconnect = true
mqttVersion = MqttConnectOptions.MQTT_VERSION_3_1_1
diff --git a/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt b/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt
index d114845..9c5cb13 100644
--- a/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt
+++ b/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt
@@ -46,20 +46,25 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.ActivityUtils
+import com.google.gson.Gson
import com.za.base.BaseActivity
import com.za.base.theme.bgColor
import com.za.base.view.CommonButton
import com.za.base.view.EmptyView
import com.za.base.view.HeadView
import com.za.base.view.LoadError
+import com.za.bean.JpushBean
import com.za.bean.db.order.OrderInfo
import com.za.common.GlobalData
+import com.za.common.log.LogUtil
import com.za.common.util.DeviceUtil
import com.za.ext.convertToFlowName
import com.za.ext.copy
import com.za.ext.finish
import com.za.ext.goStatusPage
+import com.za.service.PushListener
import com.za.service.ServiceManager
+import com.za.service.ZdPushServiceReceive
import com.za.service.location.ZdLocationManager
import com.za.servicing.R
import kotlinx.coroutines.launch
@@ -77,6 +82,47 @@ class ServicingMainActivity : BaseActivity() {
)
}
+ override fun onResume() {
+ super.onResume()
+ setupPushMessageReceiver()
+ }
+
+ private fun setupPushMessageReceiver() { // 注册推送消息接收器
+ ServiceManager.registerPushListener(object : PushListener {
+ override fun broadcast(msg : String) {
+ sendMessageToMainProcess("broadcast", msg)
+ }
+
+ override fun giveUpOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("giveUp", Gson().toJson(jpushBean))
+ }
+
+ override fun importantTip(jpushBean : JpushBean) {
+ sendMessageToMainProcess("importantTip", Gson().toJson(jpushBean))
+ }
+
+ override fun newOrderMsg(jpushBean : JpushBean) {
+ sendMessageToMainProcess("newOrder", Gson().toJson(jpushBean))
+ }
+
+ override fun reDispatchOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("reDispatch", Gson().toJson(jpushBean))
+ }
+
+ override fun revokeOrder(jpushBean : JpushBean) {
+ sendMessageToMainProcess("revoke", Gson().toJson(jpushBean))
+ }
+ })
+ }
+
+ private fun sendMessageToMainProcess(type : String, message : String) { // 使用广播将消息发送到主进程
+ val intent = Intent(ZdPushServiceReceive.RECEIVE_ACTION).setPackage(packageName)
+ intent.putExtra("type", type)
+ intent.putExtra("message", message)
+ sendBroadcast(intent)
+ LogUtil.print(TAG, "发送消息到主进程: $type")
+ }
+
companion object {
fun goToMain(context : Context,
driverName : String? = null,
@@ -116,6 +162,7 @@ private fun ServicingMainScreen(jobCode : String? = null,
scope.launch {
ServiceManager.initialize(GlobalData.application)
ZdLocationManager.startContinuousLocation(GlobalData.application)
+
}
}
diff --git a/servicing/src/main/java/com/za/ui/servicing/order_confirm/modify_money/ModifyMoneyViewModel.kt b/servicing/src/main/java/com/za/ui/servicing/order_confirm/modify_money/ModifyMoneyViewModel.kt
index 4834706..7d0a35a 100644
--- a/servicing/src/main/java/com/za/ui/servicing/order_confirm/modify_money/ModifyMoneyViewModel.kt
+++ b/servicing/src/main/java/com/za/ui/servicing/order_confirm/modify_money/ModifyMoneyViewModel.kt
@@ -47,7 +47,7 @@ class ModifyMoneyViewModel : BaseVm() {
userOrderId = userOrderId,
taskId = taskId,
unitPrice = it?.unitPrice,
- mileage = it?.amount,
+ mileage = it?.mileage,
mileageText = "${it?.mileage ?: ""}",
calculateAmount = it?.calculateAmount,
adjustAmount = it?.adjustAmount?.toFloat(),