Merge branch 'dev_robotaxi-d_250902_8.2.2' into 'master'

Dev robotaxi d 250902 8.2.2

See merge request SCA/L4HA/AndroidApp/MoGoEagleEye!876
This commit is contained in:
xinfengkun
2025-09-15 02:57:00 +00:00
414 changed files with 12801 additions and 3265 deletions

View File

@@ -1,7 +1,6 @@
package com.magic.mogo.och.charter.model
import android.content.Context
import android.net.ConnectivityManager
import com.alibaba.android.arouter.utils.TextUtils
import com.amap.api.maps.model.LatLng
import com.elegant.network.utils.GsonUtil
@@ -13,8 +12,6 @@ import com.magic.mogo.och.charter.callback.IDriverM1ControllerStatusCallback
import com.magic.mogo.och.charter.constant.CharterConst
import com.magic.mogo.och.charter.manager.CharterTrajectoryManager
import com.magic.mogo.och.charter.net.DriverM1ServiceManager
import com.mogo.commons.module.intent.IMogoIntentListener
import com.mogo.commons.module.intent.IntentManager
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters
@@ -66,7 +63,7 @@ import com.mogo.och.common.module.manager.socket.lan.bean.DPOrderClosedMsg
import com.mogo.och.common.module.manager.stopside.StopSideManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.utils.*
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import com.mogo.och.data.bean.LineInfo
/**
@@ -663,7 +660,7 @@ class DriverM1Model {
DriverM1ServiceManager.queryCurrentServiceStatus(mContext
,object: OchCommonServiceCallback<QueryBusinessStatusResponse> {
override fun onSuccess(data: QueryBusinessStatusResponse?) {
if (data == null || data.code != 0 || data.data.equals(mCurrentBusinessStatus)){
if (data == null || data.code != 0 || data.data == mCurrentBusinessStatus){
d(SceneConstant.M_CHARTER_D + TAG, "data is null or data not change" )
return
}

View File

@@ -55,7 +55,7 @@ import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.PinYinUtil
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers

View File

@@ -2,15 +2,16 @@ package com.mogo.och.charter.passenger.model
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.utilcode.util.TAG
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.PlayState
import com.mogo.och.bridge.autopilot.autopilot.IOchAutopilotStatusListener
import com.mogo.och.bridge.autopilot.autopilot.OchAutoPilotStatusListenerManager
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.utils.RxUtils
import io.reactivex.disposables.Disposable
object MusicModel : IOchAutopilotStatusListener, IOrderStatusChangeListener {
private const val TAG = "MusicModel"
init {
CharterPassengerModel.setStatusChangeListener(TAG,this)
//自动驾驶状态监听
@@ -23,36 +24,21 @@ object MusicModel : IOchAutopilotStatusListener, IOrderStatusChangeListener {
override fun onAutopilotStatusResponse(state: Int) {
// 自驾状态变化 第一次进入自驾 如果音乐属于暂停状态 开始播放 如果没有播放就播放第一首
if(state==IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
val string = SharedPrefsMgr.getInstance().getString(startMusicWithOrderKey)
if (string == null) {
CharterPassengerModel.getCurrentOrderInfo()?.let {
RxUtils.disposeSubscribe(stopMusicDisposable)
SharedPrefsMgr.getInstance().putString(startMusicWithOrderKey, it.orderNo)
AuditionManager.musicList.forEach {music->
if(music.state==PlayState.Pause){
AuditionManager.toggle(music)
return
}
}
if(!AuditionManager.isPlaying()) {
AuditionManager.playFirst()
}
MediaManager.Audition.replayOrplayFirst()
}
} else {
CharterPassengerModel.getCurrentOrderInfo()?.let {
if (it.orderNo != string) {
RxUtils.disposeSubscribe(stopMusicDisposable)
SharedPrefsMgr.getInstance().putString(startMusicWithOrderKey, it.orderNo)
AuditionManager.musicList.forEach {music->
if(music.state==PlayState.Pause){
AuditionManager.toggle(music)
return
}
}
if(!AuditionManager.isPlaying()) {
AuditionManager.playFirst()
}
MediaManager.Audition.replayOrplayFirst()
}
}
}
@@ -69,7 +55,7 @@ object MusicModel : IOchAutopilotStatusListener, IOrderStatusChangeListener {
CharterPassengerModel.getCurrentOrderInfo()?.let {
RxUtils.disposeSubscribe(stopMusicDisposable)
stopMusicDisposable = RxUtils.createSubscribe(60_000) {
AuditionManager.stop()
MediaManager.Audition.stop()
}
}
}

View File

@@ -39,7 +39,7 @@ import com.mogo.och.bridge.device.callback.LightAirconditionDoorCallback
import com.mogo.och.common.module.manager.stopside.OCHPlanningActionsCallback
import com.mogo.och.common.module.manager.stopside.StopSideStatus
import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import com.mogo.och.common.module.wigets.toast.ToastCharterUtils
import me.jessyan.autosize.utils.AutoSizeUtils
import java.util.concurrent.ConcurrentHashMap

View File

@@ -1,6 +1,5 @@
package com.mogo.och.charter.passenger.receive
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
@@ -21,7 +20,7 @@ import com.mogo.och.common.module.manager.socket.lan.bean.ChangeDestMsg
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.SoundPoolHelper
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import com.mogo.skin.utils.SkinResources
object DriverMessage: IReceivedMsgListener {

View File

@@ -14,9 +14,10 @@ import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.mogo.och.charter.passenger.R
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.manager.audition.PlayState
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.biz.media.data.PlayState
import kotlinx.android.synthetic.main.charter_p_bottom_music.view.aciv_center_image
import kotlinx.android.synthetic.main.charter_p_bottom_music.view.actv_title
import kotlinx.android.synthetic.main.charter_p_bottom_music.view.aciv_playing
@@ -27,7 +28,7 @@ open class MusicCheckView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), AuditionManager.MusicDataChangeListener {
) : ConstraintLayout(context, attrs, defStyleAttr), MusicDataChangeListener {
companion object {
private const val TAG = "StopSiteView"
@@ -87,11 +88,12 @@ open class MusicCheckView @JvmOverloads constructor(
actv_title.setTextColor(context.getColor(R.color.charter_p_090f28))
aciv_center_image.setImageResource(normalDrawable)
if(AuditionManager.isPlaying()){
if(MediaManager.Audition.isPlaying()==true){
default_info.visibility = View.GONE
aciv_playing.visibility = View.VISIBLE
aciv_playing_bg.visibility = View.VISIBLE
AuditionManager.musicDataPlaying?.let {
MediaManager.Audition.getPlaying()?.let {
Glide.with(context)
.load(it.coverHeadImageUrl)
.apply(RequestOptions().placeholder(R.drawable.charter_p_music_bg_relax_head))
@@ -140,7 +142,7 @@ open class MusicCheckView @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
AuditionManager.addDataChangeListener(TAG,this)
MediaManager.Audition.addListener(TAG,this)
parent?.let {
if (parent is ConstraintLayout) {
if (backageViewId > 0) {
@@ -155,7 +157,7 @@ open class MusicCheckView @JvmOverloads constructor(
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
AuditionManager.removeDataChangeListener(TAG)
MediaManager.Audition.removeListener(TAG)
}
override fun updateState(oldData: MusicData?, musicData: MusicData) {

View File

@@ -20,7 +20,7 @@ import com.mogo.och.charter.passenger.R
import com.mogo.och.charter.passenger.model.CharterPassengerModel
import com.mogo.och.charter.passenger.presenter.BusPassengerPresenter
import com.mogo.och.charter.passenger.presenter.CharterPassengerNoviceGuidancePresenter
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import com.mogo.skin.utils.SkinResources
import kotlinx.android.synthetic.main.charter_p_novice_guidance_fragment.include_welcome
import kotlinx.android.synthetic.main.charter_p_novice_guidance_fragment.include_welcome_01

View File

@@ -8,7 +8,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.och.charter.passenger.R
import com.mogo.och.charter.passenger.ui.music.list.MusicListView
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.biz.media.data.MusicData
import kotlinx.android.synthetic.main.charter_p_music.view.mlv_list
import kotlinx.android.synthetic.main.charter_p_music.view.mpv_music_info

View File

@@ -13,8 +13,8 @@ import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.charter.passenger.R
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.manager.audition.PlayState
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.biz.media.data.PlayState
import me.jessyan.autosize.AutoSizeCompat
/**
@@ -83,7 +83,7 @@ class MusicListItemAdapter(
holder.musicName.setTypeface(null,Typeface.NORMAL)
}
if (musicData.state==PlayState.Playing) {
if (musicData.state== PlayState.Playing) {
holder.musicPlayState.visibility = View.VISIBLE
}else{
holder.musicPlayState.visibility = View.GONE
@@ -105,7 +105,7 @@ class MusicListItemAdapter(
notifyItemInserted(dataList.size)
}
fun upDateMusicData(oldData: MusicData?,musicData: MusicData) {
fun upDateMusicData(oldData: MusicData?, musicData: MusicData) {
dataList.forEachIndexed { index, musicDataIn ->
if (musicDataIn.id==musicData.id) {
musicDataIn.state = musicData.state
@@ -143,7 +143,7 @@ class MusicListItemAdapter(
}
interface ClickListener {
fun clickItem(musicData: MusicData,position: Int)
fun clickItem(musicData: MusicData, position: Int)
}
}

View File

@@ -9,7 +9,7 @@ import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.recyclerview.widget.LinearLayoutManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.charter.passenger.R
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.biz.media.data.MusicData
import kotlinx.android.synthetic.main.charter_p_music_list.view.rv_music_list
class MusicListView : ConstraintLayout, MusicListViewModel.IMusicListViewCaLillback,
@@ -64,7 +64,7 @@ class MusicListView : ConstraintLayout, MusicListViewModel.IMusicListViewCaLillb
lineAdapter.addOneData(it)
}
override fun updateMusicData(oldData: MusicData?,musicData: MusicData) {
override fun updateMusicData(oldData: MusicData?, musicData: MusicData) {
lineAdapter.upDateMusicData(oldData,musicData)
CallerLogger.d(TAG,"${Thread.currentThread().name}----更新数据${oldData}-----${musicData}")
}
@@ -73,7 +73,7 @@ class MusicListView : ConstraintLayout, MusicListViewModel.IMusicListViewCaLillb
lineAdapter.setSelect(nextMusicData,preMusicData)
}
override fun clickItem(musicData: MusicData,position: Int) {
override fun clickItem(musicData: MusicData, position: Int) {
// 通知主页面去显示详情
this.checkListener?.checkItem(musicData)
}

View File

@@ -3,29 +3,23 @@ package com.mogo.och.charter.passenger.ui.music.list
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MusicData
class MusicListViewModel : ViewModel(),
AuditionManager.MusicDataChangeListener {
class MusicListViewModel : ViewModel(), MusicDataChangeListener {
private val TAG = MusicListViewModel::class.java.simpleName
private var viewCallback: IMusicListViewCaLillback? = null
init {
}
fun setDistanceCallback(viewCallback: IMusicListViewCaLillback) {
this.viewCallback = viewCallback
viewCallback.addAllData(AuditionManager.musicList)
CallerLogger.d(TAG,"初始化音乐${AuditionManager.musicList.size}")
AuditionManager.addDataChangeListener(TAG,this)
MediaManager.Audition.addListener(TAG,this)
}
override fun onCleared() {
AuditionManager.removeDataChangeListener(TAG)
MediaManager.Audition.removeListener(TAG)
super.onCleared()
this.viewCallback = null
}
@@ -33,10 +27,15 @@ class MusicListViewModel : ViewModel(),
interface IMusicListViewCaLillback {
fun addAllData(data:MutableList<MusicData>)
fun addOneData(it: MusicData)
fun updateMusicData(oldData: MusicData?,musicData: MusicData)
fun updateMusicData(oldData: MusicData?, musicData: MusicData)
fun upDateSelectMusic(nextMusicData: MusicData, preMusicData: MusicData?)
}
override fun onDataDis(musicList: MutableList<MusicData>) {
viewCallback?.addAllData(musicList)
CallerLogger.d(TAG,"初始化音乐${musicList.size}")
}
override fun addOneData(it: MusicData) {
CallerLogger.d(TAG,"添加音乐:${it.songName}--${it.path}")
UiThreadHandler.post({
@@ -44,7 +43,7 @@ class MusicListViewModel : ViewModel(),
}, UiThreadHandler.MODE.QUEUE)
}
override fun updateState(oldData: MusicData?,musicData: MusicData) {
override fun updateState(oldData: MusicData?, musicData: MusicData) {
UiThreadHandler.post({
viewCallback?.updateMusicData(oldData, musicData)
}, UiThreadHandler.MODE.QUEUE)

View File

@@ -17,8 +17,8 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.TimeTransformUtils
import com.mogo.och.charter.passenger.R
import com.mogo.och.charter.passenger.ui.music.list.MusicListViewModel
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.manager.audition.PlayState
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.biz.media.data.PlayState
import com.mogo.och.common.module.utils.DateTimeUtil
import kotlinx.android.synthetic.main.charter_p_music_playing.view.iv_music_cover
import kotlinx.android.synthetic.main.charter_p_music_playing.view.iv_music_cover_bg
@@ -123,7 +123,7 @@ class MusicPlayingView : ConstraintLayout, MusicPlayingViewModel.IMusicPlayingVi
tv_tag.text = musicData.tag.first()
tv_playing_time.text = DateTimeUtil.second2Time(0)
tv_playing_during.text = TimeTransformUtils.stringForTime(musicData.duration.toInt())
if(musicData.state==PlayState.Playing){
if(musicData.state== PlayState.Playing){
iv_toggle.setImageResource(R.drawable.charter_p_music_pause)
startAnimal()
}else{
@@ -168,7 +168,7 @@ class MusicPlayingView : ConstraintLayout, MusicPlayingViewModel.IMusicPlayingVi
}
override fun setPlayOrpause(it: MusicData) {
if(it.state==PlayState.Playing){
if(it.state== PlayState.Playing){
iv_toggle.setImageResource(R.drawable.charter_p_music_pause)
startAnimal()
}else{
@@ -193,7 +193,7 @@ class MusicPlayingView : ConstraintLayout, MusicPlayingViewModel.IMusicPlayingVi
tv_playing_during.text = TimeTransformUtils.stringForTime(duration.toInt())
}
override fun setSelect(currentMusicData: MusicData,preMusicData: MusicData?) {
override fun setSelect(currentMusicData: MusicData, preMusicData: MusicData?) {
viewListModel?.selectMusic(currentMusicData,preMusicData)
}

View File

@@ -3,32 +3,39 @@ package com.mogo.och.charter.passenger.ui.music.playing
import androidx.lifecycle.ViewModel
import com.elegant.utils.UiThreadHandler
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MusicData
class MusicPlayingViewModel : ViewModel(), AuditionManager.MusicDataChangeListener {
class MusicPlayingViewModel : ViewModel(), MusicDataChangeListener {
private val TAG = MusicPlayingViewModel::class.java.simpleName
private var viewCallback: IMusicPlayingViewCallback? = null
private var checkMusicData:MusicData?=null
private var checkMusicData: MusicData?=null
init {
}
private val musicDataList = mutableListOf<MusicData>()
fun setDistanceCallback(viewCallback: IMusicPlayingViewCallback) {
this.viewCallback = viewCallback
AuditionManager.addDataChangeListener(TAG,this)
MediaManager.Audition.addListener(TAG,this)
}
override fun onCleared() {
super.onCleared()
AuditionManager.removeDataChangeListener(TAG)
MediaManager.Audition.removeListener(TAG)
this.viewCallback = null
}
override fun onDataDis(musicList: MutableList<MusicData>) {
musicDataList.addAll(musicDataList)
}
override fun addOneData(it: MusicData) {
musicDataList.add(it)
}
fun setMusicData(musicData: MusicData) {
this.checkMusicData = musicData
this.viewCallback?.setViewData(musicData)
@@ -38,9 +45,8 @@ class MusicPlayingViewModel : ViewModel(), AuditionManager.MusicDataChangeListen
if(checkMusicData!=null){
setMusicData(this.checkMusicData!!)
}else{
val musicList = AuditionManager.musicList
if(musicList.size>0){
val first = musicList.first()
if (musicDataList.isNotEmpty()) {
val first = musicDataList.first()
setMusicData(first)
viewCallback?.setSelect(first,null)
}
@@ -50,33 +56,34 @@ class MusicPlayingViewModel : ViewModel(), AuditionManager.MusicDataChangeListen
fun toggle() {
checkMusicData?.let {
CallerLogger.d(TAG,"toggle:${it.songName}")
AuditionManager.toggle(it)
MediaManager.Audition.toggle(it)
}
}
fun showPreMusic() {
checkMusicData?.let {
val playing = AuditionManager.isPlaying()
val nextMusicData = AuditionManager.getPreMusicData(it)
val preTempMusic = checkMusicData
setMusicData(nextMusicData)
viewCallback?.setSelect(nextMusicData,preTempMusic)
if(playing){
AuditionManager.play(nextMusicData)
MediaManager.Audition.getPreAuditionData(it)?.let {
val preTempMusic = checkMusicData
setMusicData(it)
viewCallback?.setSelect(it,preTempMusic)
if(MediaManager.Audition.isPlaying()==true){
MediaManager.Audition.play(it)
}
}
}
}
fun showNextMusic() {
checkMusicData?.let {
val playing = AuditionManager.isPlaying()
val nextMusicData = AuditionManager.getNextMusicData(it)
val preTempMusic = checkMusicData
setMusicData(nextMusicData)
viewCallback?.setSelect(nextMusicData,preTempMusic)
if(playing){
AuditionManager.play(nextMusicData)
MediaManager.Audition.getNextAuditionData(it)?.let {
val preTempMusic = checkMusicData
setMusicData(it)
viewCallback?.setSelect(it,preTempMusic)
if(MediaManager.Audition.isPlaying()==true){
MediaManager.Audition.play(it)
}
}
}
}
@@ -84,10 +91,10 @@ class MusicPlayingViewModel : ViewModel(), AuditionManager.MusicDataChangeListen
fun setViewData(musicData: MusicData)
fun setPlayOrpause(it: MusicData)
fun setProgress(currentPlay: Long, duration: Long)
fun setSelect(currentMusicData: MusicData,preMusicData: MusicData?)
fun setSelect(currentMusicData: MusicData, preMusicData: MusicData?)
}
override fun updateState(oldData:MusicData?,musicData: MusicData) {
override fun updateState(oldData: MusicData?, musicData: MusicData) {
checkMusicData?.let {
if(it.id==musicData.id){
it.state = musicData.state
@@ -115,24 +122,25 @@ class MusicPlayingViewModel : ViewModel(), AuditionManager.MusicDataChangeListen
viewCallback?.setPlayOrpause(it)
}
}
val nextMusicData = AuditionManager.getNextMusicData(it)
val preTempMusic = checkMusicData
setMusicData(nextMusicData)
viewCallback?.setSelect(nextMusicData,preTempMusic)
AuditionManager.play(nextMusicData)
MediaManager.Audition.getNextAuditionData(it)?.let { nextMusicData->
val preTempMusic = checkMusicData
setMusicData(nextMusicData)
viewCallback?.setSelect(nextMusicData,preTempMusic)
MediaManager.Audition.play(nextMusicData)
}
}
}
fun seekTo(progress: Int) {
AuditionManager.seekTo(progress)
MediaManager.Audition.seekTo(progress)
}
fun setClickMusicData(musicData: MusicData) {
CallerLogger.d(TAG,"setClickMusicData:${musicData.songName}")
setMusicData(musicData)
val playing = AuditionManager.isPlaying()
if(playing){
AuditionManager.play(musicData)
if(MediaManager.Audition.isPlaying()==true){
MediaManager.Audition.play(musicData)
}
}
}

View File

@@ -24,8 +24,8 @@ import com.mogo.och.common.module.wigets.toast.ToastCharterUtils
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.och.charter.passenger.R
import com.mogo.och.charter.passenger.utils.FullVideoUtils
import com.mogo.och.common.module.manager.audiofocus.AudioFocusManager
import com.mogo.och.common.module.wigets.media.MediaItem
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.skin.widget.SkinImageView
import com.shuyu.gsyvideoplayer.listener.VideoAllCallBack
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
@@ -133,7 +133,7 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
start.setImageResource(R.drawable.charter_p_function_video_player_pause_small)
}
showOrHideStartPlayButton(false)
AudioFocusManager.setVideoFocusChange(true)
MediaManager.setVideoFocusChange(true)
}
else -> {
if(isIfCurrentIsFullscreen){
@@ -142,7 +142,7 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
start.setImageResource(R.drawable.charter_p_function_video_player_start_small)
}
showOrHideStartPlayButton(true)
AudioFocusManager.setVideoFocusChange(false)
MediaManager.setVideoFocusChange(false)
}
}
}
@@ -256,7 +256,7 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
override fun onCompletion() {
CallerLogger.d(TAG,"onCompletion")
AudioFocusManager.setVideoFocusChange(false)
MediaManager.setVideoFocusChange(false)
start.setImageResource(R.drawable.charter_p_function_video_player_start_small)
}
@@ -279,7 +279,7 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
override fun onError(what: Int, extra: Int) {
super.onError(what, extra)
CallerLogger.d(TAG,"onError--${what}--${extra}")
AudioFocusManager.setVideoFocusChange(false)
MediaManager.setVideoFocusChange(false)
mThumbImageViewLayout?.visibility = View.VISIBLE
ToastCharterUtils.showToastLong("哎呀,出错了,看看其他视频吧")
currentTime = -1

View File

@@ -8,7 +8,6 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.main.MainMoGoApplication
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
@@ -19,11 +18,10 @@ import com.mogo.och.charter.passenger.ui.softcontrol.layoutmanage.CarouselLayout
import com.mogo.och.charter.passenger.ui.softcontrol.layoutmanage.CarouselZoomPostLayoutListener
import com.mogo.och.charter.passenger.ui.softcontrol.layoutmanage.CenterScrollListener
import com.mogo.och.charter.passenger.ui.video.adapter.RecyclerVideoAdapter
import com.mogo.och.common.module.wigets.media.IMediaDataSourceListener
import com.mogo.och.common.module.wigets.media.MediaDataSourceManager
import com.mogo.och.common.module.wigets.media.MediaFileCacheManager
import com.mogo.och.common.module.wigets.media.MediaItem
import com.mogo.och.common.module.wigets.media.MediaPlayLogger
import com.mogo.och.common.module.biz.media.IVideoListener
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import kotlinx.android.synthetic.main.charter_p_video_fragment.view.rvVideoPlaylist
import kotlin.math.floor
@@ -80,7 +78,7 @@ class VideoView @JvmOverloads constructor(
}
}
prePlayerPosition = centerItemPosition
MediaPlayLogger.printInfoLog("pageSelect, currentPosition=$prePlayerPosition")
OchChainLogManager.writeChainLogMedia("Info", "pageSelect, currentPosition=$prePlayerPosition")
}
override fun pageStop() {
@@ -122,11 +120,11 @@ class VideoView @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
MediaFileCacheManager.createFileCacheDir(MainMoGoApplication.getApp().applicationContext)
MediaDataSourceManager.init(TAG, object : IMediaDataSourceListener {
MediaManager.Video.createCacheFileDir()
MediaManager.addListener(TAG,object :IVideoListener{
override fun onMediaDataSourceChanged(list: List<MediaItem>) {
val isNewData = mediaList.isNotEmpty()
MediaPlayLogger.printInfoLog("onMediaDataSourceChangedisNewData=$isNewData, dataSize=${list.size}, list=${GsonUtils.toJson(list)}")
OchChainLogManager.writeChainLogMedia("Info", "onMediaDataSourceChangedisNewData=$isNewData, dataSize=${list.size}, list=${GsonUtils.toJson(list)}")
val localMediaList = mutableListOf<TaxiPassengerVideoPlay>()
list.forEach {
val taxiPassengerVideoPlay = TaxiPassengerVideoPlay(
@@ -140,17 +138,18 @@ class VideoView @JvmOverloads constructor(
if (isNewData) {
if (!isVisible) {
updateMediaListDataAndView(localMediaList)
MediaPlayLogger.printInfoLog("onMediaDataSourceChanged, 宣传视频数据已更新")
OchChainLogManager.writeChainLogMedia("Info", "onMediaDataSourceChanged, 宣传视频数据已更新")
} else {
mNewMediaList.clear()
mNewMediaList.addAll(localMediaList)
}
} else {
updateMediaListDataAndView(localMediaList)
MediaPlayLogger.printInfoLog("onMediaDataSourceChanged, 宣传视频数据已更新")
OchChainLogManager.writeChainLogMedia("Info", "onMediaDataSourceChanged, 宣传视频数据已更新")
}
}
})
MediaManager.Video.init()
}
private fun updateMediaListDataAndView(newList: MutableList<TaxiPassengerVideoPlay>) {
@@ -169,7 +168,8 @@ class VideoView @JvmOverloads constructor(
}
override fun onDetachedFromWindow() {
MediaDataSourceManager.unInit(TAG)
MediaManager.Video.unInit()
MediaManager.removeListener(TAG)
super.onDetachedFromWindow()
}
@@ -193,7 +193,7 @@ class VideoView @JvmOverloads constructor(
if (mNewMediaList.isNotEmpty()) {
updateMediaListDataAndView(mNewMediaList)
mNewMediaList.clear()
MediaPlayLogger.printInfoLog("onVisibilityChanged, 宣传视频数据已更新")
OchChainLogManager.writeChainLogMedia("Info", "onVisibilityChanged, 宣传视频数据已更新")
}
} catch (e: Exception) {
e.printStackTrace()

View File

@@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.mogo.och.common.module.wigets.media.MediaItem;
import com.mogo.och.common.module.biz.media.data.MediaItem;
import com.mogo.och.common.module.wigets.toast.ToastCharterUtils;
import com.mogo.och.charter.passenger.R;
import com.mogo.och.charter.passenger.bean.TaxiPassengerVideoPlay;

View File

@@ -3,7 +3,7 @@ package com.mogo.och.charter.passenger.utils
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.voice.AIAssist
import com.mogo.och.charter.passenger.R
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.biz.media.VoiceNotice
import com.mogo.skin.utils.SkinResources
import com.mogo.tts.base.IMogoTTSCallback
import com.mogo.tts.base.LangTtsEntity

View File

@@ -40,6 +40,15 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main {
res.srcDirs = [
'src/main/res',
'src/main/res/routing',
]
}
}
}
dependencies {
@@ -53,6 +62,7 @@ dependencies {
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.material
implementation rootProject.ext.dependencies.rxandroid
implementation rootProject.ext.dependencies.amapnavi3dmap
implementation project(':OCH:common:common')
implementation rootProject.ext.dependencies.arouter

View File

@@ -2,4 +2,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.och.biz">
<application>
<activity
android:name="com.mogo.och.biz.media.video.MediaPlayerActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"
android:enabled="true"
android:exported="true"
android:resizeableActivity="false"
android:resumeWhilePausing="true"
android:screenOrientation="landscape"
android:stateNotNeeded="true"
android:theme="@style/Main"
android:windowSoftInputMode="adjustPan|stateHidden" />
</application>
</manifest>

View File

@@ -1,16 +1,19 @@
package com.mogo.och.common.module.manager.audiofocus
package com.mogo.och.biz.media
import android.content.Context
import android.media.AudioManager
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.widget.media.video.CustomManager
import com.mogo.och.common.module.manager.EnvManager
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.manager.audition.PlayState
import com.mogo.och.biz.media.audition.AuditionManager
import com.mogo.och.biz.media.video.ads.AdVideoPlayer
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.biz.media.data.PlayState
import com.shuyu.gsyvideoplayer.GSYVideoManager
object AudioFocusManager : AuditionManager.MusicDataChangeListener {
object AudioFocusManager : MusicDataChangeListener {
const val TAG = "AudioFocusManager"
@@ -23,14 +26,14 @@ object AudioFocusManager : AuditionManager.MusicDataChangeListener {
private var musicVolumeInTTS = 0
init {
AuditionManager.addDataChangeListener(TAG,this)
AuditionManager.addMusicListener(TAG,this)
mAudioManager = AbsMogoApplication.getApp().getSystemService(Context.AUDIO_SERVICE) as AudioManager
mMaxVolume = mAudioManager?.getStreamMaxVolume(AudioManager.STREAM_MUSIC)?:0
musicVolumeInTTS = (mMaxVolume*0.1f).toInt()
musicVolumeInTTS = (mMaxVolume *0.1f).toInt()
}
override fun updateState(oldData: MusicData?, musicData: MusicData) {
val temp = musicData.state==PlayState.Playing
val temp = musicData.state== PlayState.Playing
if(temp!= isPlayingMusic){
isPlayingMusic = temp
}
@@ -38,7 +41,7 @@ object AudioFocusManager : AuditionManager.MusicDataChangeListener {
// 播放音乐需要把视频暂停掉
GSYVideoManager.onPause()
}
CallerLogger.d(TAG,"music updateState ${isPlayingTTS}--${isPlayingMusic}---${isPlayingVideo}")
CallerLogger.d(TAG,"music updateState $isPlayingTTS--$isPlayingMusic---$isPlayingVideo")
}
fun setTTSFocusChange(isSpeaking:Boolean){
@@ -51,17 +54,27 @@ object AudioFocusManager : AuditionManager.MusicDataChangeListener {
AuditionManager.setVolume(0.3f,0.3f)
}
}
if (isPlayingVideo) {
CustomManager.getCustomManagersByTag(AdVideoPlayer.TAG).forEach{
it.setNeedMute(true)
}
// GSYVideoManager.instance().curPlayerManager?.setNeedMute(true)
}
}else{
if(isPlayingMusic){
AuditionManager.setVolume(1f,1f)
}
CustomManager.getCustomManagersByTag(AdVideoPlayer.TAG).forEach{
it.setNeedMute(false)
}
// GSYVideoManager.instance().curPlayerManager?.setNeedMute(false)
}
}
CallerLogger.d(TAG, "setTTSFocusChange ${isPlayingTTS}--${isPlayingMusic}---${isPlayingVideo}")
CallerLogger.d(TAG, "setTTSFocusChange $isPlayingTTS--$isPlayingMusic---$isPlayingVideo")
}
fun setVideoFocusChange(isPlaying:Boolean){
CallerLogger.d(TAG, "setMusicFocusChange ${isPlayingTTS}--${isPlayingMusic}---${isPlayingVideo}")
CallerLogger.d(TAG, "setMusicFocusChange $isPlayingTTS--$isPlayingMusic---$isPlayingVideo")
if(isPlaying!= isPlayingVideo) {
isPlayingVideo = isPlaying
if(isPlaying){
@@ -70,6 +83,19 @@ object AudioFocusManager : AuditionManager.MusicDataChangeListener {
}else {
AuditionManager.stop()
}
if (isPlayingTTS) {
CustomManager.getCustomManagersByTag(AdVideoPlayer.TAG).forEach{
it.setNeedMute(true)
}
// GSYVideoManager.instance().curPlayerManager?.setNeedMute(true)
}
} else {
if (!isPlayingTTS) {
CustomManager.getCustomManagersByTag(AdVideoPlayer.TAG).forEach{
it.setNeedMute(false)
}
// GSYVideoManager.instance().curPlayerManager?.setNeedMute(false)
}
}
}
}

View File

@@ -0,0 +1,194 @@
package com.mogo.och.biz.media
import android.content.Context
import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.function.call.base.CallerBase
import com.mogo.eagle.core.function.main.MainMoGoApplication
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils
import com.mogo.och.biz.media.audition.AuditionManager
import com.mogo.och.biz.media.tts.VoiceIn
import com.mogo.och.biz.media.tts.VoiceOut
import com.mogo.och.biz.media.video.MediaDataSourceManager
import com.mogo.och.biz.media.video.MediaPlayerActivity
import com.mogo.och.biz.media.video.VideoPlayerFragment
import com.mogo.och.common.module.biz.media.IVideoListener
import com.mogo.och.common.module.biz.media.MediaService
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.biz.media.video.MediaFileCacheManager
import com.mogo.och.biz.media.video.ads.AdMediaView
import com.mogo.tts.base.IMogoTTSCallback
import com.mogo.tts.base.LangTtsEntity
/**
* eye 桥
*/
@Route(path = OchCommonConst.BIZ_Media)
class MediaProvider : MediaService, CallerBase<IVideoListener>() {
private var context: Context? = null
private val tag = M_OCHCOMMON + "MediaProvider"
override fun init(context: Context?) {
this.context = context
}
override fun addVideoListener(tag: String, listener: IVideoListener) {
addListener(tag, listener)
}
override fun removeVideoListener(tag: String) {
removeListener(tag)
}
override fun doSomeAfterAddListener(tag: String, listener: IVideoListener) {
MediaDataSourceManager.dispatchMediaData()
}
override fun postSiteIntroduceInfo(list: MutableList<MediaItem>) {
M_LISTENERS.forEach {
it.value.diapatchMedia(list)
}
}
override fun setMediaResume() {
M_LISTENERS.forEach {
it.value.setMediaResume()
}
}
override fun setMediaPause() {
M_LISTENERS.forEach {
it.value.setMediaPause()
}
}
fun invokeMediaDataChange(newDataList: List<MediaItem>) {
M_LISTENERS.forEach {
it.value.onMediaDataSourceChanged(newDataList)
}
}
override fun setTTSFocusChange(speaking: Boolean) {
AudioFocusManager.setTTSFocusChange(speaking)
}
override fun setVideoFocusChange(playing: Boolean) {
AudioFocusManager.setVideoFocusChange(playing)
}
override fun musicStop() {
AuditionManager.stop()
}
override fun musicReplayOrplayFirst() {
AuditionManager.replayOrplayFirst()
}
override fun removeAuditionListener(tag: String) {
AuditionManager.removeMusicListener(tag)
}
override fun addAuditionListener(tag: String, listener: MusicDataChangeListener) {
AuditionManager.addMusicListener(tag,listener)
}
override fun auditionIsPlaying(): Boolean {
return AuditionManager.isPlaying()
}
override fun getPlaying(): MusicData? {
return AuditionManager.musicDataPlaying
}
override fun palyAudition(musicData: MusicData) {
AuditionManager.play(musicData)
}
override fun getPreAuditionData(it: MusicData): MusicData {
return AuditionManager.getPreMusicData(it)
}
override fun getNextAuditionData(it: MusicData): MusicData {
return AuditionManager.getNextMusicData(it)
}
override fun toggle(musicData: MusicData) {
AuditionManager.toggle(musicData)
}
override fun seekTo(progress: Int) {
AuditionManager.seekTo(progress)
}
override fun getAuditionDataList(): MutableList<MusicData> {
return AuditionManager.musicList
}
override fun showNotice(
notice: String?,
level: Int,
delayed: Long,
callBack: IMogoTTSCallback?
) {
VoiceIn.showNotice(notice,level,delayed,callBack)
}
override fun showNotice(
listTTS: MutableList<LangTtsEntity>,
level: Int,
callBack: IMogoTTSCallback?
) {
VoiceIn.showNotice(listTTS,level,callBack)
}
override fun showNoticeOut(notice: String?) {
VoiceOut.showNoticeOut(notice)
}
override fun startSecondAds() {
MultiDisplayUtils.startActWithSecond(ActivityUtils.getTopActivity(), MediaPlayerActivity::class.java)
}
override fun getAdFragment(): VideoPlayerFragment {
return VideoPlayerFragment()
}
override fun getAdView(context: Context): View {
return AdMediaView(context)
}
override fun createCacheFileDir() {
MediaFileCacheManager.createFileCacheDir(MainMoGoApplication.getApp().applicationContext)
}
override fun initMediaData() {
MediaDataSourceManager.init()
}
override fun unInitMediaData() {
MediaDataSourceManager.unInit()
}
override fun stopTTs() {
VoiceIn.stopCurrentTts()
}
override fun loadOuttts() {
VoiceOut.load()
}
override fun releaseOuttts() {
VoiceOut.release()
}
}

