refactor(servicing): 重构推送消息处理机制

- 新增 ZdPushServiceReceive 类用于集中处理推送消息
- 优化了消息处理逻辑,提高了代码的可维护性和可扩展性
-改进了消息在主进程中的广播发送方式
- 优化了语音播放逻辑,提高了播放的稳定性和流畅性
- 调整了通知渠道的创建和通知的发送方式
This commit is contained in:
songzhiling
2025-04-29 17:37:46 +08:00
parent 2f57b3e238
commit 22b0f14236
12 changed files with 453 additions and 281 deletions

View File

@ -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() {

View File

@ -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<String>() {
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
}
}
}