View File

@@ -0,0 +1,34 @@
package com.mogo.och.biz.media
import android.annotation.SuppressLint
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.common.module.biz.media.IVideoListener
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.constant.OchCommonConst
object MediaServiceManager {
private const val TAG = M_OCHCOMMON+"MediaServiceManager"
@SuppressLint("StaticFieldLeak")
private var mediaService: MediaProvider? =
ARouter.getInstance().build(OchCommonConst.BIZ_Media).navigation() as MediaProvider
fun invokeMediaSourceDataChange(newDataList: List<MediaItem>) {
mediaService?.invokeMediaDataChange(newDataList)
}
fun invokeCreateCacheFileDir() {
mediaService?.createCacheFileDir()
}
fun addVideoListener(tag:String,listener: IVideoListener){
mediaService?.addVideoListener(tag,listener)
}
fun removeVideoListener(tag: String){
mediaService?.removeVideoListener(tag)
}
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.common.module.manager.audition
package com.mogo.och.biz.media.audition
import android.media.AudioManager
import android.media.MediaPlayer
@@ -24,7 +24,7 @@ object Audition: MediaPlayer.OnPreparedListener,
}
fun registerOnAuditionListener(listener: OnAuditionListener?) {
this.listener = listener
Audition.listener = listener
}
fun unregisterOnAuditionListener() {

View File

@@ -1,4 +1,4 @@
package com.mogo.och.common.module.manager.audition
package com.mogo.och.biz.media.audition
import android.media.MediaExtractor
import android.media.MediaFormat
@@ -11,11 +11,12 @@ import com.mogo.eagle.core.utilcode.download.callback.IDownloadListener
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager.EVENT_KEY_INFE_WITH_MUSIC
import com.mogo.och.common.module.utils.FileUtils
import com.mogo.och.common.module.wigets.media.MediaBeanManager
import com.mogo.och.common.module.wigets.media.MediaPlayLogger
import com.mogo.och.biz.media.video.MediaBeanManager
import com.mogo.och.biz.media.video.MediaPlayLogger
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
@@ -25,7 +26,7 @@ import com.mogo.eagle.core.utilcode.util.FileUtils as FileHelper
object AuditionCacheManager {
private var dataChangeListener:DataChangeListener?=null
private var dataChangeListener: DataChangeListener?=null
private val context = AbsMogoApplication.getApp()
private const val TAG = "AuditionCacheManager"
@@ -175,7 +176,7 @@ object AuditionCacheManager {
}
fun addDataChangeListener(dataChangeListener: DataChangeListener) {
this.dataChangeListener = dataChangeListener
AuditionCacheManager.dataChangeListener = dataChangeListener
getMusicDataByLocationConfig()
}

View File

@@ -1,8 +1,10 @@
package com.mogo.och.common.module.manager.audition
package com.mogo.och.biz.media.audition
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.manager.audiofocus.AudioFocusManager
import com.mogo.och.common.module.biz.media.MusicDataChangeListener
import com.mogo.och.common.module.biz.media.data.MusicData
import com.mogo.och.common.module.biz.media.data.PlayState
import java.util.concurrent.ConcurrentHashMap
object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAuditionListener {
@@ -18,22 +20,22 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
init {
AuditionCacheManager.addDataChangeListener(this)
Audition.registerOnAuditionListener(this)
AudioFocusManager.load()
}
fun addDataChangeListener(tag: String, listener: MusicDataChangeListener) {
fun addMusicListener(tag: String, listener: MusicDataChangeListener) {
if (dataChangeListeners.containsKey(tag)) {
return
}
dataChangeListeners[tag] = listener
listener.onDataDis(musicList)
}
fun removeDataChangeListener(tag: String){
fun removeMusicListener(tag: String){
dataChangeListeners.remove(tag)
}
private fun getMusicDataByState(state:PlayState):Pair<Int,MusicData>?{
private fun getMusicDataByState(state: PlayState):Pair<Int, MusicData>?{
musicList.forEachIndexed { index, musicData ->
if(musicData.state==state){
return Pair(index,musicData)
@@ -103,10 +105,23 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
}
}
private fun resetData():MusicData?{
var tempRusult:MusicData?=null
//如果音乐属于暂停状态 开始播放 如果没有播放就播放第一首
fun replayOrplayFirst(){
musicList.forEach {music->
if(music.state==PlayState.Pause){
toggle(music)
return
}
}
if(!isPlaying()) {
playFirst()
}
}
private fun resetData(): MusicData?{
var tempRusult: MusicData?=null
musicList.forEach {
if(it.state!=PlayState.None){
if(it.state!= PlayState.None){
tempRusult = it
}
it.state = PlayState.None
@@ -127,20 +142,6 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
}
}
public interface MusicDataChangeListener{
fun addOneData(it: MusicData){}
/**
* toggle 修改播放器状态
* @param oldData 上一个不是 PlayState.None 的歌曲
* @param musicData 当前播放状态发生变化的歌曲
*/
fun updateState(oldData: MusicData?,musicData: MusicData)
fun updatePlayCurrent(currentPlay: Long, duration: Long, second: MusicData){}
fun onMusicCompletion(musicData: MusicData) {}
}
/**
* 音乐播放完毕
*/
@@ -152,7 +153,7 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
it.value.onMusicCompletion(oldData)
}
}else{
musicList.forEach {musicData->
musicList.forEach { musicData->
if(musicData.path==path){
dataChangeListeners.forEach {
it.value.onMusicCompletion(musicData)
@@ -183,7 +184,7 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
}
}else{
musicList.forEachIndexed { index, musicData ->
if(musicData.path==Audition.oldPath){
if(musicData.path== Audition.oldPath){
dataChangeListeners.forEach {
it.value.updatePlayCurrent(currentPlay,duration,musicData)
}
@@ -193,7 +194,7 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
}
}
fun getNextMusicData(it: MusicData):MusicData {
fun getNextMusicData(it: MusicData): MusicData {
val indexOf = musicList.indexOf(it)
if(indexOf== musicList.size-1){
return musicList.first()
@@ -216,7 +217,7 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
}
fun setVolume(leftVolume:Float, rightVolume:Float){
Audition.setVolume(leftVolume,rightVolume)
Audition.setVolume(leftVolume, rightVolume)
}
}

View File

@@ -1,11 +1,11 @@
package com.mogo.och.common.module.voice
package com.mogo.och.biz.media.tts
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.manager.audiofocus.AudioFocusManager
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.bean.OutofVoice
@@ -14,43 +14,11 @@ import com.mogo.tts.base.LangTtsEntity
import com.mogo.tts.base.LanguageType
import com.mogo.tts.base.MultiLangTtsEntity
object VoiceNotice {
object VoiceIn {
const val onlyChinese = 1 //中文
const val chineseEnglishKorean = 1 shl 1 // 左移一位 中英韩
@JvmStatic
fun showNotice(notice: String?) {
showNotice(notice, AIAssist.LEVEL0)
}
@JvmStatic
fun showNoticeOut(notice: String?) {
save2Log("车外准备播放 内容${notice}")
notice?.let {
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
val outofVoice = OutofVoice(notice)
LanSocketManager.sendMsgToClient(outofVoice)
}else{
AIAssist.getInstance(AbsMogoApplication.getApp()).playVoiceOutside(notice)
}
}
}
@JvmStatic
fun showNotice(notice: String?, level: Int) {
showNotice(notice,level,0)
}
@JvmStatic
fun showNotice(notice: String?, delayed: Long) {
showNotice(notice, AIAssist.LEVEL0, delayed)
}
@JvmStatic
fun showNotice(notice: String?, delayed: Long,callback:IMogoTTSCallback ) {
showNotice(notice, AIAssist.LEVEL0, delayed,callback)
}
@JvmStatic
@@ -99,12 +67,6 @@ object VoiceNotice {
}
fun speakTTSVoiceWithLevel(text:String, level:Int, callBack:IMogoTTSCallback){
save2Log("准备播放${text}")
AIAssist.getInstance(AbsMogoApplication.getApp()).speakTTSVoiceWithLevel(text,level,callCallBack(callBack))
}
private fun callCallBack(callBack: IMogoTTSCallback?):IMogoTTSCallback{
@@ -112,21 +74,21 @@ object VoiceNotice {
override fun onSpeakStart(speakText: String?) {
super.onSpeakStart(speakText)
callBack?.onSpeakStart(speakText)
AudioFocusManager.setTTSFocusChange(true)
MediaManager.setTTSFocusChange(true)
save2Log("开始播放${speakText}")
}
override fun onSpeakEnd(speakText: String?) {
super.onSpeakEnd(speakText)
callBack?.onSpeakEnd(speakText)
AudioFocusManager.setTTSFocusChange(false)
MediaManager.setTTSFocusChange(false)
save2Log("结束播放${speakText}")
}
override fun onSpeakError(speakText: String?, errorMsg: String?) {
super.onSpeakError(speakText, errorMsg)
callBack?.onSpeakError(speakText,errorMsg)
AudioFocusManager.setTTSFocusChange(false)
MediaManager.setTTSFocusChange(false)
save2Log("播放错误,内容:${speakText}、errorMsg:${errorMsg}")
}
}

View File

@@ -1,14 +1,29 @@
package com.mogo.och.common.module.voice
package com.mogo.och.biz.media.tts
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
import com.mogo.och.common.module.manager.socket.lan.bean.OutofVoice
object OutOffVoice {
object VoiceOut {
@JvmStatic
fun showNoticeOut(notice: String?) {
VoiceIn.save2Log("车外准备播放 内容${notice}")
notice?.let {
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
val outofVoice = OutofVoice(notice)
LanSocketManager.sendMsgToClient(outofVoice)
}else{
AIAssist.getInstance(AbsMogoApplication.getApp()).playVoiceOutside(notice)
}
}
}
val outffListener = object : ILanMessageListener<OutofVoice> {
override fun targetLan(): Class<OutofVoice> {

View File

@@ -1,11 +1,12 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import com.google.gson.reflect.TypeToken
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.Vehicle
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.biz.media.data.MusicData
object MediaBeanManager {
@@ -72,56 +73,13 @@ object MediaBeanManager {
}
}
data class MediaDataWithVehicleList(val musicDataWithEnvList: MutableList<MediaDataWithVehicle>) {
}
data class MediaDataWithVehicle(
val B1: B1,
val B2: B2,
val T1T2: T1T2,
val M1: M1,
val B1: MediaVehicle,
val B2: MediaVehicle,
val T1T2: MediaVehicle,
val M1: MediaVehicle,
)
data class B1(val medias: MutableList<MediaItem>, val musics: MutableList<MusicData>)
data class B2(val medias: MutableList<MediaItem>, val musics: MutableList<MusicData>)
data class T1T2(val medias: MutableList<MediaItem>, val musics: MutableList<MusicData>)
data class M1(val medias: MutableList<MediaItem>, val musics: MutableList<MusicData>)
data class MediaBean(
val medias: MutableList<MediaItem>,
val musics: MutableList<MusicData>,
)
data class MediaItem(
var priority: Int,
var fileUrl: String,
var fileType: Int,
var coverImageUrl: String,
var title: String,
val isTemp: Boolean = false
) {
companion object {
const val MEDIA_TYPE_IMAGE = 1
const val MEDIA_TYPE_VIDEO = 2
const val PriorityConfi = 2
const val PriorityAd = 1
const val PrioritySite = 0
// 站点优先级 0
// 广告优先级 1
// 本地配置是 2
}
fun isImageType(): Boolean {
return this.fileType == MEDIA_TYPE_IMAGE
}
fun isVideoType(): Boolean {
return this.fileType == MEDIA_TYPE_VIDEO
}
data class MediaVehicle (val medias: MutableList<MediaItem>, val musics: MutableList<MusicData>)
}

View File

@@ -1,31 +1,30 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import com.google.gson.reflect.TypeToken
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.debug.DebugConfig
import com.mogo.commons.env.ProjectUtils
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.biz.media.MediaServiceManager
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.biz.media.data.MediaItem.Companion.MEDIA_TYPE_IMAGE
import com.mogo.och.common.module.biz.media.data.MediaItem.Companion.MEDIA_TYPE_VIDEO
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.network.OchCommonSubscribeImpl
import com.mogo.och.common.module.network.interceptor.transformTry
import com.mogo.och.common.module.wigets.media.MediaItem.Companion.MEDIA_TYPE_IMAGE
import com.mogo.och.common.module.wigets.media.MediaItem.Companion.MEDIA_TYPE_VIDEO
import io.reactivex.Observable
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Query
import java.util.concurrent.ConcurrentHashMap
/**
* 广告视频数据源 管理类
@@ -64,23 +63,19 @@ object MediaDataSourceManager {
private var mHasEverGetMediaDataFromMis = false
private val mMediaDataSourceListenerMap: ConcurrentHashMap<String, IMediaDataSourceListener> =
ConcurrentHashMap()
private val getAdDataSourceLoopRunnable = Runnable {
startGetMediaDataSourceLoop()
}
fun init(tag: String, dataSourceListener: IMediaDataSourceListener) {
if (!mMediaDataSourceListenerMap.containsKey(tag)) {
mMediaDataSourceListenerMap[tag] = dataSourceListener
}
fun init() {
MediaPlayLogger.printInfoLog("init, 初始化环境 isSassProject=${ProjectUtils.isSaas()}")
if (ProjectUtils.isSaas()||ProjectUtils.isDali()) {
if(ProjectUtils.isSaas()){
mNetworkService = MoGoRetrofitFactory.getInstance(OchCommonConst.getEagleMisUrl()).create(IMediaNetworkApi::class.java)
mNetworkService = MoGoRetrofitFactory.getInstance(OchCommonConst.getEagleMisUrl()).create(
IMediaNetworkApi::class.java)
}else if(ProjectUtils.isDali()){
mNetworkService = MoGoRetrofitFactory.getInstance(OchCommonConst.getBaseUrl()).create(IMediaNetworkApi::class.java)
mNetworkService = MoGoRetrofitFactory.getInstance(OchCommonConst.getBaseUrl()).create(
IMediaNetworkApi::class.java)
}
MediaPlayLogger.printInfoLog("init, 开始检查后台配置数据")
startGetMediaDataSourceLoop()
@@ -92,12 +87,9 @@ object MediaDataSourceManager {
}
}
fun unInit(tag: String) {
fun unInit() {
MediaPlayLogger.printInfoLog("unInit")
removeGetMediaDataSourceLoop()
if (mMediaDataSourceListenerMap.containsKey(tag)) {
mMediaDataSourceListenerMap.remove(tag)
}
mLastMediaDataSourceList.clear()
}
@@ -226,17 +218,15 @@ object MediaDataSourceManager {
private fun updateMediaDataSource(newDataList: List<MediaItem>) {
mLastMediaDataSourceList.clear()
mLastMediaDataSourceList.addAll(newDataList)
mMediaDataSourceListenerMap.forEach {
val listener = it.value
listener.onMediaDataSourceChanged(newDataList)
}
MediaServiceManager.invokeMediaSourceDataChange(newDataList)
MediaPlayLogger.printInfoLog("下发新MediaData给监听者dataSize=${newDataList.size}")
}
}
fun dispatchMediaData(){
MediaPlayLogger.printInfoLog("注册后下发新MediaData给监听者dataSize=${mLastMediaDataSourceList.size}")
MediaServiceManager.invokeMediaSourceDataChange(mLastMediaDataSourceList)
}
interface IMediaDataSourceListener {
fun onMediaDataSourceChanged(list: List<MediaItem>)
}
interface IMediaNetworkApi {

View File

@@ -1,10 +1,9 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import android.content.Context
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import com.mogo.eagle.core.utilcode.download.DownloadUtils
import com.mogo.eagle.core.utilcode.download.callback.IDownloadListener
import com.mogo.eagle.core.utilcode.util.EncryptUtils
import com.mogo.och.common.module.manager.download.DownloadManager
@@ -59,7 +58,7 @@ object MediaFileCacheManager {
* 获取文件缓存的缓存path, 文件名以base64编码避免 中文命名重复文件名的影响
*/
fun getCacheFileFullPathByUrl(context: Context, mediaUrl: String): String {
return getFileCacheDir(context) +File.separator +getCacheFileName(mediaUrl)
return getFileCacheDir(context) +File.separator + getCacheFileName(mediaUrl)
}
/**

View File

@@ -1,7 +1,5 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import AdvanceImageView
import AdvanceVideoView
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
@@ -13,8 +11,9 @@ import androidx.viewpager.widget.ViewPager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.CountDownTimer
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.common.module.wigets.media.MediaLoopPlayView.Companion.IMAGE_COUNT_DOWN_SECONDS
import com.mogo.och.common.module.wigets.media.MediaLoopPlayView.Companion.TAG
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.biz.media.video.MediaLoopPlayView.Companion.IMAGE_COUNT_DOWN_SECONDS
import com.mogo.och.biz.media.video.MediaLoopPlayView.Companion.TAG
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
class MediaLoopPlayView @JvmOverloads constructor(
@@ -93,7 +92,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
fun setMediaData(list: MutableList<MediaItem>) {
if (list.isEmpty()) {
MediaPlayLogger.printInfoLog( "setMediaData, list为空")
MediaPlayLogger.printInfoLog("setMediaData, list为空")
return
}
@@ -162,7 +161,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
videoView.initVideoUrlData(item.fileUrl, item.coverImageUrl,item.priority,item.isTemp)
mItemViewList.add(videoView)
} else {
MediaPlayLogger.printErrorLog( "addItemView 不支持的文件类型:${item.fileType}")
MediaPlayLogger.printErrorLog("addItemView 不支持的文件类型:${item.fileType}")
}
}
@@ -340,7 +339,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
}
override fun onFinish() {
MediaPlayLogger.printInfoLog( "mImageCountDownTimer, 倒计时${IMAGE_COUNT_DOWN_SECONDS}秒, onFinish")
MediaPlayLogger.printInfoLog("mImageCountDownTimer, 倒计时${IMAGE_COUNT_DOWN_SECONDS}秒, onFinish")
playNextItemView(false)
}
}.start()
@@ -404,7 +403,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
}
fun setPause() {
MediaPlayLogger.printInfoLog("${MediaLoopPlayView.TAG}, setPause")
MediaPlayLogger.printInfoLog("$TAG, setPause")
if (mItemViewList.size <= 0) {
return
}
@@ -418,7 +417,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
}
fun setResume() {
MediaPlayLogger.printInfoLog("${MediaLoopPlayView.TAG}, setResume")
MediaPlayLogger.printInfoLog("$TAG, setResume")
if (mItemViewList.size <= 0) {
return
}

View File

@@ -1,9 +1,10 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.mogo.commons.utils.MogoAnalyticUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -32,13 +33,7 @@ object MediaPlayLogger {
*/
private fun trackEvent(level: String, msg: String) {
ProcessLifecycleOwner.get().lifecycleScope.launch(Dispatchers.IO) {
val map: MutableMap<String, Any> = HashMap()
map["level"] = level
map["msg"] = msg
MogoAnalyticUtils.track(
MEDIA_PLAY_PROCESS_KEY_NODE_LOG,
map
)
OchChainLogManager.writeChainLogMedia(level,msg)
}
}
}

View File

@@ -1,21 +1,11 @@
package com.mogo.och.common.module.wigets.media
package com.mogo.och.biz.media.video
import android.Manifest
import android.app.ActivityOptions
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.provider.Settings
import android.view.Display
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.mogo.eagle.core.function.main.MainLauncherActivity
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.utils.RxUtils
import com.mogo.och.biz.R
class MediaPlayerActivity : AppCompatActivity() {
@@ -23,8 +13,8 @@ class MediaPlayerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_video_player)
val fragment = MediaPlayerFragment()
setContentView(R.layout.biz_activity_video_player)
val fragment = VideoPlayerFragment()
supportFragmentManager.beginTransaction().add(R.id.videoPlayerContainer, fragment)
.commitAllowingStateLoss()
BarUtils.hideStatusBarAndSticky(this.window)

View File

@@ -1,3 +1,5 @@
package com.mogo.och.biz.media.video
import android.content.Context
import android.graphics.Bitmap
import android.media.AudioManager
@@ -21,10 +23,7 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.och.common.module.utils.CustomManager
import com.mogo.och.common.module.R
import com.mogo.och.common.module.wigets.media.MediaFileCacheManager
import com.mogo.och.common.module.wigets.media.MediaItem
import com.mogo.och.common.module.wigets.media.MediaLoopPlayView
import com.mogo.och.common.module.wigets.media.MediaPlayLogger
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.skin.utils.SkinResources
import com.mogo.skin.widget.SkinImageView
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder

View File

@@ -0,0 +1,72 @@
package com.mogo.och.biz.media.video
import com.mogo.commons.mvp.MvpFragment
import com.mogo.commons.mvp.Presenter
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.och.biz.R
import com.mogo.och.common.module.biz.media.IVideoListener
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.biz.media.data.MediaItem
import kotlinx.android.synthetic.main.biz_fragment_video_player.acb_add_site_video
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class VideoPlayerFragment :
MvpFragment<VideoPlayerFragment?, MediaPlayerPresenter?>(), IVideoListener {
companion object {
private val TAG = VideoPlayerFragment::class.java.simpleName
}
override fun getLayoutId(): Int {
return R.layout.biz_fragment_video_player
}
override fun createPresenter(): MediaPlayerPresenter {
return MediaPlayerPresenter(this)
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
acb_add_site_video.onClick {
val siteList = mutableListOf<MediaItem>()
// siteList.add(MediaItem(MediaItem.PrioritySite,"https://img.zhidaozhixing.com/fileServer/defaultPath/b47f361c3de6ea490f3086407fc0376f/a1%E8%B7%AF%E7%BA%BF%281%29.mp4",MediaItem.MEDIA_TYPE_VIDEO,"","title"))
siteList.add(MediaItem(MediaItem.PrioritySite,"https://img.zhidaozhixing.com/fileServer/online_car_hailing/1676357557335/3.mp4",MediaItem.MEDIA_TYPE_VIDEO,"","title"))
setHightPriorityMediaItem(siteList)
}
}
fun setHightPriorityMediaItem(list: MutableList<MediaItem>){
MediaManager.postSiteIntroduceInfo(list)
}
override fun onPause() {
super.onPause()
}
override fun onResume() {
super.onResume()
}
override fun onDestroy() {
super.onDestroy()
}
override fun setMediaPause() {
super.setMediaPause()
}
override fun setMediaResume() {
super.setMediaResume()
}
}
class MediaPlayerPresenter(view: VideoPlayerFragment?) :
Presenter<VideoPlayerFragment?>(view)

View File

@@ -0,0 +1,218 @@
package com.mogo.och.biz.media.video.ads
import android.content.Context
import android.graphics.Bitmap
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.och.biz.R
import com.mogo.och.biz.media.video.MediaLoopPlayView
import com.mogo.och.biz.media.video.MediaPlayLogger
import com.mogo.och.biz.media.video.ads.AdMediaViewModel.AdMediaViewCallback
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.skin.utils.SkinResources
import com.mogo.skin.widget.SkinImageView
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import kotlinx.android.synthetic.main.biz_ad_video_image.view.adVideoPlayer
import kotlinx.android.synthetic.main.biz_ad_video_image.view.imagePlayer
class AdMediaView : FrameLayout, AdMediaViewCallback {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(
context,
attributeSet,
defStyleAttr
)
private val TAG = "AdMediaView"
private var viewModel: AdMediaViewModel? = null
private var gsyVideoPlayerOptionBuilder: GSYVideoOptionBuilder? = null
private var thumbnailImageView: SkinImageView? = null
val placeholderDrawable = SkinResources.getInstance().getDrawable(R.drawable.road_video_bg)
var adPlayerCurrentPosition = -1
init {
LayoutInflater.from(context).inflate(R.layout.biz_ad_video_image, this, true)
initView()
}
private fun initView() {
//缩略图
thumbnailImageView = SkinImageView(context)
thumbnailImageView?.scaleType = ImageView.ScaleType.FIT_XY
adVideoPlayer?.thumbImageView = thumbnailImageView
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(AdMediaViewModel::class.java)
}
viewModel?.setAdMediaCallback(this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
}
override fun startPlayImage(mediaItem: MediaItem) {
BizLoopManager.runInMainThread {
myStartPlayImage(mediaItem)
}
}
private fun myStartPlayImage(mediaItem: MediaItem) {
adVideoPlayer?.visibility = GONE
imagePlayer?.visibility = VISIBLE
imagePlayer?.also {
Glide.with(context).asBitmap().load(mediaItem.fileUrl).apply(
RequestOptions().useUnlimitedSourceGeneratorsPool(true)
.placeholder(placeholderDrawable)
.error(placeholderDrawable)
.fallback(placeholderDrawable)
.centerCrop()
).listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
MediaPlayLogger.printErrorLog("图片加载失败:${e?.message}")
return false
}
override fun onResourceReady(
resource: Bitmap?,
model: Any?,
target: Target<Bitmap>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
return false
}
})
.into(it)
}
}
override fun startPlayVideo(mediaItem: MediaItem, playerCallback: GSYSampleCallBack) {
BizLoopManager.runInMainThread {
myStartPlayVideo(mediaItem, playerCallback)
}
}
private fun myStartPlayVideo(mediaItem: MediaItem, playerCallback: GSYSampleCallBack) {
try {
adVideoPlayer?.visibility = VISIBLE
imagePlayer?.visibility = GONE
adVideoPlayer?.onVideoReset()
thumbnailImageView?.also {
Glide.with(context).asBitmap().load(mediaItem.coverImageUrl)
.apply(
RequestOptions().useUnlimitedSourceGeneratorsPool(true)
.placeholder(placeholderDrawable)
.error(placeholderDrawable)
.fallback(placeholderDrawable)
.centerCrop()
)
.into(it)
}
gsyVideoPlayerOptionBuilder = GSYVideoOptionBuilder()
gsyVideoPlayerOptionBuilder
?.setUrl(mediaItem.localPath) // "/sdcard/mogo/media"
?.setThumbPlay(false)
?.build(adVideoPlayer)
adVideoPlayer?.isFocusableInTouchMode = false
adVideoPlayer?.playTag = mediaItem.fileUrl
adVideoPlayer?.setVideoAllCallBack(playerCallback)
adVideoPlayer?.setCacheImageViewGone()
if(mediaItem.pausePosition>0){
CallerLogger.d(TAG,"滑动到指定位置")
adVideoPlayer?.seekOnStart = (mediaItem.pausePosition)
}
adVideoPlayer?.startPlayLogic()
} catch (e: Exception) {
Logger.e(TAG, "startPlay error, msg=${e.message}")
playerCallback.onPlayError(mediaItem.localPath)
}
}
override fun startPlayStationVideo(stationMediaItem: MediaItem,adMediaItem:MediaItem?,playerCallback: GSYSampleCallBack) {
BizLoopManager.runInMainThread {
myStartPlayStationVideo(stationMediaItem, adMediaItem, playerCallback)
}
}
private fun myStartPlayStationVideo(stationMediaItem: MediaItem,adMediaItem:MediaItem?,playerCallback: GSYSampleCallBack) {
try {
if(adMediaItem?.isVideoType()==true&&adVideoPlayer?.playTag == adMediaItem.fileUrl){
adMediaItem.pausePosition = adVideoPlayer.currentPositionWhenPlaying
}
adVideoPlayer?.visibility = VISIBLE
imagePlayer?.visibility = GONE
adVideoPlayer?.onVideoReset()
thumbnailImageView?.also {
Glide.with(context).asBitmap().load(stationMediaItem.coverImageUrl)
.apply(
RequestOptions().useUnlimitedSourceGeneratorsPool(true)
.placeholder(placeholderDrawable)
.error(placeholderDrawable)
.fallback(placeholderDrawable)
.centerCrop()
)
.into(it)
}
gsyVideoPlayerOptionBuilder = GSYVideoOptionBuilder()
gsyVideoPlayerOptionBuilder
?.setUrl(stationMediaItem.localPath) // "/sdcard/mogo/media"
?.setThumbPlay(false)
?.build(adVideoPlayer)
adVideoPlayer?.isFocusableInTouchMode = false
adVideoPlayer?.playTag = stationMediaItem.fileUrl
adVideoPlayer?.setVideoAllCallBack(playerCallback)
adVideoPlayer?.setCacheImageViewGone()
adVideoPlayer?.startPlayLogic()
} catch (e: Exception) {
Logger.e(TAG, "startPlay error, msg=${e.message}")
playerCallback.onPlayError(stationMediaItem.localPath)
}
}
override fun pauseVideo() {
BizLoopManager.runInMainThread {
adVideoPlayer.onVideoPause()
}
}
override fun resumeVideo() {
BizLoopManager.runInMainThread {
adVideoPlayer.onVideoResume()
}
}
}

View File

@@ -0,0 +1,322 @@
package com.mogo.och.biz.media.video.ads
import androidx.lifecycle.ViewModel
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.utilcode.download.callback.IDownloadListener
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.FileUtils
import com.mogo.och.biz.media.MediaServiceManager
import com.mogo.och.biz.media.video.MediaDataSourceManager
import com.mogo.och.biz.media.video.MediaFileCacheManager
import com.mogo.och.biz.media.video.MediaPlayLogger
import com.mogo.och.common.module.biz.media.IVideoListener
import com.mogo.och.common.module.biz.media.data.MediaItem
import com.mogo.och.common.module.utils.RxUtils
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import io.reactivex.disposables.Disposable
/**
* @author XuXinChao
* @description BadCase录包管理页面
* @since: 2022/12/15
*/
class AdMediaViewModel : ViewModel(), IVideoListener {
private val TAG = M_OCHCOMMON + AdMediaViewModel::class.java.simpleName
private var viewCallback: AdMediaViewCallback? = null
private var adMediaList = mutableListOf<MediaItem>()
// 正在播放
private var currentPlayingIndex = 0
private var currentPlayingItem:MediaItem?=null
private var stationInfomation = mutableListOf<MediaItem>()
private var currentStationPlayingIndex = 0
private var currentStationPlayingItem:MediaItem?=null
private var playImageDisposable: Disposable? = null
// 播放监听 播放完一个再播放另一个
private var playerAdCallback = object : GSYSampleCallBack() {
override fun onPrepared(url: String?, vararg objects: Any?) {
CallerLogger.d(TAG, "onPrepared")
}
override fun onAutoComplete(url: String?, vararg objects: Any?) {
CallerLogger.d(TAG, "onAutoComplete")
currentPlayingItem?.pausePosition = 0
currentPlayingIndex++
startPlayerAds(currentPlayingIndex)
}
override fun onPlayError(url: String?, vararg objects: Any?) {
super.onPlayError(url, *objects)
CallerLogger.d(TAG, "onPlayError, error=${objects}")
playVideoError(url)
}
}
private fun playVideoError(url: String?) {
currentPlayingItem?.let {
if (FileUtils.isFileExists(it.localPath)) {
FileUtils.delete(it.localPath)
}
adMediaList.remove(it)
// 重新下载
downloadVideo(it)
startPlayerAds(currentPlayingIndex)
MediaPlayLogger.printInfoLog( "clearLocalErrorVideo, localPath=${it.fileUrl}")
}
}
override fun onCleared() {
MediaDataSourceManager.unInit()
MediaServiceManager.removeVideoListener(TAG)
}
fun setAdMediaCallback(viewCallback: AdMediaViewCallback) {
this.viewCallback = viewCallback
MediaServiceManager.invokeCreateCacheFileDir()
MediaServiceManager.addVideoListener(TAG,this)
MediaDataSourceManager.init()
}
override fun setMediaPause() {
super.setMediaPause()
if (currentPlayingItem?.isImageType()==true) {
RxUtils.disposeSubscribe(playImageDisposable)
}else{
this.viewCallback?.pauseVideo()
}
}
override fun setMediaResume() {
super.setMediaResume()
if (currentPlayingItem?.isImageType()==true) {
startPlayerAds(currentPlayingIndex)
}else{
this.viewCallback?.resumeVideo()
}
}
/**
* 分发广告数据
*/
override fun onMediaDataSourceChanged(list: List<MediaItem>) {
// 图片直接加入播放列表 视频检查是否缓存成功 没有缓存先缓存 缓存完再进行播放
CallerLogger.d(TAG,"收到数据-${list}")
val templateList = mutableListOf<MediaItem>()
val app = AbsMogoApplication.getApp()
list.forEach {
when (it.fileType) {
MediaItem.MEDIA_TYPE_IMAGE-> {
templateList.add(it)
// 预加载图片到磁盘缓存(指定尺寸)
Glide.with(AbsMogoApplication.getApp())
.load(it.fileUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.preload()
}
MediaItem.MEDIA_TYPE_VIDEO -> {
val localCachePath = MediaFileCacheManager.getCacheFileFullPathByUrl(app, it.fileUrl)
MediaPlayLogger.printInfoLog("本地已经有缓存文件可以直接放入列表videoPath=${localCachePath}")
it.localPath = localCachePath
if (!FileUtils.isFileExists(localCachePath)) {
downloadVideo(it)
// 去下载
return@forEach
}
templateList.add(it)
}
else -> {}
}
}
adMediaList = templateList
startPlayerAds(0)
}
private fun startPlayerAds(index:Int) {
if(adMediaList.isNotEmpty()) {
if (index < adMediaList.size) {
currentPlayingIndex = index
currentPlayingItem = adMediaList[index].also {
if (it.isImageType()) {
viewCallback?.startPlayImage(it)
RxUtils.disposeSubscribe(playImageDisposable)
playImageDisposable = RxUtils.createSubscribe(5_000) {
currentPlayingIndex++
startPlayerAds(currentPlayingIndex)
}
}
if (it.isVideoType()) {
viewCallback?.startPlayVideo(it, playerAdCallback)
}
}
} else {
// 循环
startPlayerAds(0)
}
}
}
private fun downloadVideo(it: MediaItem) {
Logger.d(TAG, "startDownLoadVideoFile, downloadUrl=${it.fileUrl}")
MediaPlayLogger.printInfoLog( "startDownLoadVideoFile, downloadUrl=${it.fileUrl}")
MediaFileCacheManager.downloadFile(it.fileUrl, object : IDownloadListener {
override fun onStart(url: String) {
Logger.d(TAG, "video play download, onStart ${it.title}")
MediaPlayLogger.printInfoLog( "startDownLoadVideoFile 开始下载, downloadUrl=${it.title}")
}
override fun onProgress(url: String, downloaded: Long, total: Long) {
val percent = (downloaded * 100 / total).toInt()
if (percent % 10 == 0) {
MediaPlayLogger.printInfoLog("downListenerpercent=$percent, downloadUrl=${it.title}")
}
}
override fun onFinished(url: String, path: String) {
Logger.d(TAG, "video play download, onFinished = $url")
//发现下载工具在断网又连网后,已完成的任务又都下载,跳转播放出现问题
CallerLogger.d(TAG,"下载成功 ${it.fileUrl==url}----${path==it.localPath}")
if (url == it.fileUrl && path == it.localPath) {
Logger.d(TAG, "下载成功 放入列表,$url---${path}")
//下载完成
synchronized(adMediaList){
if (!adMediaList.contains(it)) {
adMediaList.add(it)
}
}
}
}
override fun onError(url: String, error: String?) {
Logger.d(TAG, "video play download, onError msg=$error")
MediaPlayLogger.printErrorLog("download error, 准备重新下载downloadUrl=${url}")
}
})
}
// 播放监听 播放完一个再播放另一个
private var playerStationCallback = object : GSYSampleCallBack() {
override fun onPrepared(url: String?, vararg objects: Any?) {
CallerLogger.d(TAG, "onPrepared")
}
override fun onAutoComplete(url: String?, vararg objects: Any?) {
CallerLogger.d(TAG, "onAutoComplete")
currentStationPlayingIndex++
startPlayeStation(currentStationPlayingIndex)
}
override fun onPlayError(url: String?, vararg objects: Any?) {
super.onPlayError(url, *objects)
CallerLogger.d(TAG, "onPlayError, error=${objects}")
currentStationPlayingItem?.let {
if (FileUtils.isFileExists(it.localPath)) {
FileUtils.delete(it.localPath)
}
// 重新下载 不播放
downloadStationVideo(it)
currentStationPlayingIndex++
startPlayeStation(currentStationPlayingIndex)
}
}
}
/**
* 插播站点介绍视频广告
*/
override fun diapatchMedia(list: MutableList<MediaItem>) {
CallerLogger.d(TAG,"收到数据-${list}")
if(list.isEmpty()){
return
}
// 开始插播
if(currentPlayingItem?.isImageType()==true){
RxUtils.disposeSubscribe(playImageDisposable)
}
val templateList = mutableListOf<MediaItem>()
val app = AbsMogoApplication.getApp()
list.forEach {
val localCachePath = MediaFileCacheManager.getCacheFileFullPathByUrl(app, it.fileUrl)
MediaPlayLogger.printInfoLog("本地已经有缓存文件可以直接放入列表videoPath=${localCachePath}")
it.localPath = localCachePath
if (!FileUtils.isFileExists(localCachePath)) {
downloadStationVideo(it)
// 去下载
return@forEach
}
templateList.add(it)
}
stationInfomation = templateList
startPlayeStation(0)
}
private fun startPlayeStation(index: Int) {
if(stationInfomation.isNotEmpty()) {
if (index < stationInfomation.size) {
currentStationPlayingIndex = index
currentStationPlayingItem = stationInfomation[index].also {
viewCallback?.startPlayStationVideo(it, currentPlayingItem,playerStationCallback)
}
} else {
// 回复播放广告
currentStationPlayingIndex = 0
currentStationPlayingItem = null
startPlayerAds(currentPlayingIndex)
}
}
}
private fun downloadStationVideo(it: MediaItem) {
Logger.d(TAG, "startDownLoadVideoFile, downloadUrl=${it.fileUrl}")
MediaPlayLogger.printInfoLog( "startDownLoadVideoFile, downloadUrl=${it.fileUrl}")
MediaFileCacheManager.downloadFile(it.fileUrl, object : IDownloadListener {
override fun onStart(url: String) {
Logger.d(TAG, "video play download, onStart ${it.title}")
MediaPlayLogger.printInfoLog( "startDownLoadVideoFile 开始下载, downloadUrl=${it.title}")
}
override fun onProgress(url: String, downloaded: Long, total: Long) {
val percent = (downloaded * 100 / total).toInt()
if (percent % 10 == 0) {
MediaPlayLogger.printInfoLog("downListenerpercent=$percent, downloadUrl=${it.title}")
}
}
override fun onFinished(url: String, path: String) {
Logger.d(TAG, "video play download, onFinished = $url")
//发现下载工具在断网又连网后,已完成的任务又都下载,跳转播放出现问题
CallerLogger.d(TAG,"下载成功 ${it.fileUrl==url}----${path==it.localPath}")
}
override fun onError(url: String, error: String?) {
Logger.d(TAG, "video play download, onError msg=$error")
MediaPlayLogger.printErrorLog("download error, 准备重新下载downloadUrl=${url}")
}
})
}
interface AdMediaViewCallback {
fun startPlayImage(it: MediaItem)
fun startPlayVideo(it: MediaItem, playerCallback: GSYSampleCallBack)
fun startPlayStationVideo(stationMediaItem: MediaItem,adMediaItem: MediaItem?, playerCallback: GSYSampleCallBack)
fun pauseVideo()
fun resumeVideo()
}
}

View File

@@ -0,0 +1,197 @@
package com.mogo.och.biz.media.video.ads
import android.content.Context
import android.media.AudioManager
import android.text.TextUtils
import android.util.AttributeSet
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.widget.media.video.CustomManager
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.och.biz.media.video.MediaLoopPlayView
import com.mogo.och.common.module.biz.media.MediaManager
import com.shuyu.gsyvideoplayer.utils.Debuger
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import me.jessyan.autosize.utils.AutoSizeUtils
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge as GSYVideoViewBridge1
class AdVideoPlayer : StandardGSYVideoPlayer {
companion object {
const val TAG = "AdVideoPlayer"
}
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
init {
hideWidget()
GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL)
GSYVideoType.setRenderType(GSYVideoType.GLSURFACE)
}
override fun init(context: Context) {
super.init(context)
onAudioFocusChangeListener =
AudioManager.OnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {}
AudioManager.AUDIOFOCUS_LOSS -> {
//todo 判断如果不是外界造成的就不处理
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
//todo 判断如果不是外界造成的就不处理
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {}
}
}
}
override fun getGSYVideoManager(): GSYVideoViewBridge1 {
CustomManager.getCustomManager(key).initContext(context.applicationContext)
return CustomManager.getCustomManager(key)
}
override fun backFromFull(context: Context): Boolean {
return CustomManager.backFromWindowFull(context, key)
}
override fun releaseVideos() {
CustomManager.releaseAllVideos(key)
}
override fun getFullId(): Int {
return CustomManager.FULLSCREEN_ID
}
override fun getSmallId(): Int {
return CustomManager.SMALL_ID
}
override fun hideAllWidget() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerhideAllWidget")
}
override fun changeUiToNormal() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToNormal-hide")
hideWidget()
}
override fun changeUiToPreparingShow() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToPreparingShow-hide")
hideWidget()
}
override fun changeUiToPlayingShow() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToPlayingShow")
setCacheImageViewGone()
}
override fun changeUiToPauseShow() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToPauseShow-hide")
// startPlayLogic()
}
override fun changeUiToCompleteShow() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToCompleteShow")
setCacheImageViewGone()
}
override fun changeUiToPlayingBufferingShow() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToPlayingBufferingShow")
hideWidget()
}
override fun changeUiToError() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayerchangeUiToError")
hideWidget()
}
private fun hideWidget() {
setViewShowState(mBottomContainer, INVISIBLE)
setViewShowState(mProgressBar, INVISIBLE)
setViewShowState(mCurrentTimeTextView, INVISIBLE)
setViewShowState(mTotalTimeTextView, INVISIBLE)
setViewShowState(mBottomProgressBar, INVISIBLE)
setViewShowState(mBackButton, INVISIBLE)
setViewShowState(mStartButton, INVISIBLE)
setViewShowState(mThumbImageViewLayout, VISIBLE)
setViewShowState(mThumbImageView, VISIBLE)
setViewShowState(mTopContainer, INVISIBLE)
setViewShowState(mLoadingProgressBar, INVISIBLE)
setViewShowState(mLockScreen, INVISIBLE)
setIsTouchWiget(false)
isFocusableInTouchMode = false
}
private var oldPlaying = false
override fun setStateAndUi(state: Int) {
super.setStateAndUi(state)
Logger.d("AdVideoPlayer", "播放状态 $state")
val playing = state == GSYVideoView.CURRENT_STATE_PLAYING
if (oldPlaying != playing) {
oldPlaying = playing
MediaManager.setVideoFocusChange(playing)
}
}
fun setCacheImageViewVisible() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayersetCacheImageViewVisible")
setViewShowState(mThumbImageViewLayout, VISIBLE)
// setViewShowState(mThumbImageView, VISIBLE)
}
fun setCacheImageViewGone() {
Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayersetCacheImageViewGone")
setViewShowState(mThumbImageViewLayout, INVISIBLE)
// setViewShowState(mThumbImageView, INVISIBLE)
}
//失去焦点声音压低
override fun onLossTransientCanDuck() {
// setStreamVolume(0.2f)
setNeedMute(true)
}
//获取焦点声音恢复
override fun onGankAudio() {
// setStreamVolume(5.0f)
setNeedMute(false)
}
private fun setStreamVolume(percent: Float) {
var mAudioManager = mContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
var maxVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
var volume = (percent * maxVolume).toInt()
if (volume < 0) {
volume = 0
}
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0)
}
private fun setNeedMute(isMute: Boolean) {
gsyVideoManager?.player?.setNeedMute(isMute)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (!mIfCurrentIsFullscreen) {
val dp2px = AutoSizeUtils.dp2px(context, 16f)
this.outlineProvider = TextureVideoViewOutlineProvider(dp2px.toFloat())
this.clipToOutline = true
}
}
private val key: String
get() {
if (mPlayPosition == -22) {
Debuger.printfError(javaClass.simpleName + " used getKey() " + "******* PlayPosition never set. ********")
}
if (TextUtils.isEmpty(mPlayTag)) {
Debuger.printfError(javaClass.simpleName + " used getKey() " + "******* PlayTag never set. ********")
}
return TAG + mPlayPosition + mPlayTag
}
}

View File

@@ -0,0 +1,53 @@
package com.mogo.och.biz.routing
import android.content.Context
import android.view.View
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.biz.routing.ui.RoutingSwitchView
import com.mogo.och.common.module.biz.routing.RoutingCallback
import com.mogo.och.common.module.biz.routing.RoutingService
import com.mogo.och.common.module.constant.OchCommonConst
@Route(path = OchCommonConst.BIZ_ROUTING)
class RoutingProvider : RoutingService {
private var context: Context? = null
private val TAG = M_OCHCOMMON + "RoutingProvider"
private var switchView:RoutingSwitchView?=null
private var callback:RoutingCallback?=null
override fun getRoutingView(): View? {
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
context?.let {
if(switchView==null){
switchView = RoutingSwitchView(it)
}
return switchView
}
}
return null
}
override fun setRoutingCallback(callback: RoutingCallback?) {
this.callback = callback
}
override fun init(context: Context?) {
this.context = context
}
fun invokeCallbackShowMap(isShow: Boolean) {
this.callback?.showMap(isShow)
}
}

View File

@@ -0,0 +1,19 @@
package com.mogo.och.biz.routing
import android.annotation.SuppressLint
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.och.common.module.constant.OchCommonConst
object RoutingServiceManager {
@SuppressLint("StaticFieldLeak")
private var routingService: RoutingProvider? =
ARouter.getInstance().build(OchCommonConst.BIZ_ROUTING).navigation() as RoutingProvider
fun invokeCallback(isShow: Boolean) {
this.routingService?.invokeCallbackShowMap(isShow)
}
}

View File

@@ -1,8 +1,9 @@
package com.mogo.och.unmanned.taxi.bean
package com.mogo.och.biz.routing.bean
import com.mogo.eagle.core.data.BaseData
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.data.bean.ContraiInfo
import com.mogo.och.data.bean.LineInfo
/**
* 灰度路线信息
@@ -16,7 +17,9 @@ data class GrayLineBean(
var lineFailCount: Int?, //线路累计反馈不可用次数
var isChoosed: Boolean = false, //当前是否选中
var startSite: RoutingSite?,
var endSite: RoutingSite?
var endSite: RoutingSite?,
var allStation:MutableList<RoutingSite>?=null,
var distance:Float,
)
/**
@@ -29,7 +32,6 @@ data class RoutingSite(
var gcjLon: Double,// 高德坐标
var wgs84Lon: Double,//高精坐标
var wgs84Lat: Double,//高精坐标
var pointType: Int // 1:途径点 2:禁行点 3:站点
) {
fun toBusStationBean(): BusStationBean {
val temp = BusStationBean()
@@ -39,7 +41,6 @@ data class RoutingSite(
temp.lon = wgs84Lon
temp.gcjLat = gcjLat
temp.gcjLon = gcjLon
temp.pointType = pointType
temp.isLeaving = true
return temp
}
@@ -49,36 +50,65 @@ data class RoutingSite(
* 轨迹信息
*/
data class ContrailBean(
var businessType:Int=0,
var contrailId: Long = -1L,
var contrailSaveTime: Long = -1L,
var csvFileMd5: String = "",
var csvFileUrl: String = "",
var lineId: Long = -1L,
var lineName: String = "",
var contrailId: Long = -1L,
var csvFileUrl: String = "",
var csvFileMd5: String = "",
var txtFileUrl: String = "",
var segmentPointList:MutableList<PointInfoGroup> = mutableListOf(),
var txtFileMd5: String = "",
var contrailSaveTime: Long = -1L,
var csvFileUrlDPQP: String = "",
var csvFileMd5DPQP: String = "",
var txtFileUrlDPQP: String = "",
var txtFileMd5DPQP: String = "",
var contrailSaveTimeDPQP: Long = -1L,
var version: Long = -1L,
var passPoints: MutableList<RoutingSite>?, // 用于算路的经停点
var blackPoints: MutableList<RoutingSite>?, // 用于算路的黑名單點
var txtFileUrl: String = "",
) {
fun toContraiInfo(): ContraiInfo {
val tempPassPoints = mutableListOf<BusStationBean>()
passPoints?.forEach {
tempPassPoints.add(it.toBusStationBean())
}
val tempblackPoints = mutableListOf<BusStationBean>()
blackPoints?.forEach {
tempPassPoints.add(it.toBusStationBean())
segmentPointList.forEach {
for (pointInfo in it.blackList) {
tempblackPoints.add(pointInfo.toBusStationBean())
}
for (pointInfo in it.pointList) {
tempPassPoints.add(pointInfo.toBusStationBean())
}
}
return ContraiInfo(lineId,csvFileUrl,csvFileMd5,txtFileUrl,txtFileMd5,contrailSaveTime,tempPassPoints,tempblackPoints)
return ContraiInfo(lineId,csvFileUrl,csvFileMd5,txtFileUrl,txtFileMd5,contrailSaveTime,tempPassPoints,tempblackPoints, 2)
}
fun getPassAndBlackPoint(index: Int): Pair<MutableList<BusStationBean>, MutableList<BusStationBean>> {
val tempPassPoints = mutableListOf<BusStationBean>()
val tempblackPoints = mutableListOf<BusStationBean>()
segmentPointList.forEach {
if(it.segment==index){
for (pointInfo in it.blackList) {
tempblackPoints.add(pointInfo.toBusStationBean())
}
for (pointInfo in it.pointList) {
tempPassPoints.add(pointInfo.toBusStationBean())
}
return Pair(tempPassPoints,tempblackPoints)
}
}
return Pair(tempPassPoints,tempblackPoints)
}
}
data class PointInfoGroup(var blackList:MutableList<PointInfo>,//用于算路的黑名單點
var pointList:MutableList<PointInfo>,//用于算路的经停点
var segment:Int)
data class PointInfo(var latitude:Double,var longitude:Double,var pointType:Int,var segment:Int) {
fun toBusStationBean(): BusStationBean {
val temp = BusStationBean()
temp.lat = latitude
temp.lon = longitude
temp.pointType = pointType
temp.isLeaving = true
return temp
}
}
/**
* 查询灰度线路列表
*/
@@ -87,7 +117,7 @@ data class QueryGrayContrailListRsp(var data: MutableList<GrayLineBean>?) : Base
/**
* 通过id查询轨迹详情
*/
data class StartGrayContrailTaskReq(var sn: String, var contrailId: Long)
data class StartGrayContrailTaskReq(var sn: String, var contrailId: Long, var driverId: Long)
/**
* 开始一个路线的灰度任务对服务端的路线标记
@@ -99,11 +129,6 @@ data class StartGrayContrailTaskRsp(var data: Long?) : BaseData()
*/
data class QueryRoutingContrailByIdRsp(var data: ContrailBean?) : BaseData()
/**
* 上报路线打点
*/
data class SubmitGrayLineIssueLocationReq(var grayId: Long, var gcjLon: Double, var gcjLat: Double)
/**
* 结束一个路线的灰度任务
*/
@@ -113,14 +138,14 @@ data class EndGrayContrailTaskReq(
var occurrenceTime: Long
) //feedback 1:成功 2:失败
/**
* 灰度任务&查询轨迹详情
*/
data class StartGrayAndQueryContrailRsp(
var taskId: Long?,
var contrail: ContrailBean?,
var grayLineBean: GrayLineBean
var grayLineBean: GrayLineBean,
var stationList: MutableList<BusStationBean>
) : BaseData()
data class PointError(var code: String, var name: String, var isCheck: Boolean = false)
@@ -140,13 +165,35 @@ data class SaveGrayContrailErrorReasons(
var wgs84Lon: Double,
var wgs84Lat: Double,
var occurrenceTime: Long,
var plateNumber: String,
var driverId: Long,
var noteCodes: MutableList<String>,
) //feedback 1:成功 2:失败
/**
* 小巴接驳班车 获取站点的参数
*/
data class QuerySitesReasons(
var lineId: Long, // 线路id
var businessType: Int,// 业务模式
)
enum class EndGrayTaskFeedbackType(var type: Int) {
USABLE_YES(1),
USABLE_NO(2)
}
data class BindLineListResponse(val data: List<Result>?) : BaseData() {
data class Result(
var line: LineInfo?,
var siteList: List<BusStationBean>?,//站点名称
)
}
data class SitesInfo(val data: List<RoutingSite>?) : BaseData()

View File

@@ -1,16 +1,17 @@
package com.mogo.och.unmanned.taxi.network
package com.mogo.och.biz.routing.net
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.BaseData
import com.mogo.och.unmanned.taxi.bean.EndGrayContrailTaskReq
import com.mogo.och.unmanned.taxi.bean.QueryGrayContrailListRsp
import com.mogo.och.unmanned.taxi.bean.QueryPointErrorReasonsRsp
import com.mogo.och.unmanned.taxi.bean.QueryRoutingContrailByIdRsp
import com.mogo.och.unmanned.taxi.bean.SaveGrayContrailErrorReasons
import com.mogo.och.unmanned.taxi.bean.StartGrayContrailTaskReq
import com.mogo.och.unmanned.taxi.bean.StartGrayContrailTaskRsp
import com.mogo.och.unmanned.taxi.bean.SubmitGrayLineIssueLocationReq
import com.mogo.och.biz.routing.bean.BindLineListResponse
import com.mogo.och.biz.routing.bean.QueryGrayContrailListRsp
import com.mogo.och.biz.routing.bean.QueryPointErrorReasonsRsp
import com.mogo.och.biz.routing.bean.QueryRoutingContrailByIdRsp
import com.mogo.och.biz.routing.bean.QuerySitesReasons
import com.mogo.och.biz.routing.bean.SaveGrayContrailErrorReasons
import com.mogo.och.biz.routing.bean.SitesInfo
import com.mogo.och.biz.routing.bean.StartGrayContrailTaskReq
import com.mogo.och.biz.routing.bean.StartGrayContrailTaskRsp
import io.reactivex.Observable
import retrofit2.http.Body
import retrofit2.http.GET
@@ -19,13 +20,13 @@ import retrofit2.http.Headers
import retrofit2.http.POST
import retrofit2.http.Query
interface TaxiRoutingServiceApi {
interface RoutingServiceApi {
/**
* 查询灰度线路列表
*/
@Headers("Content-type:application/json;charset=UTF-8")
@GET("/och-taxi-cabin/api/business/v1/queryGrayContrailList")
@GET("/och-contrail/contrail/queryGrayContrailList")
fun queryRoutingGrayLineList(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@@ -36,7 +37,7 @@ interface TaxiRoutingServiceApi {
* 开始一个路线的灰度任务
*/
@Headers("Content-type:application/json;charset=UTF-8")
@POST("/och-taxi-cabin/api/business/v1/startGray")
@POST("/och-contrail/grayFeedback/saveFeedback")
fun startGrayTask(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@@ -44,36 +45,26 @@ interface TaxiRoutingServiceApi {
): Observable<StartGrayContrailTaskRsp>
/**
* 根据id查询灰度轨迹详情
* 根据轨迹id查询轨迹信息
*/
@Headers("Content-type:application/json;charset=UTF-8")
@GET("/och-taxi-cabin/api/business/v1/gray/contrail")
@GET("/och-contrail/contrail/queryCabinContrailById")
fun queryRoutingContrailById(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Query("id") contrailId: Long
@Query("contrailId") contrailId: Long
): Observable<QueryRoutingContrailByIdRsp>
/**
* 上报路线打点
*/
@Headers("Content-type:application/json;charset=UTF-8")
@POST("/och-taxi-cabin/api/business/v1/saveDotDetail")
fun submitGrayLineIssueLocation(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Body data: SubmitGrayLineIssueLocationReq
): Observable<BaseData>
/**
* 结束一个路线的灰度任务
*/
@Headers("Content-type:application/json;charset=UTF-8")
@POST("/och-taxi-cabin/api/business/v1/endGray")
@GET("/och-contrail/grayFeedback/update")
fun endGrayTask(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Body data: EndGrayContrailTaskReq
@Query("id") id:Long,
@Query("feedback") feedback:Int,
): Observable<BaseData>
/**
@@ -90,10 +81,22 @@ interface TaxiRoutingServiceApi {
* 结束一个路线的灰度任务
*/
@Headers("Content-type:application/json;charset=UTF-8")
@POST("/och-taxi-cabin/api/business/v1/saveDotDetail")
@POST("/och-contrail/dotDetail/save")
fun saveDotDetail(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Body data: SaveGrayContrailErrorReasons
): Observable<BaseData>
@Headers("Content-type:application/json;charset=UTF-8")
@POST("/och-vehicle/api/line/querySiteListByLine")
fun querySiteListByLine(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Body data: QuerySitesReasons
): Observable<SitesInfo>
}

View File

@@ -0,0 +1,172 @@
package com.mogo.och.biz.routing.net
import android.content.Context
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.och.biz.routing.bean.EndGrayContrailTaskReq
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.QueryGrayContrailListRsp
import com.mogo.och.biz.routing.bean.QueryPointErrorReasonsRsp
import com.mogo.och.biz.routing.bean.QuerySitesReasons
import com.mogo.och.biz.routing.bean.SaveGrayContrailErrorReasons
import com.mogo.och.biz.routing.bean.SitesInfo
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.biz.routing.bean.StartGrayContrailTaskReq
import com.mogo.och.common.module.biz.login.LoginStatusManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.network.OchCommonSubscribeImpl
import com.mogo.och.common.module.network.interceptor.transformTry
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.weaknet.repository.db.exception.NetDataException
import io.reactivex.Observable
object RoutingServiceManager {
private var mRoutingServiceApi: RoutingServiceApi =
MoGoRetrofitFactory.getInstance(OchCommonConst.getBaseUrl()).create(
RoutingServiceApi::class.java
)
/**
* 查询灰度路线列表
*/
fun queryRoutingGrayLineList(
context: Context,
callback: OchCommonServiceCallback<QueryGrayContrailListRsp>
) {
mRoutingServiceApi.queryRoutingGrayLineList(
sn = SharedPrefsMgr.getInstance().sn
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryRoutingGrayLineList"))
}
/**
* 结束一个灰度任务
*/
fun endGrayTask(
context: Context,
data: EndGrayContrailTaskReq,
callback: OchCommonServiceCallback<BaseData>
) {
mRoutingServiceApi.endGrayTask(id = data.grayId, feedback = data.feedback).transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "endGrayTask"))
}
fun getErrorPointReasons(
context: Context,
callback: OchCommonServiceCallback<QueryPointErrorReasonsRsp>
) {
mRoutingServiceApi.getDotErrorList().transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "dot/list"))
}
fun saveDotDetail(
context: Context,
data: SaveGrayContrailErrorReasons,
callback: OchCommonServiceCallback<BaseData>
) {
mRoutingServiceApi.saveDotDetail(data = data).transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "dot/list"))
}
/**
* 标记灰度任务被启动验证
*/
fun startGrayTaskAndQueryRoutingContrail(
context: Context,
sn: String,
contrailId: Long,
grayLineBean: GrayLineBean,
callback: OchCommonServiceCallback<StartGrayAndQueryContrailRsp>
) {
val data = StartGrayContrailTaskReq(sn, contrailId ,LoginStatusManager.getOchLoginInfo()?.driverId?:0L)
val requestContral = mRoutingServiceApi.queryRoutingContrailById(contrailId = contrailId)
val startRouting = mRoutingServiceApi.startGrayTask(data = data)
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
||AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)
||AppIdentityModeUtils.isScheduled(FunctionBuildConfig.appIdentityMode)
) {
val request = QuerySitesReasons(grayLineBean.lineId?:0,
LoginStatusManager.getOchBizInfo()?.businessType?:11)
val querySites = mRoutingServiceApi.querySiteListByLine(data = request)
Observable.zip(requestContral,startRouting,querySites) { t1, t2, t3 ->
if ((t1.code != 0 && t1.code != 200) || t1.data == null) {
throw NetDataException(t1.code, "${t1.msg}_queryCabinContrailById")
}
if (t2.code != 0 && t2.code != 200 || t2.data == null) {
throw NetDataException(t2.code, "${t2.msg}_saveFeedback")
}
if (t3.code != 0 && t3.code != 200 || t3.data.isNullOrEmpty()) {
throw NetDataException(t3.code, "${t3.msg}_saveFeedback")
}
val stationList = mutableListOf<BusStationBean>()
t3.data.let { lineList->
lineList.forEach {
stationList.add(it.toBusStationBean())
}
}
val result = StartGrayAndQueryContrailRsp(
taskId = t2.data!!,
contrail = t1.data,
grayLineBean = grayLineBean,
stationList = stationList
)
result.code = t1.code
result.msg = t1.msg
result
}.transformTry()
.subscribe(
OchCommonSubscribeImpl(
context,
callback,
"startGrayTaskAndQueryRoutingContrail"
)
)
}else if(AppIdentityModeUtils.isTaxi(FunctionBuildConfig.appIdentityMode)){
Observable.zip(requestContral,startRouting) { t1, t2 ->
if ((t1.code != 0 && t1.code != 200)||t1.data==null) {
throw NetDataException(t1.code,"${t1.msg}_queryCabinContrailById")
}
if (t2.code != 0 && t2.code != 200||t2.data==null) {
throw NetDataException(t2.code,"${t2.msg}_saveFeedback")
}
val stationList = mutableListOf<BusStationBean>()
grayLineBean.startSite?.toBusStationBean()?.let {
stationList.add(it)
}
grayLineBean.endSite?.toBusStationBean()?.let {
stationList.add(it)
}
val result = StartGrayAndQueryContrailRsp(
taskId = t2.data!!,
contrail = t1.data,
grayLineBean = grayLineBean,
stationList = stationList
)
result.code = t1.code
result.msg = t1.msg
result
}.transformTry()
.subscribe(
OchCommonSubscribeImpl(
context,
callback,
"startGrayTaskAndQueryRoutingContrail"
)
)
}
}
fun querySiteListByList(request: QuerySitesReasons): Observable<SitesInfo> {
return mRoutingServiceApi.querySiteListByLine(data = request)
}
}

View File

@@ -1,8 +1,8 @@
package com.mogo.och.unmanned.taxi.ui.routing
package com.mogo.och.biz.routing.ui
import androidx.lifecycle.ViewModel
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
/**
* @author XuXinChao

View File

@@ -1,21 +1,25 @@
package com.mogo.och.unmanned.taxi.ui.routing
package com.mogo.och.biz.routing.ui
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.commons.module.status.MogoStatusManager
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.TaxiUnmannedDriverProvider
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import kotlinx.android.synthetic.main.unmanned_routing_switch.view.routingRunningView
import kotlinx.android.synthetic.main.unmanned_routing_switch.view.routingSelectView
import kotlinx.android.synthetic.main.unmanned_routing_switch.view.switch_routing_loading
import com.mogo.och.common.module.utils.RxUtils
import kotlinx.android.synthetic.main.biz_taxi_switch.view.routingOtherRunningView
import kotlinx.android.synthetic.main.biz_taxi_switch.view.routingSelectView
import kotlinx.android.synthetic.main.biz_taxi_switch.view.routingTaxiRunningView
import kotlinx.android.synthetic.main.biz_taxi_switch.view.switch_routing_loading
class RoutingSwitchView: ConstraintLayout, RoutingSwitchModel.SwtichLineViewCallback {
@@ -35,17 +39,17 @@ class RoutingSwitchView: ConstraintLayout, RoutingSwitchModel.SwtichLineViewCall
private var viewModel: RoutingSwitchModel?=null
private var fragment: LifecycleOwner?=null
private var data: StartGrayAndQueryContrailRsp?=null
init {
LayoutInflater.from(context).inflate(R.layout.unmanned_routing_switch, this, true)
LayoutInflater.from(context).inflate(R.layout.biz_taxi_switch, this, true)
initView()
initEventBus()
}
private fun initView(){
fragment = TaxiUnmannedDriverProvider.getFragmentInfo()
switch_routing_loading.setEmptyText(ResourcesUtils.getString(R.string.common_biz_loading))
}
@@ -57,7 +61,15 @@ class RoutingSwitchView: ConstraintLayout, RoutingSwitchModel.SwtichLineViewCall
super.onVisibilityAggregated(isVisible)
if(isVisible){
showLoadingView()
showRoutingSelectView()
if (MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingPerformTask) {
if(data!=null){
showRoutingRunning(data!!)
}else{
showRoutingSelectView()
}
}else {
showRoutingSelectView()
}
}
}
@@ -67,39 +79,63 @@ class RoutingSwitchView: ConstraintLayout, RoutingSwitchModel.SwtichLineViewCall
override fun showLoadingView(){
startLoading = System.currentTimeMillis()
routingSelectView.visibility = GONE
routingRunningView.visibility = GONE
routingTaxiRunningView.visibility = GONE
routingOtherRunningView.visibility = GONE
switch_routing_loading.visibility = VISIBLE
}
override fun showRoutingSelectView() {
this.data = null
val endLoading = System.currentTimeMillis()
val dex = (100-(endLoading - startLoading)).takeIf { it>=0 }?:0
CallerLogger.d(TAG,"展示选择线路 lading 展示了 ${dex}毫秒")
ThreadUtils.runOnUiThreadDelayed({
routingSelectView.visibility = VISIBLE
routingRunningView.visibility = GONE
routingTaxiRunningView.visibility = GONE
routingOtherRunningView.visibility = GONE
switch_routing_loading.visibility = GONE
},dex, ThreadUtils.MODE.QUEUE)
}
override fun showRoutingRunning(data: StartGrayAndQueryContrailRsp) {
this.data = data
val endLoading = System.currentTimeMillis()
val dex = (100-(endLoading - startLoading)).takeIf { it>=0 }?:0
CallerLogger.d(TAG,"展示线路 lading 展示了 ${dex}毫秒")
ThreadUtils.runOnUiThreadDelayed({
OchChainLogManager.writeChainLogRouting("展示线路:","延时${dex}ms")
RxUtils.createSubscribe(dex) {
OchChainLogManager.writeChainLogRouting("展示线路:","信息:$data")
routingSelectView.visibility = GONE
routingRunningView.visibility = VISIBLE
switch_routing_loading.visibility = GONE
routingRunningView.setData(data)
},dex, ThreadUtils.MODE.QUEUE)
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
|| AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)
|| AppIdentityModeUtils.isScheduled(FunctionBuildConfig.appIdentityMode)
) {
routingTaxiRunningView.visibility = GONE
routingOtherRunningView.visibility = VISIBLE
routingOtherRunningView.setData(data)
}else if(AppIdentityModeUtils.isTaxi(FunctionBuildConfig.appIdentityMode)){
routingTaxiRunningView.visibility = VISIBLE
routingOtherRunningView.visibility = GONE
routingTaxiRunningView.setData(data)
}
}
}
override fun onAttachedToWindow() {
CallerLogger.d(TAG,"onAttachedToWindow")
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingSwitchModel::class.java)
}
viewModel?.setDistanceCallback(this)
data = null
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerLogger.d(TAG,"onDetachedFromWindow")
data = null
}
}

View File

@@ -1,16 +1,15 @@
package com.mogo.och.unmanned.taxi.ui.routing.errorpoint
package com.mogo.och.biz.routing.ui.errorpoint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.PointError
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.bean.PointError
import me.jessyan.autosize.AutoSizeCompat
/**
@@ -40,7 +39,7 @@ class ErrorPointItemAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextVH {
val view: View
val inflater = LayoutInflater.from(context)
view = inflater.inflate(R.layout.taxt_report_error_point_item, parent, false)
view = inflater.inflate(R.layout.biz_taxi_report_error_point_item, parent, false)
return TextVH(view)
}
@@ -48,9 +47,9 @@ class ErrorPointItemAdapter(
val errorInfo = dataList[holder.bindingAdapterPosition]
AutoSizeCompat.autoConvertDensityOfGlobal(holder.itemView.resources)
if (errorInfo.isCheck) {
holder.cbErrorInfo.setImageResource(R.drawable.taxi_routing_check)
holder.cbErrorInfo.setImageResource(R.drawable.biz_taxi_routing_check)
}else{
holder.cbErrorInfo.setImageResource(R.drawable.taxi_routing_uncheck)
holder.cbErrorInfo.setImageResource(R.drawable.biz_taxi_uncheck)
}
holder.cbErrorResong.text = errorInfo.name
holder.itemView.onClick {

View File

@@ -1,29 +1,25 @@
package com.mogo.och.unmanned.taxi.ui.routing.errorpoint
package com.mogo.och.biz.routing.ui.errorpoint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.flexbox.AlignItems
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.bean.PointError
import com.mogo.och.common.module.wigets.WindowRelativeLayout
import com.mogo.och.common.module.wigets.dialog.CommonDialogView
import com.mogo.och.common.module.wigets.dialog.CommonFeedbackDialog
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.PointError
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.lvs_loding
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.rvErrorPointReason
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.tv_report_error_point_reason
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.tv_report_error_point_reason_cancel
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.tv_work_order_time
import kotlinx.android.synthetic.main.biz_taxi_report_error_point_panel.view.rvErrorPointReason
import kotlinx.android.synthetic.main.biz_taxi_report_error_point_panel.view.lvs_loding
import kotlinx.android.synthetic.main.biz_taxi_report_error_point_panel.view.tv_report_error_point_reason
import kotlinx.android.synthetic.main.biz_taxi_report_error_point_panel.view.tv_report_error_point_reason_cancel
import kotlinx.android.synthetic.main.biz_taxi_report_error_point_panel.view.tv_work_order_time
/**
*
@@ -78,7 +74,7 @@ class ReportErrorPointView : WindowRelativeLayout,
private fun initView() {
d(SceneConstant.M_TAXI_P + TAG, "initView")
LayoutInflater.from(context).inflate(R.layout.taxt_report_error_point_panel, this, true)
LayoutInflater.from(context).inflate(R.layout.biz_taxi_report_error_point_panel, this, true)
rvErrorPointReason?.layoutManager = GridLayoutManager(context, 2)
rvErrorPointReason?.setHasFixedSize(true)

View File

@@ -1,16 +1,17 @@
package com.mogo.och.unmanned.taxi.ui.routing.errorpoint
package com.mogo.och.biz.routing.ui.errorpoint
import androidx.lifecycle.ViewModel
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.biz.routing.bean.PointError
import com.mogo.och.biz.routing.bean.QueryPointErrorReasonsRsp
import com.mogo.och.biz.routing.bean.SaveGrayContrailErrorReasons
import com.mogo.och.biz.routing.net.RoutingServiceManager
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.common.module.biz.login.LoginStatusManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.unmanned.taxi.bean.PointError
import com.mogo.och.unmanned.taxi.bean.QueryPointErrorReasonsRsp
import com.mogo.och.unmanned.taxi.bean.SaveGrayContrailErrorReasons
import com.mogo.och.unmanned.taxi.network.TaxiRoutingServiceManager
class ReportErrorPointViewModel : ViewModel() {
@@ -30,7 +31,7 @@ class ReportErrorPointViewModel : ViewModel() {
}
fun getPointErrorReasons(){
TaxiRoutingServiceManager.getErrorPointReasons(
RoutingServiceManager.getErrorPointReasons(
AbsMogoApplication.getApp(),
object : OchCommonServiceCallback<QueryPointErrorReasonsRsp> {
override fun onSuccess(data: QueryPointErrorReasonsRsp?) {
@@ -70,6 +71,7 @@ class ReportErrorPointViewModel : ViewModel() {
checkDataList.forEach {pointError->
errorReasonCodes.add(pointError.code)
}
val saveGrayContrailErrorReasons = SaveGrayContrailErrorReasons(
it,
gcj02.longitude,
@@ -77,9 +79,11 @@ class ReportErrorPointViewModel : ViewModel() {
wgs84.longitude,
wgs84.latitude,
occurrenceTime,
LoginStatusManager.getOchCarInfo()?.plateNumber?:"",
LoginStatusManager.getOchLoginInfo()?.driverId?:0L,
errorReasonCodes
)
TaxiRoutingServiceManager.saveDotDetail(
RoutingServiceManager.saveDotDetail(
AbsMogoApplication.getApp(),
saveGrayContrailErrorReasons,
object : OchCommonServiceCallback<BaseData> {

View File

@@ -1,6 +1,9 @@
package com.mogo.och.unmanned.taxi.ui.routing.routingselect
package com.mogo.och.biz.routing.ui.routingselect
import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -8,10 +11,13 @@ import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.DiffUtil.Callback
import androidx.recyclerview.widget.RecyclerView
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.GrayLineBean
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.SitesInfo
import com.mogo.och.common.module.utils.ResourcesUtils
import me.jessyan.autosize.AutoSizeCompat
/**
* 路线列表adapter
*/
@@ -25,7 +31,11 @@ class RoutingItemAdapter(
// RecyclerView设置点击事件
private var mItemClickListener: LineItemClickListener? = null
private val middleCOlor =ResourcesUtils.getColor(R.color.biz_routing_2eacff)
private val allCOlor =ResourcesUtils.getColor(R.color.color_FFFFFF)
fun setDataList(dataList: List<GrayLineBean>) {
if (this.mData == dataList) {
// 如果新旧列表一致,则直接返回
return
@@ -42,7 +52,7 @@ class RoutingItemAdapter(
viewType: Int
): RoutingItemViewHolder {
val view = LayoutInflater.from(mContext).inflate(
R.layout.unmanned_routing_select_item, parent, false
R.layout.biz_taxi_select_item, parent, false
)
return RoutingItemViewHolder(view)
}
@@ -51,10 +61,39 @@ class RoutingItemAdapter(
val currentPosition = holder.bindingAdapterPosition
val routing = mData[currentPosition]
AutoSizeCompat.autoConvertDensityOfGlobal(holder.itemView.resources)
holder.routingId.text = "${routing.lineId}"
holder.routingName.text = routing.lineName
holder.todayVerifyNum.text = "今日验证:${routing.carVerificationCount}"
holder.routingEndName.text = "${routing.endSite?.siteName?:""}方向"
val startName = routing.startSite?.siteName ?: ""
val endName = routing.endSite?.siteName ?: ""
if(routing.allStation.isNullOrEmpty()||routing.allStation?.size==2){
holder.routingEndName.text = "${startName} - ${endName}"
}else{
routing.allStation?.let {
val middleStationSize = it.size-2
val spannableString = SpannableString("${startName} - ${middleStationSize}站 - ${endName}")
// 设置不同颜色范围
spannableString.setSpan(
ForegroundColorSpan(allCOlor),
0, startName.length+2, // 从索引0开始的前4个字符
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
spannableString.setSpan(
ForegroundColorSpan(middleCOlor),
startName.length+3, startName.length+5, // 索引5-9的字符
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
spannableString.setSpan(
ForegroundColorSpan(allCOlor),
startName.length+6, spannableString.length, // 索引10-14的字符
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
holder.routingEndName.text = spannableString
}
}
holder.historyVerifyNumEnableNum.text = "${routing.lineSuccessCount}可用"
holder.historyVerifyNumDisenableNum.text = "${routing.lineFailCount}不可用"
//设置item点击事件
@@ -71,7 +110,14 @@ class RoutingItemAdapter(
mItemClickListener = itemClickListener
}
fun upDateInfo(grayLineBean: GrayLineBean, data: SitesInfo) {
grayLineBean.allStation = data.data?.toMutableList()
val indexOf = mData.indexOf(grayLineBean)
notifyItemChanged(indexOf)
}
class RoutingItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val routingId: AppCompatTextView = itemView.findViewById(R.id.actv_routing_id)//线路名称
val routingName: AppCompatTextView = itemView.findViewById(R.id.actv_routing_name)//线路名称
val todayVerifyNum: AppCompatTextView = itemView.findViewById(R.id.actv_today_verify_num) //终点
val routingEndName: AppCompatTextView = itemView.findViewById(R.id.actv_routing_end_name) //终点站点名称

View File

@@ -1,4 +1,4 @@
package com.mogo.och.unmanned.taxi.ui.routing.routingselect
package com.mogo.och.biz.routing.ui.routingselect
import androidx.lifecycle.ViewModel
import com.mogo.commons.AbsMogoApplication
@@ -6,20 +6,28 @@ import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
import com.mogo.eagle.core.function.call.och.CallerEagleBaseFunctionCall4OchManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.QueryGrayContrailListRsp
import com.mogo.och.biz.routing.bean.QuerySitesReasons
import com.mogo.och.biz.routing.bean.SitesInfo
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.biz.routing.net.RoutingServiceManager
import com.mogo.och.bridge.autopilot.line.LineManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.data.bean.LineInfo
import com.mogo.och.unmanned.taxi.bean.GrayLineBean
import com.mogo.och.unmanned.taxi.bean.QueryGrayContrailListRsp
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.unmanned.taxi.network.TaxiRoutingServiceManager
import com.mogo.och.unmanned.taxi.ui.debug.DebugView
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingModel
import com.mogo.och.unmanned.taxi.ui.routing.routingrunning.RoutingRunningModel
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.biz.login.LoginStatusManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.network.OchCommonNet
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
/**
* @author XuXinChao
@@ -28,7 +36,7 @@ import com.mogo.och.unmanned.taxi.ui.routing.routingrunning.RoutingRunningModel
*/
class RoutingSelectModel : ViewModel() {
private val TAG = RoutingRunningModel::class.java.simpleName
private val TAG = M_OCHCOMMON +"RoutingSelectModel"
private var viewCallback: SwtichRoutingViewCallback? = null
@@ -39,13 +47,41 @@ class RoutingSelectModel : ViewModel() {
}
fun queryStationList(grayLineBean: GrayLineBean) {
val request = QuerySitesReasons(grayLineBean.lineId?:0,
LoginStatusManager.getOchBizInfo()?.businessType?:11)
RoutingServiceManager.querySiteListByList(request)
.flatMap(OchCommonNet("queryBusRoutes",false))
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<SitesInfo> {
override fun onSubscribe(d: Disposable) {
d(TAG, "queryBusRoutes onSubscribe")
}
override fun onError(e: Throwable) {
e.printStackTrace()
OchChainLogManager.writeChainLogError("查询站点错误","灰度信息${grayLineBean}")
}
override fun onComplete() {
d(TAG, "queryBusRoutes onComplete")
}
override fun onNext(data: SitesInfo) {
viewCallback?.updateAdapter(grayLineBean,data)
}
})
}
/**
* 查询灰度路线
*/
fun queryRoutingGrayLineList() {
DebugView.printInfoMsg("[查询灰度路线] 准备发送请求sn=${SharedPrefsMgr.getInstance().sn}")
OchChainLogManager.writeChainLogRouting("[查询灰度路线]","[查询灰度路线] 准备发送请求sn=${SharedPrefsMgr.getInstance().sn}")
TaxiRoutingServiceManager.queryRoutingGrayLineList(
RoutingServiceManager.queryRoutingGrayLineList(
content,
object : OchCommonServiceCallback<QueryGrayContrailListRsp> {
override fun onSuccess(data: QueryGrayContrailListRsp) {
@@ -53,11 +89,17 @@ class RoutingSelectModel : ViewModel() {
TAG,
"queryRoutingGrayLineList onSuccess: data=${GsonUtils.toJson(data)}"
)
DebugView.printInfoMsg("[查询灰度路线] 请求successdataSize=${data?.data?.size}")
OchChainLogManager.writeChainLogRouting("[查询灰度路线]","[查询灰度路线] 请求successdataSize=${data?.data?.size}")
val result = mutableListOf<GrayLineBean>()
data.data?.also {
result.addAll(it)
}
result.forEach {
it.startSite?.let { startSite->
it.distance = BridgeManager.distance2Point( startSite.gcjLon, startSite.gcjLat,)
}
}
result.sortBy { it.distance }
viewCallback?.onQueryRoutingGrayLineListSuccess(result)
}
@@ -66,7 +108,7 @@ class RoutingSelectModel : ViewModel() {
TAG,
"queryRoutingGrayLineList onFail: code=$code, msg=$msg"
)
DebugView.printErrorMsg("[查询灰度路线] 请求fail, code=$code, msg=$msg, sn=${SharedPrefsMgr.getInstance().sn}")
OchChainLogManager.writeChainLogRouting("[查询灰度路线]","[查询灰度路线] 请求fail, code=$code, msg=$msg, sn=${SharedPrefsMgr.getInstance().sn}")
ToastUtils.showShort("查询灰度线路列表异常, 请稍后重试, code=$code")
viewCallback?.onQueryRoutingGrayLineListFailed(msg ?: "查询灰度线路列表异常, 请稍后重试")
}
@@ -83,7 +125,7 @@ class RoutingSelectModel : ViewModel() {
TAG,
"queryRoutingGrayLineList onError, msg=$hintStr, sn=${SharedPrefsMgr.getInstance().sn}"
)
DebugView.printErrorMsg("[查询灰度路线] 请求error, msg=$hintStr")
OchChainLogManager.writeChainLogRouting("[查询灰度路线]","[查询灰度路线] 请求error, msg=$hintStr")
viewCallback?.onQueryRoutingGrayLineListFailed(hintStr)
}
})
@@ -93,8 +135,8 @@ class RoutingSelectModel : ViewModel() {
* 开始灰度任务&查询轨迹详情
*/
fun startGrayTaskAndQueryRoutingContrail(contrailId: Long, grayLineBean: GrayLineBean) {
DebugView.printInfoMsg("[开始灰度任务&查询轨迹详情] 准备发送请求contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
TaxiRoutingServiceManager.startGrayTaskAndQueryRoutingContrail(
OchChainLogManager.writeChainLogRouting("[开始灰度任务&查询轨迹详情]","[开始灰度任务&查询轨迹详情] 准备发送请求contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
RoutingServiceManager.startGrayTaskAndQueryRoutingContrail(
content,
sn = SharedPrefsMgr.getInstance().sn,
contrailId = contrailId,
@@ -109,7 +151,7 @@ class RoutingSelectModel : ViewModel() {
)
}"
)
DebugView.printInfoMsg("[开始灰度任务&查询轨迹详情] 请求successtaskId=${data.taskId}, contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
OchChainLogManager.writeChainLogRouting("[开始灰度任务&查询轨迹详情]","[开始灰度任务&查询轨迹详情] 请求successtaskId=${data.taskId}, contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
initAutopilot(data)
}
@@ -119,7 +161,7 @@ class RoutingSelectModel : ViewModel() {
TAG,
"startGrayTaskAndQueryRoutingContrail onFail: code=$code, msg=$msg"
)
DebugView.printErrorMsg("[开始灰度任务&查询轨迹详情] 请求fail, code=$code, msg=$msg, contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
OchChainLogManager.writeChainLogRouting("[开始灰度任务&查询轨迹详情]","[开始灰度任务&查询轨迹详情] 请求fail, code=$code, msg=$msg, contrailId=${contrailId}, lineId=${grayLineBean.lineId}")
viewCallback?.onStartGrayTaskAndQueryContrailFailed( msg ?: "startGrayTaskAndQueryRoutingContrail onFail")
}
@@ -135,7 +177,7 @@ class RoutingSelectModel : ViewModel() {
TAG,
"startGrayTaskAndQueryRoutingContrail onError, msg=$hintStr, contrailId=${contrailId}, lineId=${grayLineBean.lineId}"
)
DebugView.printErrorMsg("[开始灰度任务&查询轨迹详情] 请求error, msg=$hintStr")
OchChainLogManager.writeChainLogRouting("[开始灰度任务&查询轨迹详情]","[开始灰度任务&查询轨迹详情] 请求error, msg=$hintStr")
viewCallback?.onStartGrayTaskAndQueryContrailFailed(hintStr)
}
}
@@ -143,41 +185,40 @@ class RoutingSelectModel : ViewModel() {
}
private fun initAutopilot(data: StartGrayAndQueryContrailRsp) {
DebugView.printInfoMsg("[开始任务] 准备开始任务")
OchChainLogManager.writeChainLogRouting("[开始任务]","[开始任务] 准备开始任务")
val grayLineBean = data.grayLineBean
val contrailBean = data.contrail
val grayId = data.taskId
if (grayLineBean == null || contrailBean == null) {
val stationList = data.stationList
if (grayLineBean == null || contrailBean == null || stationList.size < 2) {
ToastUtils.showShort("灰度线路或轨迹信息异常,请稍后再试")
DebugView.printErrorMsg("[开始任务] 灰度线路或轨迹信息异常,请稍后再试")
OchChainLogManager.writeChainLogRouting("[开始任务]","[开始任务] 灰度线路或轨迹信息异常,请稍后再试")
return
}
DebugView.printInfoMsg("[启自驾] 准备启动自驾")
OchChainLogManager.writeChainLogRouting("[启自驾]","[启自驾] 准备启动自驾")
val startStation = grayLineBean.startSite?.toBusStationBean()
val endStation = grayLineBean.endSite?.toBusStationBean()
val temp = mutableListOf<BusStationBean>()
if(startStation!=null){
temp.add(startStation)
}
if(endStation!=null){
temp.add(endStation)
stationList.forEachIndexed { index, busStationBean ->
if(index>0){
val (tempPassPoints, tempblackPoints) = contrailBean.getPassAndBlackPoint(index)
busStationBean.passPoints = tempPassPoints
busStationBean.blackPoints = tempblackPoints
}
}
LineManager.setLineInfo(
LineInfo(
grayLineBean.lineId?:0L,
LineInfo(grayLineBean.lineId?:0L,
grayLineBean.lineName?:"",
orderId = "${data.taskId}",
siteInfos = temp
)
siteInfos = stationList)
)
LineManager.setContraiInfo(contrailBean.toContraiInfo())
LineManager.setStartAndEndStation(startStation,endStation)
CallerEagleBaseFunctionCall4OchManager.updateOrderStatus(true)
viewCallback?.onStartGrayTaskAndQueryContrailSuccess(data)
// Routing 从这里解析出经停信息,轨迹信息,并调用下载轨迹接口
LineManager.initAutopilotControlParameters()?.let {
LineManager.initAutopilotControlParametersFromContrai()?.let {
CallerLogger.d(TAG,"下发下载轨迹信息:${it}")
OchChainLogManager.writeChainLogRouting("[启自驾]","下发下载轨迹信息:${it}")
CallerAutoPilotControlManager.sendTrajectoryDownloadReq(it)
}
}
@@ -200,6 +241,8 @@ class RoutingSelectModel : ViewModel() {
*/
fun onStartGrayTaskAndQueryContrailFailed(errorStr: String)
fun updateAdapter(grayLineBean: GrayLineBean, data: SitesInfo)
}
}

View File

@@ -0,0 +1,364 @@
package com.mogo.och.biz.routing.ui.routingselect
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.SitesInfo
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.common.module.wigets.WrapContentLinearLayoutManager
import com.mogo.och.biz.routing.ui.RoutingSwitchModel
import com.mogo.och.biz.routing.ui.routingselect.RoutingSelectModel.SwtichRoutingViewCallback
import com.mogo.och.common.module.manager.InputManager
import com.mogo.och.common.module.manager.InputTextChangeListener
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.common.module.wigets.KeyboarView
import kotlinx.android.synthetic.main.biz_taxi_select.view.acctv_search_byid
import kotlinx.android.synthetic.main.biz_taxi_select.view.aciv_input_icon
import kotlinx.android.synthetic.main.biz_taxi_select.view.aciv_refresh_task
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_current_order
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_distance
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_id_asc
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_id_desc
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_num_asc
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_num_desc
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_time_asc
import kotlinx.android.synthetic.main.biz_taxi_select.view.actv_order_by_time_desc
import kotlinx.android.synthetic.main.biz_taxi_select.view.cl_select_order
import kotlinx.android.synthetic.main.biz_taxi_select.view.cl_select_order_contain
import kotlinx.android.synthetic.main.biz_taxi_select.view.include_empty
import kotlinx.android.synthetic.main.biz_taxi_select.view.include_error
import kotlinx.android.synthetic.main.biz_taxi_select.view.switch_routing_rv
import me.jessyan.autosize.utils.AutoSizeUtils
class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback, InputTextChangeListener {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
companion object {
const val TAG = "SwitchBizView"
}
private var viewModel: RoutingSelectModel?=null
private var swtichViewModel: RoutingSwitchModel?=null
private lateinit var mChooseLineListAdapter: RoutingItemAdapter
private lateinit var mLinearLayoutManager: WrapContentLinearLayoutManager
private val mRoutingLineList: MutableList<GrayLineBean> = ArrayList()
private var mCurrentChosenPosition: Int = -1
private var animator: ObjectAnimator?=null
private var animatorStart = System.currentTimeMillis()
private var tempAllData = mutableListOf<GrayLineBean>()
init {
LayoutInflater.from(context).inflate(R.layout.biz_taxi_select, this, true)
initView()
}
private fun initView(){
mLinearLayoutManager = WrapContentLinearLayoutManager(context)
switch_routing_rv.layoutManager = mLinearLayoutManager
mChooseLineListAdapter = RoutingItemAdapter(context, mRoutingLineList)
switch_routing_rv.addItemDecoration(SpacesItemDecoration(AutoSizeUtils.dp2px(context,20f)))
switch_routing_rv.adapter = mChooseLineListAdapter
//设置item 点击事件
mChooseLineListAdapter.setOnLineItemClickListener(object :
RoutingItemAdapter.LineItemClickListener {
override fun onItemClick(data: GrayLineBean) {
if(data.contrailId==null||data.contrailId!!<=0L){
ToastUtils.showShort("请设置轨迹信息")
}
OchChainLogManager.writeChainLogRouting("[选择灰度任务]","[选择灰度任务] 当前选择 ${data} ")
resetStatus()
swtichViewModel?.showLoading()
viewModel?.startGrayTaskAndQueryRoutingContrail(data.contrailId!!,data)
}
})
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
|| AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)
|| AppIdentityModeUtils.isScheduled(FunctionBuildConfig.appIdentityMode)
) {
switch_routing_rv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val firstVisible = layoutManager.findFirstVisibleItemPosition()
val lastVisible = layoutManager.findLastVisibleItemPosition()
// 获取所有可见Item
(firstVisible..lastVisible).map { position ->
val grayLineBean = mRoutingLineList[position]
if (grayLineBean.allStation.isNullOrEmpty()) {
viewModel?.queryStationList(grayLineBean)
}
}
}
}
})
}
aciv_refresh_task.onClick {
viewModel?.queryRoutingGrayLineList()
aciv_refresh_task.isEnabled = false
animatorStart = System.currentTimeMillis()
if(animator==null) {
animator = ObjectAnimator.ofFloat(aciv_refresh_task, "rotation", 0f, 360f)
animator?.setDuration(1000) // 设置动画持续时间
animator?.repeatCount = ValueAnimator.INFINITE // 设置动画无限重复
animator?.repeatMode = ValueAnimator.RESTART // 设置重复模式
}
animator?.start()
resetStatus()
}
cl_select_order_contain.onClick {
cl_select_order_contain.visibility = View.GONE
}
cl_select_order.onClick {
cl_select_order_contain.visibility = View.VISIBLE
}
actv_order_by_distance.onClick {
mRoutingLineList.sortBy { it.distance }
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_default)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_id_asc.onClick {
mRoutingLineList.sortBy { it.lineId }
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_id_asc)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_id_desc.onClick {
mRoutingLineList.sortByDescending { it.lineId }
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_id_desc)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_num_asc.onClick {
mRoutingLineList.sortBy {
(it.lineSuccessCount?:0)+(it.lineFailCount?:0)
}
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_num_asc)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_num_desc.onClick {
// 按照总验证次序降序排列,而不是今日验证次序
mRoutingLineList.sortByDescending {
(it.lineSuccessCount?:0)+(it.lineFailCount?:0)
}
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_num_desc)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_time_asc.onClick {
mRoutingLineList.sortBy { it.contrailId }
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_time_asc)
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_time_desc.onClick {
mRoutingLineList.sortByDescending { it.contrailId }
mChooseLineListAdapter.notifyDataSetChanged()
cl_select_order_contain.visibility = View.GONE
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_time_desc)
switch_routing_rv.smoothScrollToPosition(0)
}
acctv_search_byid.onClick {
if(acctv_search_byid.isChecked==true){
acctv_search_byid.isChecked = false
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_normal)
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_normal)
InputManager.setKeyboardVisable(View.GONE)
}else{
acctv_search_byid.isChecked = true
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_check)
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_check)
InputManager.setKeyboardVisable(View.VISIBLE)
}
}
}
private fun resetStatus() {
InputManager.clearInput()
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_default)
switch_routing_rv.smoothScrollToPosition(0)
acctv_search_byid.isChecked = false
acctv_search_byid.text = ""
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_normal)
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_normal)
InputManager.setKeyboardVisable(GONE)
}
private fun showEmptyView() {
switch_routing_rv.visibility = GONE
include_empty.visibility = View.VISIBLE
include_error.visibility = View.GONE
}
private fun showErrorView() {
switch_routing_rv.visibility = GONE
include_empty.visibility = View.GONE
include_error.visibility = View.VISIBLE
}
private fun showRecyclerView() {
switch_routing_rv.visibility = VISIBLE
include_empty.visibility = View.GONE
include_error.visibility = View.GONE
}
private fun onRoutingGrayLineListChanged(data: MutableList<GrayLineBean>) {
if (data.isNotEmpty()) {
showRecyclerView()
tempAllData = data
mRoutingLineList.clear()
mRoutingLineList.addAll(data)
mChooseLineListAdapter.notifyDataSetChanged()
ToastUtils.showShort("刷新成功")
} else {
showEmptyView()
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingSelectModel::class.java)
}
viewModel?.setDistanceCallback(this)
swtichViewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingSwitchModel::class.java)
}
InputManager.addListener(TAG,this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
InputManager.removeListener(TAG)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
if(isVisible){
viewModel?.queryRoutingGrayLineList()
}
}
override fun onQueryRoutingGrayLineListSuccess(data: MutableList<GrayLineBean>) {
// 数据默认按照距离排序过了
onRoutingGrayLineListChanged(data)
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
||AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)
||AppIdentityModeUtils.isScheduled(FunctionBuildConfig.appIdentityMode)
) {
data.forEachIndexed { index, grayLineBean ->
if (index < 3) {
viewModel?.queryStationList(grayLineBean)
}
}
}
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_default)
acctv_search_byid.text=""
cancleAni()
}
override fun onQueryRoutingGrayLineListFailed(errorStr: String) {
showErrorView()
cancleAni()
}
override fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) {
swtichViewModel?.showRoutingRunning(data)
}
override fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) {
swtichViewModel?.showRoutingSelectView()
}
override fun updateAdapter(grayLineBean: GrayLineBean, data: SitesInfo) {
mChooseLineListAdapter.upDateInfo(grayLineBean,data)
}
private fun cancleAni(){
val endTime = System.currentTimeMillis()
val dex = (1000-(endTime - animatorStart)).takeIf { it>=0 }?:0
UiThreadHandler.postDelayed({
animator?.cancel()
aciv_refresh_task.isEnabled = true
},dex, UiThreadHandler.MODE.QUEUE,)
}
override fun onTextChange(info: String) {
ToastUtils.showShort(info)
if (acctv_search_byid.isChecked) {
acctv_search_byid.text = info
if(info.isEmpty()){
mRoutingLineList.clear()
mRoutingLineList.addAll(tempAllData)
mChooseLineListAdapter.notifyDataSetChanged()
}else{
val searchData = tempAllData.filter { it.lineId.toString().contains(info) }
mRoutingLineList.clear()
mRoutingLineList.addAll(searchData)
mChooseLineListAdapter.notifyDataSetChanged()
}
}
}
override fun onKeyVisiblityChange(b: Boolean) {
if(b){
acctv_search_byid.isChecked = true
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_check)
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_check)
}else{
acctv_search_byid.isChecked = false
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_normal)
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_normal)
}
}
}

View File

@@ -0,0 +1,263 @@
package com.mogo.och.biz.routing.ui.runing.other
import android.animation.ArgbEvaluator
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.biz.R
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.data.bean.BusStationBean
import me.jessyan.autosize.utils.AutoSizeUtils
/**
* 路线列表adapter
*/
class TaskRunningAdapter(
private val mContext: Context,
val mData: MutableList<BusStationBean>
) : RecyclerView.Adapter<TaskRunningAdapter.TaskRunningViewHolder>() {
companion object {
const val TAG = "${M_OCHCOMMON}TaskRunningAdapter"
}
private val argbEvaluator: ArgbEvaluator = ArgbEvaluator()
private val startColor = ResourcesUtils.getColor(R.color.common_1970FF)
private val endColor = ResourcesUtils.getColor(R.color.common_19FF7F)
private val heightItem = 100f
private val halfHeight = 16.5f
private var totalHeight = 0f
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): TaskRunningViewHolder {
val view = LayoutInflater.from(mContext).inflate(
R.layout.biz_other_running_item, parent, false
)
return TaskRunningViewHolder(view)
}
override fun onBindViewHolder(holder: TaskRunningViewHolder, position: Int) {
val currentPosition = holder.bindingAdapterPosition
val line = mData[currentPosition]
holder.actvStationName.text = line.name
val startStationIndex = TaskRunningModel.currentIndex
if (startStationIndex >= 0) {
CallerLogger.d(TAG, "位置:$currentPosition ${TaskRunningModel.currentIndex} 当前站${mData[startStationIndex]} ")
}
if (currentPosition < startStationIndex) {
holder.actvStationName.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
AutoSizeUtils.dp2px(mContext, 40f).toFloat()
)
holder.actvStationName.setTextColor(ResourcesUtils.getColor(R.color.common_4DFFFFFF))
holder.acivStationHead.setImageResource(R.drawable.bus_switch_line_adapter_point_pass)
} else if (currentPosition == startStationIndex) {
holder.actvStationName.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
AutoSizeUtils.dp2px(mContext, 45f).toFloat()
)
holder.actvStationName.setTextColor(ResourcesUtils.getColor(R.color.common_2EACFF))
holder.acivStationHead.setImageResource(R.drawable.bus_runnint_task_middle)
} else {
holder.actvStationName.setTextColor(ResourcesUtils.getColor(R.color.white))
holder.actvStationName.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
AutoSizeUtils.dp2px(mContext, 40f).toFloat()
)
holder.itemView.background = null
holder.acivStationHead.setImageResource(R.drawable.bus_runnint_task_middle)
}
when (currentPosition) {
0 -> {
holder.acivStationHeadBig.visibility = View.VISIBLE
holder.acivStationHead.visibility = View.INVISIBLE
holder.acivStationHeadBig.setImageResource(R.drawable.bus_runnint_task_start)
holder.middleStationBg.visibility = View.GONE
holder.startStationBg.visibility = View.VISIBLE
holder.endStationBg.visibility = View.GONE
if (startStationIndex == 0) {
if (line.isLeaving) {
// 下端 灰色
holder.startStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
holder.itemView.background = null
} else {
// 下端 彩色
holder.itemView.setBackgroundResource(R.drawable.bus_task_current_station_bg)
val orientation = GradientDrawable.Orientation.TOP_BOTTOM
val temp01 = GradientDrawable(
orientation, intArrayOf(
startColor,
endColor
)
)
holder.startStationBg.background = temp01
}
} else {
// 下端 灰色
holder.startStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
holder.itemView.background = null
}
}
mData.size - 1 -> {
holder.acivStationHeadBig.visibility = View.VISIBLE
holder.acivStationHead.visibility = View.INVISIBLE
holder.acivStationHeadBig.setImageResource(R.drawable.bus_runnint_task_end)
holder.middleStationBg.visibility = View.GONE
holder.startStationBg.visibility = View.GONE
holder.endStationBg.visibility = View.VISIBLE
if (startStationIndex == itemCount - 2) {
if (line.isLeaving) {
holder.endStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
holder.itemView.setBackgroundResource(R.drawable.bus_task_current_station_bg)
} else {
holder.itemView.setBackgroundResource(R.drawable.bus_task_current_station_bg)
holder.endStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
}
} else {
// 上端 彩色
holder.itemView.background = null
val startColorTemp = argbEvaluator.evaluate(
((totalHeight - halfHeight) / totalHeight).toFloat(),
startColor,
endColor
) as Int
val endColorTemp = argbEvaluator.evaluate(1f, startColor, endColor) as Int
val orientation = GradientDrawable.Orientation.TOP_BOTTOM
val temp01 = GradientDrawable(
orientation, intArrayOf(
startColorTemp,
endColorTemp
)
)
holder.endStationBg.background = temp01
}
}
else -> {
holder.acivStationHeadBig.visibility = View.GONE
holder.acivStationHead.visibility = View.VISIBLE
holder.middleStationBg.visibility = View.VISIBLE
holder.startStationBg.visibility = View.GONE
holder.endStationBg.visibility = View.GONE
if (currentPosition == startStationIndex) {
if (line.isLeaving) {
// 灰色
holder.middleStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
holder.itemView.background = null
} else {
// 彩色
holder.itemView.setBackgroundResource(R.drawable.bus_task_current_station_bg)
val startColorTemp = argbEvaluator.evaluate(0f, startColor, endColor) as Int
val endColorTemp =
argbEvaluator.evaluate(100f / totalHeight, startColor, endColor) as Int
val orientation = GradientDrawable.Orientation.TOP_BOTTOM
val temp01 = GradientDrawable(
orientation, intArrayOf(
startColorTemp,
endColorTemp
)
)
holder.middleStationBg.background = temp01
}
} else if (currentPosition < startStationIndex) {
// 灰色
holder.middleStationBg.setBackgroundResource(R.color.common_4DFFFFFF)
holder.itemView.background = null
} else {
var dex = 0f
if (startStationIndex == 0) {
val firstItemData = mData[0]
if (!firstItemData.isLeaving) {
dex = halfHeight
}
} else {
val checkIndex = mData.get(startStationIndex)
if (!checkIndex.isLeaving) {
dex = heightItem
}
}
// 彩色
holder.itemView.background = null
val index = (currentPosition - startStationIndex - 1) * 100
val startFraction = (dex + index) / totalHeight
val endFraction = (dex + index + 100) / totalHeight
// CallerLogger.d(
// TAG,
// "位置:$currentPosition 当前站${startStationIndex} 开始百分比:${startFraction} 结束百分比:${endFraction}"
// )
val startColorTemp =
argbEvaluator.evaluate(startFraction, startColor, endColor) as Int
val endColorTemp =
argbEvaluator.evaluate(endFraction, startColor, endColor) as Int
val orientation = GradientDrawable.Orientation.TOP_BOTTOM
val temp01 = GradientDrawable(
orientation, intArrayOf(
startColorTemp,
endColorTemp
)
)
holder.middleStationBg.background = temp01
}
}
}
if (currentPosition == startStationIndex + 1) {
val preLine = mData[currentPosition - 1]
if (preLine.isLeaving) {
holder.itemView.setBackgroundResource(R.drawable.bus_task_current_station_bg)
} else {
holder.itemView.background = null
}
}
}
override fun getItemCount(): Int {
return mData.size
}
fun setDataList(dataList: List<BusStationBean>) {
this.mData.clear()
this.mData.addAll(dataList)
totalHeight = 33 + (dataList.size - 2) * heightItem
notifyItemRangeChanged(0, dataList.size, true)
}
fun notifyChange(){
if (TaskRunningModel.currentIndex == 0) {
totalHeight = 33 + (mData.size - 2) * heightItem
} else {
totalHeight =
(halfHeight + (mData.size - 1 - TaskRunningModel.currentIndex) * heightItem).toFloat()
}
notifyItemRangeChanged(0, mData.size, true)
}
class TaskRunningViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val actvStationName: AppCompatTextView = itemView.findViewById(R.id.actv_station_name)//站点名称
val acivStationHead: AppCompatImageView =
itemView.findViewById(R.id.aciv_station_head)//普通站点标识 不是起始和终点坐标
val acivStationHeadBig: AppCompatImageView =
itemView.findViewById(R.id.aciv_station_head_big)//起始和终点坐标标识
val middleStationBg: View = itemView.findViewById(R.id.bg_pass_bg) //贯通背景调
val endStationBg: View = itemView.findViewById(R.id.bg_pass_head_bg) //终点的背景
val startStationBg: View = itemView.findViewById(R.id.bg_pass_bottom_bg) //起点坐标的背景
}
}

View File

@@ -0,0 +1,303 @@
package com.mogo.och.biz.routing.ui.runing.other
import androidx.lifecycle.ViewModel
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.module.status.MogoStatusManager
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.och.CallerEagleBaseFunctionCall4OchManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.och.biz.routing.bean.ContrailBean
import com.mogo.och.biz.routing.bean.EndGrayContrailTaskReq
import com.mogo.och.biz.routing.bean.EndGrayTaskFeedbackType
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.biz.routing.net.RoutingServiceManager
import com.mogo.och.bridge.autopilot.autopilot.IOchAutopilotStatusListener
import com.mogo.och.bridge.autopilot.autopilot.OchAutoPilotStatusListenerManager
import com.mogo.och.bridge.autopilot.autopilot.bean.ArrivedStation
import com.mogo.och.bridge.autopilot.line.ILineCallback
import com.mogo.och.bridge.autopilot.line.LineManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.data.bean.BusStationBean
/**
* @author XuXinChao
* @description BadCase录包管理页面
* @since: 2022/12/15
*/
class TaskRunningModel : ViewModel() {
private val TAG = M_OCHCOMMON + TaskRunningModel::class.java.simpleName
private var viewCallback: SwtichLineViewCallback? = null
private val content = AbsMogoApplication.getApp()
private var _data: StartGrayAndQueryContrailRsp? = null
val data: StartGrayAndQueryContrailRsp?
get() = _data
private var currentGrayLineBean: GrayLineBean? = null
private var currentContrailBean: ContrailBean? = null
private var stationList: MutableList<BusStationBean>? = null
private var currentGrayId: Long? = null
/**
* 是否可以进行进站操作
*/
var arrivedStation:Boolean = false
companion object {
var currentIndex = -1
}
override fun onCleared() {
}
fun setDistanceCallback(viewCallback: SwtichLineViewCallback) {
this.viewCallback = viewCallback
}
fun setNewData(data: StartGrayAndQueryContrailRsp) {
this._data = data
this.currentGrayLineBean = data.grayLineBean
this.currentContrailBean = data.contrail
this.currentGrayId = data.taskId
this.stationList = data.stationList
this.stationList?.forEach {
it.isLeaving = false
}
currentIndex = 0
this.stationList?.let {
val startStationNext = it[currentIndex]
val endStation = it[currentIndex + 1]
CallerLogger.d(TAG,"setNewData index:${currentIndex} ${startStationNext.name} -- ${endStation.name}")
LineManager.setStartAndEndStation(startStationNext, endStation)
}
MogoStatusManager.getInstance().setTaxiUnmanedDriverLineRoutingPerformTask(TAG, true)
//添加到站监听
OchAutoPilotStatusListenerManager.addListener(TAG, mMogoAutopilotStatusListener)
LineManager.addListener(TAG, lineCallback)
}
//MAP到站监听
private val mMogoAutopilotStatusListener: IOchAutopilotStatusListener =
object : IOchAutopilotStatusListener {
override fun onAutopilotArriveAtStation(arrivalNotification: ArrivedStation?) {
if(!arrivedStation){
OchChainLogManager.writeChainLogRouting("已到站","等待重试",false)
return
}
CallerLogger.i(
TAG,
"onAutopilotArriveAtStation = ${arrivalNotification.toString()}"
)
OchChainLogManager.writeChainLogRouting(
"MAP到站通知",
"[MAP到站通知] 上报到站location=${arrivalNotification?.endLocation}"
)
arriveStation()
}
}
private val lineCallback: ILineCallback = object : ILineCallback {
override fun arrivedStationSuccessBySearch() {
OchChainLogManager.writeChainLogRouting(
"[自车定位围栏]",
"\"[自车定位围栏] 并查询底盘触发到站, endSiteId=${currentGrayLineBean?.endSite?.siteId}, endSiteName=${currentGrayLineBean?.endSite?.siteName}, lineId=${currentGrayLineBean?.lineId},围栏范围:${OchCommonConst.ARRIVE_AT_START_STATION_DISTANCE}米 没有过站、速度基本为零且在15m内\""
)
if(!arrivedStation){
OchChainLogManager.writeChainLogRouting("已到站","等待重试",false)
return
}
arriveStation()
}
}
fun leaveStation() {
stationList?.let {
if (it.isNotEmpty()) {
if (currentIndex + 1 >= it.size) {
this.viewCallback?.showCompleteTask()
return
}
val startStation = it[currentIndex]
val endStation = it[currentIndex + 1]
startStation.isLeaving = true
arrivedStation = true
startStation.drivingStatus = 2
CallerLogger.d(TAG,"leaveStation index:${currentIndex} ${startStation.name}---${endStation.name}")
this.viewCallback?.notifyItemChange(currentIndex)
this.viewCallback?.showArriverStationAndCompleteTask()
if (CallerAutoPilotStatusListenerManager.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
) {
LineManager.startAutopilot()
}
}
}
}
fun arriveStation() {
stationList?.let {
val startStation = it[currentIndex]
if (currentIndex + 2 >= it.size) {
startStation.isLeaving = true
this.viewCallback?.showCompleteTask()
}else {
startStation.isLeaving = false
arrivedStation = false
startStation.drivingStatus = 1
currentIndex += 1
val startStationNext = it[currentIndex]
val endStation = it[currentIndex + 1]
CallerLogger.d(TAG, "setNewData index:${currentIndex} ${startStationNext.name}----${endStation.name}")
LineManager.setStartAndEndStation(startStationNext, endStation)
}
LineManager.getStations { start, end ->
BizLoopManager.runInMainThread{
this.viewCallback?.onArrivedStation(start.isLeaving)
}
}
}
}
interface SwtichLineViewCallback {
// 到站
fun onArrivedStation(leaving: Boolean)
// 结束服务成功
fun onSubmitEndTaskSuccess()
// 结束服务失败
fun onSubmitEndTaskFailed(s: String)
// 站点到站和结束任务
fun showCompleteTask()
//
fun showArriverStationAndCompleteTask()
fun notifyItemChange(currentIndex: Int)
fun clearData()
}
/**
* 结束灰度任务
*/
fun endGrayTask(grayId: Long, type: EndGrayTaskFeedbackType, occurrenceTime: Long) {
OchChainLogManager.writeChainLogRouting(
"[结束灰度任务]",
"[结束灰度任务] 准备发送请求grayId=$grayId type=${type.type}, typeName=${type.name}"
)
val submit = EndGrayContrailTaskReq(grayId, type.type, occurrenceTime)
RoutingServiceManager.endGrayTask(
content,
submit,
object : OchCommonServiceCallback<BaseData> {
override fun onSuccess(data: BaseData?) {
CallerLogger.d(
TAG,
"endGrayTask onSuccess: data=${
GsonUtils.toJson(
data
)
}"
)
OchChainLogManager.writeChainLogRouting(
"[结束灰度任务]",
"[结束灰度任务] 请求successgrayId=$grayId type=${type.type}, typeName=${type.name}"
)
clearData()
viewCallback?.onSubmitEndTaskSuccess()
}
override fun onFail(code: Int, msg: String?) {
CallerLogger.d(
TAG,
"endGrayTask onFail: code=$code, msg=$msg"
)
OchChainLogManager.writeChainLogRouting(
"[结束灰度任务]",
"[结束灰度任务] 请求fail, code=$code, msg=$msg, grayId=$grayId type=${type.type}, typeName=${type.name}"
)
viewCallback?.onSubmitEndTaskFailed(msg ?: "endGrayTask onFail")
}
override fun onError() {
super.onError()
var hintStr = ""
if (!NetworkUtils.isConnected(content)) {
hintStr = "网络出现异常,请稍后重试"
} else {
hintStr = "上报结束任务异常, 请稍后重试"
}
CallerLogger.d(
TAG,
"endGrayTask onError, msg=$hintStr"
)
OchChainLogManager.writeChainLogRouting(
"[结束灰度任务]",
"[结束灰度任务] 请求error, msg=$hintStr, grayId=$grayId type=${type.type}, typeName=${type.name}"
)
viewCallback?.onSubmitEndTaskFailed(hintStr)
}
})
}
private fun clearData() {
_data = null
this.currentGrayLineBean = null
this.currentContrailBean = null
this.currentGrayId = null
LineManager.setLineInfo(null)
LineManager.setContraiInfo(null)
LineManager.setStartAndEndStation(null, null)
BizLoopManager.runInMainThread{
this.viewCallback?.clearData()
}
CallerEagleBaseFunctionCall4OchManager.updateOrderStatus(false)
// 设置灰度路线任务执行状态,切换模式时判断使用
MogoStatusManager.getInstance().setTaxiUnmanedDriverLineRoutingPerformTask(TAG, false)
// 移除到站监听
OchAutoPilotStatusListenerManager.removeListener(TAG)
LineManager.removeListener(TAG)
cancelAutopilot()
}
/**
* 结束自动驾驶
* */
private fun cancelAutopilot() {
try {
CallerAutoPilotControlManager.cancelAutoPilot()
OchChainLogManager.writeChainLogRouting("[取消自驾]", "[取消自驾] 调用成功")
CallerLogger.d(TAG, "结束自动驾驶")
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,261 @@
package com.mogo.och.biz.routing.ui.runing.other
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.RoutingServiceManager
import com.mogo.och.biz.routing.bean.EndGrayTaskFeedbackType
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.biz.routing.ui.RoutingSwitchModel
import com.mogo.och.biz.routing.ui.errorpoint.ReportErrorPointView
import com.mogo.och.bridge.autopilot.line.LineManager
import com.mogo.och.common.module.map.AmapNaviToDestinationModel
import com.mogo.och.common.module.wigets.dialog.CommonDialogStatus
import com.mogo.och.common.module.wigets.CommonSlideView
import com.mogo.och.common.module.wigets.WrapContentLinearLayoutManager
import kotlinx.android.synthetic.main.biz_other_running.view.aciv_task_leave_station_slide_bg
import kotlinx.android.synthetic.main.biz_other_running.view.actv_arriver_station
import kotlinx.android.synthetic.main.biz_other_running.view.actv_complete_task
import kotlinx.android.synthetic.main.biz_other_running.view.actv_running_task_last_station
import kotlinx.android.synthetic.main.biz_other_running.view.actv_submit_task
import kotlinx.android.synthetic.main.biz_other_running.view.bus_task_running_line_name
import kotlinx.android.synthetic.main.biz_other_running.view.loading_arrive_station
import kotlinx.android.synthetic.main.biz_other_running.view.rl_running_task_station_list
/**
* Bus接驳算路验证的任务
*/
class TaskRunningView : ConstraintLayout, TaskRunningModel.SwtichLineViewCallback {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(
context,
attributeSet,
defStyleAttr
)
constructor(
context: Context,
attributeSet: AttributeSet,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attributeSet, defStyleAttr, defStyleRes)
companion object {
const val TAG = M_OCHCOMMON + "TaskRunningView"
}
private var viewModel: TaskRunningModel? = null
private var swtichViewModel: RoutingSwitchModel?=null
private lateinit var mAdapter: TaskRunningAdapter
private lateinit var linearLayoutManager: WrapContentLinearLayoutManager
private var closeRouting: CommonDialogStatus?=null
init {
LayoutInflater.from(context).inflate(R.layout.biz_other_running, this, true)
initView()
}
private fun initView() {
linearLayoutManager = WrapContentLinearLayoutManager(context)
rl_running_task_station_list.setLayoutManager(linearLayoutManager)
mAdapter = TaskRunningAdapter(context, mutableListOf())
rl_running_task_station_list.setAdapter(mAdapter)
// 滑动出发
aciv_task_leave_station_slide_bg.setSlideListener(object : CommonSlideView.SlideListener {
override fun slideEnd() {
if (TaskRunningModel.currentIndex == mAdapter.mData.size-2) {
LineManager.getStations { start, end ->
if (viewModel?.arrivedStation == true && start.isLeaving) {
aciv_task_leave_station_slide_bg.setTextValue("单程结束")
aciv_task_leave_station_slide_bg.reset()
viewModel?.data?.taskId?.let {
showFeedbackDialog(it)
}
}else{
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
viewModel?.leaveStation()
}
}
} else {
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
viewModel?.leaveStation()
}
}
})
// 到站
actv_arriver_station.onClick {
loading_arrive_station.visibility = VISIBLE
viewModel?.arriveStation()
}
// 结束任务
actv_complete_task.onClick {
viewModel?.data?.taskId?.let {
showFeedbackDialog(it)
}
}
actv_submit_task.onClick {
CallerLogger.d(TAG,"启动自驾参数:${LineManager.initAutopilotControlParameters()}")
viewModel?.data?.taskId?.let {
ReportErrorPointView.showDialog(context,it)
}
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(TaskRunningModel::class.java)
}
swtichViewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingSwitchModel::class.java)
}
viewModel?.setDistanceCallback(this)
}
private fun showFeedbackDialog(grayId: Long) {
CallerLogger.d(TAG, "showFeedbackDialog!")
val occurrenceTime = System.currentTimeMillis()
if(closeRouting==null) {
CallerLogger.d(TAG, "closeRouting is null!")
closeRouting = CommonDialogStatus
.Builder()
.title("路线验证结束")
.tips("请点击按钮反馈验证结果")
.showClose(true)
.cancelTextColor(R.color.biz_routing_FF4E41)
.cancelStr("线路不可用")
.confirmStr("线路可用")
.status(CommonDialogStatus.Status.success)
.build(context)
}else{
if(closeRouting?.isShowing==true){
CallerLogger.d(TAG, "closeRouting is showing, return!")
return
}
}
closeRouting?.setClickListener(object : CommonDialogStatus.ClickListener {
override fun confirm() {
swtichViewModel?.showLoading()
viewModel?.endGrayTask(grayId, EndGrayTaskFeedbackType.USABLE_YES, occurrenceTime)
}
override fun cancel() {
swtichViewModel?.showLoading()
viewModel?.endGrayTask(
grayId,
EndGrayTaskFeedbackType.USABLE_NO,
occurrenceTime
)
}
})
CallerLogger.d(TAG, "closeRouting show!")
closeRouting?.show()
}
fun showLeaveStationView() {
aciv_task_leave_station_slide_bg.visibility = VISIBLE
actv_arriver_station.visibility = GONE
actv_complete_task.visibility = GONE
}
override fun showArriverStationAndCompleteTask() {
aciv_task_leave_station_slide_bg.visibility = INVISIBLE
actv_arriver_station.visibility = VISIBLE
actv_complete_task.visibility = VISIBLE
}
fun setData(data: StartGrayAndQueryContrailRsp) {
viewModel?.setNewData(data)
bus_task_running_line_name.setText(data.grayLineBean.lineName)
actv_running_task_last_station.text = "${data.stationList.last().name ?: ""}"
mAdapter.setDataList(data.stationList)
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
showLeaveStationView()
}
/**
* 到达目的地
*/
override fun onArrivedStation(leaving: Boolean) {
//
showLeaveStationView()
loading_arrive_station.visibility = GONE
notifyItemChange(0)
if (TaskRunningModel.currentIndex == mAdapter.mData.size-2) {
LineManager.getStations { start, end ->
if(start.isLeaving){
aciv_task_leave_station_slide_bg.setTextValue("单程结束")
}else{
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
}
}
} else {
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
}
}
/**
* 服务完成
*/
override fun onSubmitEndTaskSuccess() {
ToastUtils.showLong("结束任务成功")
RoutingServiceManager.invokeCallback(false)
// 移除高德导航计算距离
AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi()
swtichViewModel?.showRoutingSelectView()
}
/**
* 服务完成失败
*/
override fun onSubmitEndTaskFailed(errorStr: String) {
ToastUtils.showShort(errorStr)
viewModel?.data?.let {
swtichViewModel?.showRoutingRunning(it)
}
}
override fun showCompleteTask() {
aciv_task_leave_station_slide_bg.setTextValue("单程结束")
}
override fun notifyItemChange(currentIndex: Int) {
mAdapter.notifyChange()
}
override fun clearData() {
bus_task_running_line_name.setText("--")
actv_running_task_last_station.text = "往--"
mAdapter.setDataList(mutableListOf())
aciv_task_leave_station_slide_bg.setTextValue("滑动出发")
showLeaveStationView()
}
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.unmanned.taxi.ui.routing.routingrunning
package com.mogo.och.biz.routing.ui.runing.taxi
import androidx.lifecycle.ViewModel
import com.mogo.commons.AbsMogoApplication
@@ -9,6 +9,12 @@ import com.mogo.eagle.core.function.call.och.CallerEagleBaseFunctionCall4OchMana
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.och.biz.routing.bean.ContrailBean
import com.mogo.och.biz.routing.bean.EndGrayContrailTaskReq
import com.mogo.och.biz.routing.bean.EndGrayTaskFeedbackType
import com.mogo.och.biz.routing.bean.GrayLineBean
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.biz.routing.net.RoutingServiceManager
import com.mogo.och.bridge.autopilot.autopilot.IOchAutopilotStatusListener
import com.mogo.och.bridge.autopilot.autopilot.OchAutoPilotStatusListenerManager
import com.mogo.och.bridge.autopilot.autopilot.bean.ArrivedStation
@@ -17,24 +23,17 @@ import com.mogo.och.bridge.autopilot.line.LineManager
import com.mogo.och.bridge.distance.IDistanceListener
import com.mogo.och.bridge.distance.TrajectoryAndDistanceManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.unmanned.taxi.bean.ContrailBean
import com.mogo.och.unmanned.taxi.bean.EndGrayContrailTaskReq
import com.mogo.och.unmanned.taxi.bean.EndGrayTaskFeedbackType
import com.mogo.och.unmanned.taxi.bean.GrayLineBean
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst
import com.mogo.och.unmanned.taxi.network.TaxiRoutingServiceManager
import com.mogo.och.unmanned.taxi.ui.debug.DebugView
/**
* @author XuXinChao
* @description BadCase录包管理页面
* @since: 2022/12/15
*/
class RoutingRunningModel : ViewModel(), IDistanceListener {
class TaxiRunningModel : ViewModel(), IDistanceListener {
private val TAG = RoutingRunningModel::class.java.simpleName
private val TAG = TaxiRunningModel::class.java.simpleName
private var viewCallback: RoutingRuningCallback? = null
@@ -58,16 +57,14 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
TAG,
"onAutopilotArriveAtStation = ${arrivalNotification.toString()}"
)
DebugView.printInfoMsg("[MAP到站通知] 上报到站location=${arrivalNotification?.endLocation}")
OchChainLogManager.writeChainLogRouting("MAP到站通知","[MAP到站通知] 上报到站location=${arrivalNotification?.endLocation}")
viewCallback?.onArrivedStation(currentGrayId)
}
}
private val lineCallback: ILineCallback = object : ILineCallback {
override fun arrivedStationSuccessBySearch() {
DebugView.printInfoMsg(
"[自车定位围栏] 并查询底盘触发到站, endSiteId=${currentGrayLineBean?.endSite?.siteId}, endSiteName=${currentGrayLineBean?.endSite?.siteName}, lineId=${currentGrayLineBean?.lineId},围栏范围:${TaxiUnmannedConst.ARRIVE_AT_START_STATION_DISTANCE}米 没有过站、速度基本为零且在15m内"
)
OchChainLogManager.writeChainLogRouting("[自车定位围栏]","\"[自车定位围栏] 并查询底盘触发到站, endSiteId=${currentGrayLineBean?.endSite?.siteId}, endSiteName=${currentGrayLineBean?.endSite?.siteName}, lineId=${currentGrayLineBean?.lineId},围栏范围:${OchCommonConst.ARRIVE_AT_START_STATION_DISTANCE}米 没有过站、速度基本为零且在15m内\"")
viewCallback?.onArrivedStation(currentGrayId)
}
}
@@ -101,6 +98,9 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
this.currentGrayLineBean = data.grayLineBean
this.currentContrailBean = data.contrail
this.currentGrayId = data.taskId
if(data.stationList.size>=2) {
LineManager.setStartAndEndStation(data.stationList[0], data.stationList[1])
}
MogoStatusManager.getInstance().setTaxiUnmanedDriverLineRoutingPerformTask(TAG, true)
//添加到站监听
OchAutoPilotStatusListenerManager.addListener(TAG, mMogoAutopilotStatusListener)
@@ -111,9 +111,9 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
* 结束灰度任务
*/
fun endGrayTask(grayId: Long, type: EndGrayTaskFeedbackType, occurrenceTime: Long) {
DebugView.printInfoMsg("[结束灰度任务] 准备发送请求grayId=$grayId type=${type.type}, typeName=${type.name}")
OchChainLogManager.writeChainLogRouting("[结束灰度任务]","[结束灰度任务] 准备发送请求grayId=$grayId type=${type.type}, typeName=${type.name}")
val submit = EndGrayContrailTaskReq(grayId, type.type, occurrenceTime)
TaxiRoutingServiceManager.endGrayTask(
RoutingServiceManager.endGrayTask(
content,
submit,
object : OchCommonServiceCallback<BaseData> {
@@ -126,7 +126,7 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
)
}"
)
DebugView.printInfoMsg("[结束灰度任务] 请求successgrayId=$grayId type=${type.type}, typeName=${type.name}")
OchChainLogManager.writeChainLogRouting("[结束灰度任务]","[结束灰度任务] 请求successgrayId=$grayId type=${type.type}, typeName=${type.name}")
clearData()
viewCallback?.onSubmitEndTaskSuccess()
}
@@ -136,7 +136,7 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
TAG,
"endGrayTask onFail: code=$code, msg=$msg"
)
DebugView.printErrorMsg("[结束灰度任务] 请求fail, code=$code, msg=$msg, grayId=$grayId type=${type.type}, typeName=${type.name}")
OchChainLogManager.writeChainLogRouting("[结束灰度任务]","[结束灰度任务] 请求fail, code=$code, msg=$msg, grayId=$grayId type=${type.type}, typeName=${type.name}")
viewCallback?.onSubmitEndTaskFailed(msg ?: "endGrayTask onFail")
}
@@ -152,7 +152,7 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
TAG,
"endGrayTask onError, msg=$hintStr"
)
DebugView.printErrorMsg("[结束灰度任务] 请求error, msg=$hintStr, grayId=$grayId type=${type.type}, typeName=${type.name}")
OchChainLogManager.writeChainLogRouting("[结束灰度任务]","[结束灰度任务] 请求error, msg=$hintStr, grayId=$grayId type=${type.type}, typeName=${type.name}")
viewCallback?.onSubmitEndTaskFailed(hintStr)
}
})
@@ -184,7 +184,7 @@ class RoutingRunningModel : ViewModel(), IDistanceListener {
private fun cancelAutopilot() {
try {
CallerAutoPilotControlManager.cancelAutoPilot()
DebugView.printInfoMsg("[取消自驾] 调用成功")
OchChainLogManager.writeChainLogRouting("[取消自驾]","[取消自驾] 调用成功")
CallerLogger.d(TAG, "结束自动驾驶")
} catch (e: Exception) {
e.printStackTrace()

View File

@@ -1,4 +1,4 @@
package com.mogo.och.unmanned.taxi.ui.routing.routingrunning
package com.mogo.och.biz.routing.ui.runing.taxi
import android.content.Context
import android.util.AttributeSet
@@ -10,34 +10,37 @@ import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.amap.api.navi.model.NaviLatLng
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.biz.R
import com.mogo.och.biz.routing.RoutingServiceManager
import com.mogo.och.biz.routing.bean.EndGrayTaskFeedbackType
import com.mogo.och.biz.routing.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.map.AmapNaviToDestinationModel
import com.mogo.och.common.module.map.ICommonNaviChangedCallback
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.EndGrayTaskFeedbackType
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst
import com.mogo.och.unmanned.taxi.ui.routing.RoutingSwitchModel
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingModel
import com.mogo.och.biz.routing.ui.RoutingSwitchModel
import com.mogo.och.common.module.map.MapMakerManager
import com.mogo.och.common.module.wigets.dialog.CommonDialogStatus
import com.mogo.och.unmanned.taxi.ui.routing.errorpoint.ReportErrorPointView
import com.mogo.och.unmanned.taxi.utils.TaskUtils
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_current_itinerary_end_name
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_current_itinerary_start_name
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_distance_end
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_end_routing
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_routing_name
import kotlinx.android.synthetic.main.unmanned_routing_running.view.actv_submit_task
import kotlinx.android.synthetic.main.unmanned_routing_running.view.goutp_show_routing_info
import kotlinx.android.synthetic.main.unmanned_routing_running.view.include_empty
import kotlinx.android.synthetic.main.unmanned_routing_running.view.naviToStart
import com.mogo.och.biz.routing.ui.errorpoint.ReportErrorPointView
import com.mogo.och.biz.routing.ui.runing.other.TaskRunningView
import com.mogo.och.biz.routing.ui.runing.other.TaskRunningView.Companion
import com.mogo.och.biz.routing.ui.utils.TimeDistanceUtils
import com.mogo.och.common.module.constant.OchCommonConst
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_end_routing
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_current_itinerary_end_name
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_current_itinerary_start_name
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_distance_end
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_routing_name
import kotlinx.android.synthetic.main.biz_taxi_running.view.actv_submit_task
import kotlinx.android.synthetic.main.biz_taxi_running.view.goutp_show_routing_info
import kotlinx.android.synthetic.main.biz_taxi_running.view.include_empty
import kotlinx.android.synthetic.main.biz_taxi_running.view.naviToStart
class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCallback,
class TaxiRunningView: ConstraintLayout, TaxiRunningModel.RoutingRuningCallback,
ICommonNaviChangedCallback {
@@ -54,14 +57,14 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
const val TAG = "RoutingRunningView"
}
private var viewModel: RoutingRunningModel?=null
private var viewModel: TaxiRunningModel?=null
private var swtichViewModel: RoutingSwitchModel?=null
private var closeRouting: CommonDialogStatus?=null
init {
LayoutInflater.from(context).inflate(R.layout.unmanned_routing_running, this, true)
LayoutInflater.from(context).inflate(R.layout.biz_taxi_running, this, true)
initView()
initListener()
}
@@ -84,20 +87,24 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
}
private fun showFeedbackDialog(grayId: Long) {
CallerLogger.d(TAG, "showFeedbackDialog!")
val occurrenceTime = System.currentTimeMillis()
val topActivity = ActivityUtils.getTopActivity()
if(closeRouting==null) {
CallerLogger.d(TAG, "closeRouting is null!")
closeRouting = CommonDialogStatus
.Builder()
.title("路线验证结束")
.tips("请点击按钮反馈验证结果")
.showClose(true)
.cancelTextColor(R.color.taxi_color_FF4E41)
.cancelTextColor(R.color.biz_routing_FF4E41)
.cancelStr("线路不可用")
.confirmStr("线路可用")
.status(CommonDialogStatus.Status.success)
.build(context)
.build(topActivity)
}else{
if(closeRouting?.isShowing==true){
CallerLogger.d(TAG, "closeRouting is showing, return!")
return
}
}
@@ -120,7 +127,9 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
)
}
})
closeRouting?.show()
if(!topActivity.isFinishing() && !topActivity.isDestroyed()) {
closeRouting?.show()
}
}
/**
@@ -132,7 +141,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
}
private fun removeAllMapMarker() {
MapMakerManager.removeAllMapMarkerByOwner(TaxiUnmannedConst.TYPE_MARKER_ROUTING_VERIFY)
MapMakerManager.removeAllMapMarkerByOwner(OchCommonConst.TYPE_MARKER_ROUTING_VERIFY)
}
private fun initStartNaviToStationParam(
@@ -162,16 +171,8 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
*/
private fun updateCurrentTaskTripInfo(meters: Long, timeInSecond: Long) {
UiThreadHandler.post {
CallerLogger.d(
TAG,
"updateCurrentTaskTripInfo, taskUtil, ${
TaskUtils.getCurrentTaskTripHtml(
meters,
timeInSecond
)
}"
)
actv_distance_end.text = "${TaskUtils.getCurrentTaskDistance(meters)} ${TaskUtils.getCurrentTaskTime(timeInSecond)}"
CallerLogger.d(TAG, "updateCurrentTaskTripInfo, taskUtil, ${TimeDistanceUtils.getCurrentTaskTripHtml(meters, timeInSecond)}")
actv_distance_end.text = "${TimeDistanceUtils.getCurrentTaskDistance(meters)} ${TimeDistanceUtils.getCurrentTaskTime(timeInSecond)}"
}
}
@@ -188,7 +189,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
resourceId: Int
) {
if (isAdd) {
MapMakerManager.addMapMaker(TaxiUnmannedConst.TYPE_MARKER_ROUTING_VERIFY, uuid, lat, lon, resourceId)
MapMakerManager.addMapMaker(OchCommonConst.TYPE_MARKER_ROUTING_VERIFY, uuid, lat, lon, resourceId)
} else {
MapMakerManager.removeMapMaker(uuid, lat, lon)
}
@@ -198,7 +199,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingRunningModel::class.java)
ViewModelProvider(it).get(TaxiRunningModel::class.java)
}
swtichViewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RoutingSwitchModel::class.java)
@@ -223,7 +224,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
override fun reInitNaviAmap(isPlay: Boolean, isRestart: Boolean) {
CallerLogger.d(TAG, "isPlay = $isPlay, isRestart=$isRestart")
if (!isRestart) {
TaxiRoutingModel.startNaviToEndStationByAMap(false)
RoutingServiceManager.invokeCallback(false)
return
}
}
@@ -244,11 +245,11 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
it.gcjLon
)
naviToStart.setOnClickListener {
TaxiRoutingModel.startNaviToEndStationByAMap(true)
RoutingServiceManager.invokeCallback(true)
}
setOrRemoveMapMaker(
true,
TaxiUnmannedConst.TAXI_ROUTING_VERIFY_START_SITE,
OchCommonConst.TAXI_ROUTING_VERIFY_START_SITE,
it.wgs84Lat,
it.wgs84Lon,
R.raw.star_marker
@@ -258,7 +259,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
data.grayLineBean.endSite?.also {
setOrRemoveMapMaker(
true,
TaxiUnmannedConst.TAXI_ROUTING_VERIFY_END_SITE,
OchCommonConst.TAXI_ROUTING_VERIFY_END_SITE,
it.wgs84Lat,
it.wgs84Lon,
R.raw.end_marker
@@ -271,7 +272,7 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
override fun onSubmitEndTaskSuccess() {
ToastUtils.showLong("结束任务成功")
TaxiRoutingModel.startNaviToEndStationByAMap(false)
RoutingServiceManager.invokeCallback(false)
// 移除高德导航计算距离
AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi()
swtichViewModel?.showRoutingSelectView()

View File

@@ -0,0 +1,112 @@
package com.mogo.och.biz.routing.ui.utils
import android.text.Spanned
import androidx.core.text.HtmlCompat
import com.mogo.eagle.core.utilcode.util.DateTimeUtils
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.NumberFormatUtil
import java.util.Calendar
import kotlin.math.ceil
import kotlin.math.roundToInt
object TimeDistanceUtils {
fun getCurrentTaskDistance(meters: Long):String{
var dis = "0"
var disUnit = "公里"
if (meters > 0) {
if (meters / 1000 < 1) {
disUnit = ""
dis = meters.toFloat().roundToInt().toString()
} else {
disUnit = "公里"
dis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
}
}
return "${dis}${disUnit}"
}
fun getCurrentTaskTime(timeInSecond: Long):String{
val min = ceil(timeInSecond.toDouble() / 60f).toInt()
return "${min}分钟"
}
/**
* 剩余里程和剩余时间 html
*/
fun getCurrentTaskTripHtml(meters: Long, timeInSecond: Long): Spanned {
var dis = "0"
var disUnit = "公里"
if (meters > 0) {
if (meters / 1000 < 1) {
disUnit = ""
dis = meters.toFloat().roundToInt().toString()
} else {
disUnit = "公里"
dis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
}
}
val min = ceil(timeInSecond.toDouble() / 60f).toInt()
val strHtml =
("<font color=\"#CAD6FF\">里程 </font>"
+ "<b><font color=\"#FFFFFF\">"
+ dis + "</font></b>"
+ "<font color=\"#CAD6FF\"> "
+ disUnit + "</font>"
+ "<font color=\"#CAD6FF\">,剩余 </font>"
+ "<b><font color=\"#FFFFFF\">"
+ min + "</font></b>"
+ "<font color=\"#CAD6FF\"> 分钟</font>")
return HtmlCompat.fromHtml(strHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun getCurrentTaskWaitTimeHtml(): Spanned {
val currentCale = DateTimeUtils.getCurrentDateTime()
val currentDay =
DateTimeUtil.formatCalendarToString(currentCale, DateTimeUtil.yyyy_MM_dd)
currentCale.add(Calendar.MINUTE, 10)
val strHtml13: String = if (currentDay == DateTimeUtil.formatCalendarToString(
currentCale,
DateTimeUtil.yyyy_MM_dd
)
) {
("<font color=\"#CAD6FF\">免费等待至 </font>"
+ "<b><font color=\"#FFFFFF\"><big>" + DateTimeUtil.formatCalendarToString(
currentCale,
DateTimeUtil.HH_mm
) + "</big></b></font>")
} else {
("<font color=\"#CAD6FF\">免费等待至</font>"
+ "<font color=\"#FFFFFF\"><big>" + DateTimeUtil.formatCalendarToString(
currentCale,
DateTimeUtil.MM_dd_HH_mm
) + "</big></font>")
}
return HtmlCompat.fromHtml(strHtml13, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun getCurrentTaskTotalAndDurationHtml(mileage: Float, duration: Int): Spanned {
val strHtml =
("<font color=\"#CAD6FF\">全程 </font>" + "<font color=\"#FFFFFF\"> $mileage </font>" + "<font color=\"#CAD6FF\"> 公里 </font>"
+ "<font color=\"#CAD6FF\">,总用时 </font>" + "<font color=\"#FFFFFF\"> $duration </font>" + "<font color=\"#CAD6FF\"> 分钟</font>")
return HtmlCompat.fromHtml(strHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun getCurrentTaskPhoneNumAndPassengerCountHtml(phoneNum: String, passengerSize: Int): Spanned {
return HtmlCompat.fromHtml(
"<font color=\"#FFFFFF\"> " + phoneNum + "</font>" +
"<font color=\"#6473B2\"> | </font>" +
"<font color=\"#FFFFFF\">" + passengerSize + "" + "</font>",
HtmlCompat.FROM_HTML_MODE_LEGACY
)
}
fun getNextTaskPhoneNumAndPassengerCountHtml(phoneNum: String, passengerSize: Int): Spanned {
return HtmlCompat.fromHtml(
"<font color=\"#FFFFFF\"> " + phoneNum + "</font>" +
"<font color=\"#6473B2\"> | </font>" +
"<font color=\"#FFFFFF\">" + passengerSize + "" + "</font>",
HtmlCompat.FROM_HTML_MODE_LEGACY
)
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/road_video_bg"
tools:parentTag="FrameLayout">
<com.mogo.och.biz.media.video.ads.AdVideoPlayer
android:visibility="gone"
android:id="@+id/adVideoPlayer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.appcompat.widget.AppCompatImageView
android:visibility="gone"
android:id="@+id/imagePlayer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>

View File

@@ -3,17 +3,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 图片或视频广告-->
<com.mogo.och.common.module.wigets.media.MediaLoopPlayView
android:id="@+id/imageVideoRotationView"
<com.mogo.och.biz.media.video.ads.AdMediaView
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"/>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/acb_add_site_video"
android:text="添加视频"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_width="@dimen/dp_100"

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/biz_routing_FF4E41" android:state_pressed="true"/>
<item android:color="@color/biz_routing_FF4E41" android:state_pressed="false"/>
<item android:color="@color/biz_routing_FF4E41"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/biz_routing_2eacff" android:state_pressed="true"/>
<item android:color="@color/biz_routing_2eacff" android:state_pressed="false"/>
<item android:color="@color/biz_routing_2eacff"/>
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/biz_routing_4D000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/biz_routing_80000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/biz_button_selected"/>
<item android:state_pressed="false" android:drawable="@drawable/biz_button_normal"/>
<item android:state_checked="true" android:drawable="@drawable/biz_button_selected"/>
<item android:state_checked="false" android:drawable="@drawable/biz_button_normal"/>
<item android:drawable="@drawable/biz_button_normal"/>
</selector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/common_color_4D000000"/>
<stroke android:color="@color/common_2EACFF" android:width="@dimen/dp_2"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/common_color_4D000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/biz_input_order_id_check"/>
<item android:state_pressed="false" android:drawable="@drawable/biz_input_order_id_normal"/>
<item android:state_checked="true" android:drawable="@drawable/biz_input_order_id_check"/>
<item android:state_checked="false" android:drawable="@drawable/biz_input_order_id_normal"/>
<item android:drawable="@drawable/biz_input_order_id_normal"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/biz_routing_4D000000" />
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:endColor="#660043FF"
android:startColor="#0028345E" />
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:endColor="#CC0043FF"
android:startColor="#0028345E" />
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/bus_switch_task_selected"/>
<item android:state_pressed="false" android:drawable="@drawable/bus_switch_task_normal"/>
<item android:state_checked="true" android:drawable="@drawable/bus_switch_task_selected"/>
<item android:state_checked="false" android:drawable="@drawable/bus_switch_task_normal"/>
<item android:drawable="@drawable/bus_switch_task_normal"/>
</selector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/bus_switch_task_selected"/>
<item android:state_pressed="false" android:drawable="@drawable/bus_switch_task_normal"/>
<item android:state_checked="true" android:drawable="@drawable/bus_switch_task_selected"/>
<item android:state_checked="false" android:drawable="@drawable/bus_switch_task_normal"/>
<item android:drawable="@drawable/bus_switch_task_normal"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/common_color_4D000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:endColor="#CC0043FF"
android:startColor="#0028345E" />
<corners android:radius="@dimen/dp_30" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/bus_switch_line_selected"/>
<item android:state_pressed="false" android:drawable="@drawable/bus_switch_line_normal"/>
<item android:drawable="@drawable/bus_switch_line_normal"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/common_color_4D000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/common_80000000"/>
<corners android:radius="@dimen/dp_30"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@dimen/dp_30"/>
<solid android:color="@color/common_color_4D000000"/>
</shape>

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/dp_880"
android:layout_height="match_parent"
tools:layout_height="@dimen/dp_966"
tools:background="@drawable/bus_switch_line_normal"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/bus_task_running_line_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="@dimen/dp_45"
android:layout_marginStart="@dimen/dp_54"
android:singleLine="true"
android:ellipsize="end"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@+id/actv_running_task_time"
android:layout_marginEnd="@dimen/dp_140"
android:layout_marginTop="@dimen/dp_37"
android:textColor="@color/white"
tools:text="线路名称"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_running_task_last_station"
android:textColor="@color/common_B3FFFFFF"
android:textSize="@dimen/dp_36"
app:layout_constraintStart_toStartOf="@+id/bus_task_running_line_name"
app:layout_constraintTop_toBottomOf="@+id/bus_task_running_line_name"
android:layout_marginTop="@dimen/dp_11"
tools:text="往新街口方向"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/actv_running_task_time"
android:gravity="center"
android:layout_marginEnd="@dimen/dp_54"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@dimen/dp_2"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_100">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_submit_task"
android:layout_width="@dimen/dp_200"
android:layout_height="@dimen/dp_80"
app:pressed_enabled="false"
android:gravity="center"
android:text="问题打点"
android:background="@drawable/biz_button_selector"
android:textColor="@color/white"
android:textSize="@dimen/dp_40" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rl_running_task_station_list"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0"
android:layout_marginStart="@dimen/dp_54"
android:layout_marginEnd="@dimen/dp_52"
app:layout_constraintTop_toBottomOf="@+id/actv_running_task_last_station"
app:layout_constraintBottom_toTopOf="@+id/aciv_task_leave_station_slide_bg"
android:layout_marginTop="@dimen/dp_22"
android:layout_marginBottom="@dimen/dp_46"/>
<com.mogo.och.common.module.wigets.CommonSlideView
android:id="@+id/aciv_task_leave_station_slide_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:assetsfolder="images"
app:slide_title="@string/common_leave_station"
android:layout_marginBottom="@dimen/dp_46"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_arriver_station"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:gravity="center"
android:textSize="@dimen/dp_40"
android:textColor="@color/white"
android:background="@drawable/bus_running_task_arrive_station_selector"
android:layout_marginBottom="@dimen/dp_46"
android:layout_marginStart="@dimen/dp_54"
android:text="@string/common_arrive_station"
android:layout_width="@dimen/dp_474"
android:layout_height="@dimen/dp_120"/>
<com.mogo.och.common.module.wigets.loading.LoadingViewSmall
android:id="@+id/loading_arrive_station"
android:src="@drawable/common_biz_loading_samll"
app:layout_constraintTop_toTopOf="@+id/actv_arriver_station"
app:layout_constraintBottom_toBottomOf="@+id/actv_arriver_station"
app:layout_constraintEnd_toEndOf="@+id/actv_arriver_station"
android:layout_marginEnd="@dimen/dp_30"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_complete_task"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:gravity="center"
android:textSize="@dimen/dp_40"
android:textColor="@color/white"
android:background="@drawable/bus_running_task_complete_selector"
android:layout_marginBottom="@dimen/dp_46"
android:layout_marginEnd="@dimen/dp_54"
android:text="@string/common_complete"
android:layout_width="@dimen/dp_245"
android:layout_height="@dimen/dp_120"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_100"
tools:background="@drawable/bus_switch_line_selector">
<View
android:id="@+id/bg_pass_bg"
app:layout_constraintStart_toStartOf="@+id/aciv_station_head"
app:layout_constraintEnd_toEndOf="@+id/aciv_station_head"
android:background="@color/common_4DFFFFFF"
android:layout_width="@dimen/dp_7"
android:layout_height="match_parent"/>
<View
android:id="@+id/bg_pass_head_bg"
android:layout_marginBottom="@dimen/dp_11"
app:layout_constraintStart_toStartOf="@+id/aciv_station_head_big"
app:layout_constraintEnd_toEndOf="@+id/aciv_station_head_big"
tools:background="@color/light_prompt_red"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/aciv_station_head_big"
android:layout_width="@dimen/dp_7"
android:layout_height="0dp"/>
<View
android:id="@+id/bg_pass_bottom_bg"
app:layout_constraintStart_toStartOf="@+id/aciv_station_head_big"
app:layout_constraintEnd_toEndOf="@+id/aciv_station_head_big"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/aciv_station_head_big"
android:layout_marginTop="@dimen/dp_11"
tools:background="@color/light_prompt_red"
android:layout_width="@dimen/dp_7"
android:layout_height="0dp"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/aciv_station_head"
android:src="@drawable/bus_switch_line_adapter_point"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="@dimen/dp_33"
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/aciv_station_head_big"
android:src="@drawable/bus_runnint_task_start"
app:layout_constraintTop_toTopOf="@+id/aciv_station_head"
app:layout_constraintStart_toStartOf="@+id/aciv_station_head"
app:layout_constraintBottom_toBottomOf="@+id/aciv_station_head"
app:layout_constraintEnd_toEndOf="@+id/aciv_station_head"
android:layout_width="@dimen/dp_45"
android:layout_height="@dimen/dp_45"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_station_name"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/aciv_station_head"
android:layout_marginStart="@dimen/dp_36"
android:layout_marginEnd="@dimen/dp_36"
app:layout_constraintEnd_toEndOf="parent"
android:text="天安门天安门天安门…"
android:singleLine="true"
android:textColor="@color/white"
android:ellipsize="end"
android:textSize="@dimen/dp_45"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_12"
android:background="@drawable/routing_choose_line_shape_select_line_item_bg_normal"
android:background="@drawable/biz_shape_select_line_item_bg_normal"
android:orientation="vertical"
android:paddingStart="@dimen/dp_78"
android:paddingEnd="@dimen/dp_78">
@@ -51,7 +51,7 @@
android:layout_toRightOf="@+id/todayVerifyNumTextView"
android:gravity="right|center_vertical"
android:maxLines="1"
android:textColor="@color/taxi_color_ccb9c3e9"
android:textColor="@color/biz_routing_ccb9c3e9"
android:textSize="@dimen/dp_30"
tools:text="路线累计反馈0可用1不可用" />
</RelativeLayout>

View File

@@ -13,7 +13,7 @@
android:id="@+id/no_routing_data_iv"
android:layout_width="@dimen/dp_386"
android:layout_height="@dimen/dp_350"
android:src="@drawable/no_order_data"
android:src="@drawable/biz_taxi_no_order_data"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

View File

@@ -10,7 +10,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/taxi_routing_uncheck"
android:src="@drawable/biz_taxi_uncheck"
android:layout_width="@dimen/dp_53"
android:layout_height="@dimen/dp_53"/>
<androidx.appcompat.widget.AppCompatTextView

Some files were not shown because too many files have changed in this diff Show More