Merge branch 'refs/heads/dev_robotaxi-d_240912_6.7.0' into dev_robotaxi-d_240912_6.7.2_local

This commit is contained in:
donghongyu-pc
2024-10-17 10:02:36 +08:00
86 changed files with 2115 additions and 330 deletions

View File

@@ -17,6 +17,7 @@ import com.mogo.commons.mvp.MvpFragment
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
import com.mogo.eagle.core.function.hmi.ui.widget.ColdStartView
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
@@ -43,6 +44,7 @@ import kotlinx.android.synthetic.main.biz_login_view.biz_login_svp
import kotlinx.android.synthetic.main.biz_login_view.bv_switch_business
import kotlinx.android.synthetic.main.biz_login_view.cl_login_info
import kotlinx.android.synthetic.main.biz_login_view.eiv_Info
import kotlinx.android.synthetic.main.biz_login_view.viewColdStart
import me.jessyan.autosize.utils.AutoSizeUtils
@@ -106,56 +108,67 @@ class LoginFragment : MvpFragment<LoginFragment?, LoginPresenter?>(), ILoginView
biz_login_svp.setIsTouchWigetFull(false)
biz_login_svp.enableshowProgressDialog = false
biz_login_svp.enableDoubleClick = false
gsyVideoOptionBuilder.setUrl(videoUrl)
.setCacheWithPlay(false)
.setPlayTag("TaxiPassengerArrivedView")
.build(biz_login_svp)
biz_login_svp.setVideoAllCallBack(object : GSYSampleCallBack() {
override fun onAutoComplete(url: String?, vararg objects: Any?) {
if (AppIdentityModeUtils.isT1T2(FunctionBuildConfig.appIdentityMode)) {
biz_login_svp?.setBackgroundResource(R.drawable.biz_login_bg_taxi_end)
}else{
biz_login_svp?.setBackgroundResource(R.drawable.biz_login_bg_bus_end)
}
viewColdStart.setColdStartResultListener(object: ColdStartView.ColdStartResultListener{
override fun coldStartSuccess() {
gsyVideoOptionBuilder.setUrl(videoUrl)
.setCacheWithPlay(false)
.setPlayTag("TaxiPassengerArrivedView")
.build(biz_login_svp)
}
})
if (showLoginInfoAnimator1 == null) {
showLoginInfoAnimator1 = ObjectAnimator.ofFloat(cl_login_info, "alpha", 0f, 1f)
showLoginInfoAnimator1?.interpolator = LinearInterpolator()
}
if (showLoginInfoAnimator2 == null) {
val dp2px = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(), -50f)
showLoginInfoAnimator2 = ObjectAnimator.ofFloat(cl_login_info, "translationY", 0f, dp2px.toFloat())
showLoginInfoAnimator2?.interpolator = DecelerateInterpolator()
}
UiThreadHandler.postDelayed({
cl_login_info?.let {
val animatorSet = AnimatorSet()
animatorSet.playTogether(showLoginInfoAnimator1, showLoginInfoAnimator2)
animatorSet.duration = 500
animatorSet.addListener(object :AnimatorListener{
override fun onAnimationStart(animation: Animator) {
cl_login_info?.visibility = View.VISIBLE
}
override fun onAnimationEnd(animation: Animator) {
biz_login_svp.setVideoAllCallBack(object : GSYSampleCallBack() {
override fun onAutoComplete(url: String?, vararg objects: Any?) {
if (AppIdentityModeUtils.isT1T2(FunctionBuildConfig.appIdentityMode)) {
biz_login_svp?.setBackgroundResource(R.drawable.biz_login_bg_taxi_end)
}else{
biz_login_svp?.setBackgroundResource(R.drawable.biz_login_bg_bus_end)
}
}
override fun onAnimationCancel(animation: Animator) {
}
override fun onAnimationRepeat(animation: Animator) {
}
})
animatorSet.start()
if (showLoginInfoAnimator1 == null) {
showLoginInfoAnimator1 = ObjectAnimator.ofFloat(cl_login_info, "alpha", 0f, 1f)
showLoginInfoAnimator1?.interpolator = LinearInterpolator()
}
if (showLoginInfoAnimator2 == null) {
val dp2px = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(), -50f)
showLoginInfoAnimator2 = ObjectAnimator.ofFloat(cl_login_info, "translationY", 0f, dp2px.toFloat())
showLoginInfoAnimator2?.interpolator = DecelerateInterpolator()
}
UiThreadHandler.postDelayed({
cl_login_info?.let {
val animatorSet = AnimatorSet()
animatorSet.playTogether(showLoginInfoAnimator1, showLoginInfoAnimator2)
animatorSet.duration = 500
animatorSet.addListener(object :AnimatorListener{
override fun onAnimationStart(animation: Animator) {
cl_login_info?.visibility = View.VISIBLE
}
override fun onAnimationEnd(animation: Animator) {
}
override fun onAnimationCancel(animation: Animator) {
}
override fun onAnimationRepeat(animation: Animator) {
}
})
animatorSet.start()
}
},2_000,UiThreadHandler.MODE.QUEUE)
biz_login_svp.startPlayLogic()
}
},2_000,UiThreadHandler.MODE.QUEUE)
override fun coldStartFail() {
}
})
}
inputPhoneNormal()
@@ -304,7 +317,6 @@ class LoginFragment : MvpFragment<LoginFragment?, LoginPresenter?>(), ILoginView
biz_cl_driver_main?.viewTreeObserver?.addOnGlobalLayoutListener(onlayoutListener)
super.onResume()
CallerLogger.d(TAG, "onResume")
biz_login_svp.startPlayLogic()
}
override fun onPause() {

View File

@@ -180,4 +180,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.mogo.eagle.core.function.hmi.ui.widget.ColdStartView
android:id="@+id/viewColdStart"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -15,8 +15,5 @@
<string name="network_error_tip">网络异常,请稍后重试</string>
<string name="request_error_tip">请求出现异常,请稍后重试</string>
<string name="qr_cancel">取消</string>
<string name="bind_driver_qr_title">扫描二维码完成车辆绑定</string>
<string name="biz_log_i_see">我知道了</string>
</resources>

View File

@@ -0,0 +1,7 @@
package com.mogo.och.common.module.biz.media
import com.mogo.och.common.module.wigets.media.MediaItem
interface IMediaDispatch {
fun diapatchMedia(list :MutableList<MediaItem>)
}

View File

@@ -0,0 +1,15 @@
package com.mogo.och.common.module.biz.media
import com.mogo.och.common.module.utils.CallerBase
import com.mogo.och.common.module.wigets.media.MediaItem
object MediaManager : CallerBase<IMediaDispatch>() {
fun postSiteIntroduceInfo(list: MutableList<MediaItem>){
M_LISTENERS.forEach {
val listener = it.value
listener.diapatchMedia(list)
}
}
}

View File

@@ -143,6 +143,16 @@ object OchAutoPilotStatusListenerManager : CallerBase<IOchAutopilotStatusListene
TrajectoryManager.removeDownLoadSuccessLine(lineId)
}
}
when (guardianInfo?.code) {
MogoReport.Code.Error.EMAP.TRA_LOAD_FAILED -> {
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 加载轨迹文件失败", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY)
}
MogoReport.Code.Error.EMAP.TRA_NOT_EXIST -> {
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 无法找到轨迹文件", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY)
}
else -> {}
}
M_LISTENERS.forEach {
val listener = it.value
listener.onAutopilotGuardian(guardianInfo)

View File

@@ -12,6 +12,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.DateTimeUtils
import com.mogo.och.common.module.manager.autopilot.OCHAdasAbilityManager
import com.mogo.och.common.module.manager.autopilot.autopilot.bean.SessionWithTime
import com.mogo.och.common.module.manager.autopilot.line.LineManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.RxUtils
@@ -209,6 +210,7 @@ object OchAutopilotAnalytics {
RxUtils.disposeSubscribe(timeOutDisposable)
timeOutDisposable = RxUtils.createSubscribe(LOOP_PERIOD_15S) {
triggerStartAutopilotFailureEvent("", "15s后app等待超时", System.currentTimeMillis())
LineManager.invokeStartAutopilotTimeOut()
}
}
}

View File

@@ -8,9 +8,11 @@ import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLi
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLonLat
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.data.och.OchInfo
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
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.datacenter.CallerDataCenterBizListener
import com.mogo.eagle.core.function.call.map.CallerMapGlobalTrajectoryDrawManager
import com.mogo.eagle.core.function.call.och.CallerEagleBaseFunctionCall4OchManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
@@ -77,6 +79,10 @@ object LineManager : CallerBase<ILineCallback>() {
private var autopilotId: String by Delegates.observable("") { _, oldValue, newValue ->
if (oldValue != newValue) {
CallerEagleBaseFunctionCall4OchManager.setOchAutopilotOrderId(newValue)
getStations { start, end ->
CallerDataCenterBizListener.invokeOchInfo(OchInfo(0, mutableListOf(start.toMogoLocation(),end.toMogoLocation())))
}
}
}

View File

@@ -0,0 +1,172 @@
package com.mogo.och.common.module.manager.download
import android.annotation.SuppressLint
import android.content.Context
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import com.mogo.commons.AbsMogoApplication
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.eagle.core.utilcode.util.RegexUtils
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.loop.LoopInfo
import com.mogo.och.common.module.utils.FileUtils
import io.reactivex.schedulers.Schedulers
import java.io.File
@SuppressLint("StaticFieldLeak")
object DownloadManager {
private const val TAG = "DownloadManager"
private val waitDownLoadList = mutableListOf<OchDownLoad>()
private val context: Context?=AbsMogoApplication.getApp()
init {
BizLoopManager.setLoopFunction(TAG, LoopInfo(5*60, ::go2Download, scheduler = Schedulers.io()))
}
/**
* 获取本地缓存文件的文件全路径
*/
private fun getFileCacheDir(): String {
// 有些手机需要通过自定义目录
val relativePath = "mogo" + File.separator + "media" + File.separator
val cacheDir = File(Environment.getExternalStorageDirectory(), relativePath)
if (com.mogo.eagle.core.utilcode.util.FileUtils.createOrExistsDir(cacheDir)) {
return cacheDir.absolutePath
}
return FileUtils.getCacheDirectory(context, "") + relativePath
}
/**
* 本地是否已经存在下载完成的文件
*/
private fun isLocalCacheFileExists(mediaUrl: String): Boolean {
val localVideoCacheFilePath =
getCacheFileFullPathByUrl(mediaUrl)
Log.e(TAG, "文件是否存在mediaUrl=$mediaUrl------本地文件:${localVideoCacheFilePath}")
return com.mogo.eagle.core.utilcode.util.FileUtils.isFileExists(localVideoCacheFilePath)
}
/**
* 获取文件缓存的缓存path, 文件名以base64编码避免 中文命名,重复文件名的影响
*/
private fun getCacheFileFullPathByUrl(mediaUrl: String): String {
return getFileCacheDir() +File.separator +getCacheFileName(mediaUrl)
}
/**
* 本地缓存文件的文件名md5编码避免文件名重复或者特殊字符编码问题
*/
private fun getCacheFileName(mediaUrl: String): String {
val fileSuffix = FileUtils.getExtension(mediaUrl)
if (TextUtils.isEmpty(fileSuffix)) {
Log.e(TAG, "getCacheFileName 根据url获取文件后缀不合法mediaUrl=$mediaUrl")
return ""
}
return EncryptUtils.encryptMD5ToString(mediaUrl) + FileUtils.EXTENSION_SEPARATOR + fileSuffix
}
fun clearLocalFile(localVideoPath:String) {
if (com.mogo.eagle.core.utilcode.util.FileUtils.isFileExists(localVideoPath)) {
com.mogo.eagle.core.utilcode.util.FileUtils.delete(localVideoPath)
}
OchChainLogManager.writechainLogDownload("删除本地文件","localVideoPath:${localVideoPath}")
}
fun downloadVideoFile(mediaUrl: String, listener: IDownloadListener?) {
if (!RegexUtils.isURL(mediaUrl)) {
OchChainLogManager.writechainLogDownload("准备下载","url 错误 ${mediaUrl}")
return
}
val downloadUrl = mediaUrl
val downloadDir = getFileCacheDir()
val downloadFileName = getCacheFileName(mediaUrl)+"_temp"
waitDownLoadList.add(OchDownLoad(downloadUrl,downloadDir,downloadFileName,listener))
if(waitDownLoadList.size==1){
go2Download()
}
}
private fun go2Download(){
if(waitDownLoadList.isEmpty()){
return
}
val first = waitDownLoadList.first()
// 临时文件存在 需要删除重新下载
if (com.mogo.eagle.core.utilcode.util.FileUtils.isFileExists(first.downloadDir+File.separator+first.downloadFileName)) {
OchChainLogManager.writechainLogDownload("删除临时文件","文件名称:${first.downloadDir+File.separator+first.downloadFileName}")
clearLocalFile(first.downloadDir+File.separator+first.downloadFileName)
}
// 改名后文件存在 不需要下载
if(isLocalCacheFileExists(first.downloadUrl)){
if(waitDownLoadList.size>0) {
waitDownLoadList.removeFirst()
}
OchChainLogManager.writechainLogDownload("取消下载文件已存在","信息:${first}")
go2Download()
return
}
OchChainLogManager.writechainLogDownload("准备下载","信息:${first}")
DownloadUtils.downLoad(
context,
first.downloadUrl,
first.downloadDir,
first.downloadFileName,
object :IDownloadListener{
override fun onStart(url: String) {
OchChainLogManager.writechainLogDownload("开始下载","url:${url}")
first.listener?.onStart(url)
}
override fun onProgress(url: String, downloaded: Long, total: Long) {
first.listener?.onProgress(url,downloaded,total)
OchChainLogManager.writechainLogDownload("下载中","url:${url}_downloaded${downloaded}_total:${total}",upload = false)
}
override fun onFinished(url: String, path: String) {
OchChainLogManager.writechainLogDownload("下载成功","url:${url}---path:${path}")
if(waitDownLoadList.size>0) {
waitDownLoadList.removeFirst()
}
if(path.endsWith("_temp")){
val tempFile = File(path)
val newName = tempFile.name.replace("_temp","")
com.mogo.eagle.core.utilcode.util.FileUtils.rename(tempFile,newName)
first.listener?.onFinished(url,path.replace("_temp",""))
}
go2Download()
}
override fun onError(url: String, error: String?) {
first.listener?.onError(url,error)
OchChainLogManager.writechainLogDownload("下载错误","url:${url}---error:${error}")
clearLocalFile(first.downloadDir+File.separator+first.downloadFileName)
if(first.downLoadCount>=5){
OchChainLogManager.writechainLogDownload("下载错误5次可终点关注","url:${url}---error:${error}")
if(waitDownLoadList.size>0) {
waitDownLoadList.removeFirst()
}
go2Download()
return
}
first.downLoadCount++
go2Download()
}
}
)
}
}

View File

@@ -0,0 +1,6 @@
package com.mogo.och.common.module.manager.download
import com.mogo.eagle.core.utilcode.download.callback.IDownloadListener
import java.util.UUID
data class OchDownLoad(val downloadUrl:String, val downloadDir:String, val downloadFileName:String, val listener: IDownloadListener?, var downLoadCount:Int = 0)

View File

@@ -33,10 +33,16 @@ object OchChainLogManager {
// 网络接口
const val EVENT_KEY_INFO_Net = "event_key_och_net"
// 下载日志
const val EVENT_KEY_INFO_Download = "event_key_och_download"
// 初始化信息
const val EVENT_KEY_INFO_INIT = "event_key_och_init"
// 局域网内socket 通讯
const val EVENT_KEY_INFO_SOCKET = "analytics_event_och_track_screen_msg"
// 局域网内socket 连接状态流转
const val EVENT_KEY_INFO_SOCKET_CONNECT = "analytics_event_och_track_screen_connect"
@@ -51,19 +57,23 @@ object OchChainLogManager {
const val EVENT_KEY_INFO_DB = "analytics_event_och_db"
fun writeChainLogDb( title: String, info: String) {
fun writeChainLogDb(title: String, info: String) {
writeChainLog(title, info, true, EVENT_KEY_INFO_DB)
}
fun writeChainLogNet(mustUpdate: Boolean, title: String, info: String) {
if(mustUpdate){
if (mustUpdate) {
writeChainLog(title, info, true, EVENT_KEY_INFO_Net)
}else {
} else {
writeChainLog(title, info, DebugConfig.isDebug(), EVENT_KEY_INFO_Net)
}
}
fun writechainLogDownload(title: String, info: String,upload: Boolean=true) {
writeChainLog(title, info, upload, EVENT_KEY_INFO_Download)
}
fun writeChainLogScanner(title: String, changeInfo: String) {
writeChainLog(title, changeInfo, true, EVENT_KEY_INFO_SCANNER)
}

View File

@@ -0,0 +1,76 @@
package com.mogo.och.common.module.wigets
import android.content.Context
import android.graphics.Bitmap
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.LifecycleObserver
import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog
import com.mogo.och.common.module.R
/**
* 带有title, tip,confirm,cancel的dialog
*/
class BindQRCodeDialogNew: BaseFloatDialog, LifecycleObserver {
private var qrBm : AppCompatImageView? = null
private var qrCancel: AppCompatTextView? = null
private var qrTitle: AppCompatTextView? = null
private var clickListener: ClickListener? = null
constructor(builder: Builder,context: Context) : super(context) {
qrTitle?.text = builder.titleStr
qrCancel?.text = builder.cancelStr
qrBm?.setImageBitmap(builder.qrBm)
}
init{
setContentView(R.layout.bind_driver_qr_view)
setCanceledOnTouchOutside(true)
qrTitle = findViewById(R.id.qr_title)
qrBm = findViewById(R.id.qr_bm)
qrCancel = findViewById(R.id.bind_qr_cancel)
qrCancel?.setOnClickListener {
clickListener?.cancel()
dismiss()
}
}
fun setClickListener(clickListener: ClickListener) {
this.clickListener = clickListener
}
interface ClickListener{
fun cancel()
}
class Builder{
var titleStr:String = ""
var cancelStr:String = ""
var qrBm: Bitmap? = null
fun title(title: String) : Builder{
this.titleStr = title
return this
}
fun cancelStr(cancel: String) : Builder{
this.cancelStr = cancel
return this
}
fun qrBm(bm: Bitmap) : Builder{
this.qrBm = bm
return this
}
fun build(context: Context): BindQRCodeDialogNew? {
return BindQRCodeDialogNew(this,context)
}
}
}

View File

@@ -1,17 +1,21 @@
package com.mogo.och.common.module.wigets
package com.mogo.och.common.module.wigets.dialog
import android.content.Context
import android.graphics.Color
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.LifecycleObserver
import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.R
import com.mogo.och.common.module.utils.ResourcesUtils
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
@@ -28,6 +32,7 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
private var commonTips : TextView? = null
private var countDownTxt: AppCompatTextView? = null
private var commonStatus:AppCompatImageView?=null
private var commonClose:AppCompatImageView?=null
private var clickListener: ClickListener? = null
@@ -35,9 +40,14 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
private var mCountdownValue: Int = 0
private var status:Status = Status.ask
private var showCloseView:Boolean = false
constructor(builder: Builder,context: Context) : super(context) {
@ColorRes
private var cancelTextColor:Int = R.color.white
private var status: Status = Status.ask
constructor(builder: Builder, context: Context) : super(context) {
commonTitle?.text = builder.titleStr
commonTips?.text = builder.tipsStr
commonCancel?.text = builder.cancelStr
@@ -45,6 +55,12 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
countDownTxt?.text = builder.countDownValue.toString()
mCountdownValue = builder.countDownValue
status = builder.statusEnum
showCloseView = builder.showClose
cancelTextColor = builder.cancelTextColor
this.clickListener = builder.clickListener
commonCancel?.setTextColor(ResourcesUtils.getColors(cancelTextColor))
when (status) {
Status.ask -> {
commonStatus?.setImageResource(R.drawable.common_dialog_icon_ask)
@@ -52,6 +68,9 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
Status.loading -> {
commonStatus?.setImageResource(R.drawable.common_dialog_status_loading)
}
Status.success -> {
commonStatus?.setImageResource(R.drawable.common_feedback_success)
}
}
if (mCountdownValue > 0){
@@ -59,6 +78,9 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
}else{
countDownTxt?.visibility = View.GONE
}
if(showCloseView){
commonClose?.visibility = View.VISIBLE
}
}
init{
@@ -72,6 +94,7 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
commonTips = findViewById(R.id.common_dialog_content_new)
countDownTxt = findViewById(R.id.common_count_down_new)
commonStatus = findViewById(R.id.common_dialog_status)
commonClose = findViewById(R.id.common_dialog_close)
commonConfirm?.setOnClickListener{
clickListener?.confirm()
@@ -81,6 +104,10 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
clickListener?.cancel()
dismiss()
}
commonClose?.onClick {
clickListener?.dismiss()
dismiss()
}
}
fun setClickListener(clickListener: ClickListener) {
@@ -88,8 +115,9 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
}
interface ClickListener{
fun confirm()
fun cancel()
fun confirm(){}
fun cancel(){}
fun dismiss(){}
}
override fun onAttachedToWindow() {
@@ -151,35 +179,53 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
var confirmStr:String = ""
var cancelStr:String = ""
var countDownValue: Int = 0
var showClose:Boolean =false
var cancelTextColor:Int = Color.WHITE
var clickListener:ClickListener?=null
fun title(title: String) : Builder{
fun title(title: String) : Builder {
this.titleStr = title
return this
}
fun tips(tips: String) : Builder{
fun tips(tips: String) : Builder {
this.tipsStr = tips
return this
}
fun confirmStr(commit: String) : Builder{
fun confirmStr(commit: String) : Builder {
this.confirmStr = commit
return this
}
fun showClose(show:Boolean):Builder{
this.showClose = show
return this
}
fun cancelTextColor(@ColorRes color: Int): Builder {
this.cancelTextColor = color
return this
}
/**
* 不传倒计时没有 >0 有倒计时
*/
fun countdownValue(value: Int): Builder{
fun countdownValue(value: Int): Builder {
this.countDownValue = value
return this
}
fun cancelStr(cancel: String) : Builder{
fun cancelStr(cancel: String) : Builder {
this.cancelStr = cancel
return this
}
fun clickListener(clickListener: ClickListener): Builder {
this.clickListener = clickListener
return this
}
fun build(context: Context): CommonDialogStatus {
return CommonDialogStatus(this,context)
}
@@ -191,7 +237,7 @@ class CommonDialogStatus: BaseFloatDialog, LifecycleObserver {
}
enum class Status{
ask,loading
ask,loading,success
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.och.common.module.wigets.dialog
import android.content.Context
import android.view.View
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.LifecycleObserver
import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.utils.RxUtils
/**
* loading
*/
class CommonFeedbackDialog : BaseFloatDialog, LifecycleObserver {
private var status: Status = Status.success
private val ivFeedbackStatus:AppCompatImageView by lazy { findViewById(R.id.iv_feedback_status) }
private val tvFeedbackStatusDescribe:AppCompatTextView by lazy { findViewById(R.id.tv_feedback_status_describe) }
private var listener:Listener?=null
private var mRunnable:Runnable= Runnable {
ToastUtils.showLong("超时未响应,请求失败")
}
constructor(builder: Builder, context: Context) : super(context) {
tvFeedbackStatusDescribe.text = builder.titleStr
status = builder.statusEnum
listener = builder.listener
when (status) {
Status.success -> {
ivFeedbackStatus.setImageResource(R.drawable.common_feedback_success)
}
Status.fail -> {
ivFeedbackStatus.setImageResource(R.drawable.common_feedback_fail)
}
}
RxUtils.createSubscribe(1_000) {
hide()
this.listener?.cancel()
}
}
init {
setContentView(R.layout.common_feedback_dialog)
setCanceledOnTouchOutside(false)
}
class Builder{
var statusEnum: Status = Status.success
var titleStr:String = ""
var listener:Listener?=null
fun title(title: String) : Builder{
this.titleStr = title
return this
}
fun listener(listener: Listener) : Builder{
this.listener = listener
return this
}
fun build(context: Context): CommonFeedbackDialog {
return CommonFeedbackDialog(this,context)
}
fun status(ask: Status): Builder {
this.statusEnum = ask
return this
}
}
enum class Status{
success,fail,loading
}
interface Listener{
fun cancel()
}
}

View File

@@ -3,14 +3,24 @@ package com.mogo.och.common.module.wigets.media
data class MediaDataList(val medias: MutableList<MediaItem>)
data class MediaItem(
var priority:Int,
var fileUrl: String,
var fileType: Int,
var coverImageUrl: String,
var title: 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 {
@@ -20,4 +30,6 @@ data class MediaItem(
fun isVideoType(): Boolean {
return this.fileType == MEDIA_TYPE_VIDEO
}
}

View File

@@ -6,6 +6,7 @@ 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
@@ -73,9 +74,8 @@ object MediaDataSourceManager {
if (!mMediaDataSourceListenerMap.containsKey(tag)) {
mMediaDataSourceListenerMap[tag] = dataSourceListener
}
val isSassProject = isSassProject()
MediaPlayLogger.printInfoLog("init, 初始化环境 isSassProject=$isSassProject")
if (isSassProject) {
MediaPlayLogger.printInfoLog("init, 初始化环境 isSassProject=${ProjectUtils.isSaas()}")
if (ProjectUtils.isSaas()) {
mNetworkService = MoGoRetrofitFactory.getInstance(OchCommonConst.getEagleMisUrl()).create(IMediaNetworkApi::class.java)
MediaPlayLogger.printInfoLog("init, 开始检查后台配置数据")
startGetMediaDataSourceLoop()
@@ -265,6 +265,7 @@ data class MediaDataResp(val data: List<MediaData>) : BaseData() {
val rotationItemList = mutableListOf<MediaItem>()
mediaDataList?.forEach {
val rotationItem = MediaItem(
priority = MediaItem.PriorityAd,
fileUrl = if (TextUtils.isEmpty(it.file_path)) "" else "${it.file_path}",
fileType = if (it.file_type == 1) MEDIA_TYPE_VIDEO else MEDIA_TYPE_IMAGE,
coverImageUrl = if (TextUtils.isEmpty(it.cover_path)) "" else "${it.cover_path}",

View File

@@ -7,6 +7,7 @@ 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
import com.mogo.och.common.module.utils.FileUtils
import java.io.File
@@ -58,7 +59,7 @@ object MediaFileCacheManager {
* 获取文件缓存的缓存path, 文件名以base64编码避免 中文命名,重复文件名的影响
*/
fun getCacheFileFullPathByUrl(context: Context, mediaUrl: String): String {
return getFileCacheDir(context) + getCacheFileName(mediaUrl)
return getFileCacheDir(context) +File.separator +getCacheFileName(mediaUrl)
}
/**
@@ -67,22 +68,14 @@ object MediaFileCacheManager {
fun isLocalCacheFileExists(context: Context, mediaUrl: String): Boolean {
val localVideoCacheFilePath =
getCacheFileFullPathByUrl(context, mediaUrl)
Log.e(TAG, "文件是否存在mediaUrl=$mediaUrl------本地文件:${localVideoCacheFilePath}")
return com.mogo.eagle.core.utilcode.util.FileUtils.isFileExists(localVideoCacheFilePath)
}
/**
* 下载文件
*/
fun downloadFile(context: Context, mediaUrl: String, listener: IDownloadListener) {
val downloadUrl = mediaUrl
val downloadDir = getFileCacheDir(context)
val downloadFileName = getCacheFileName(mediaUrl)
DownloadUtils.downLoad(
context,
downloadUrl,
downloadDir,
downloadFileName,
listener
)
fun downloadFile(mediaUrl: String, listener: IDownloadListener) {
DownloadManager.downloadVideoFile(mediaUrl,listener)
}
}

View File

@@ -14,6 +14,7 @@ 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.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
class MediaLoopPlayView @JvmOverloads constructor(
@@ -47,6 +48,10 @@ class MediaLoopPlayView @JvmOverloads constructor(
pagerAdapter?.setNewMediaData(list)
}
fun setsetHightPriorityMediaItem(list: MutableList<MediaItem>){
pagerAdapter?.setSiteInfortion(list)
}
fun setPause() {
pagerAdapter?.setPause()
}
@@ -81,6 +86,8 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
//新的数据,在轮播下一次切换的时机完成整体数据的更新
private val mNewDataList: MutableList<MediaItem> = mutableListOf()
private var hightPriorityMediaItem: MutableList<MediaItem> = mutableListOf()
private var mLastViewPagerPosition = -1
private var mImageCountDownTimer: CountDownTimer? = null
@@ -111,6 +118,14 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
mNewDataList.addAll(list)
}
fun setSiteInfortion(list: MutableList<MediaItem>){
hightPriorityMediaItem = list
if(list.isEmpty()){
return
}
startPlayHightPriorityMediaItem(false,1)
}
override fun getCount(): Int {
return mDataList.size
}
@@ -144,7 +159,7 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
mItemViewList.add(imageView)
} else if (item.isVideoType()) {
val videoView = AdvanceVideoView(mContext)
videoView.initVideoUrlData(item.fileUrl, item.coverImageUrl)
videoView.initVideoUrlData(item.fileUrl, item.coverImageUrl,item.priority,item.isTemp)
mItemViewList.add(videoView)
} else {
MediaPlayLogger.printErrorLog( "addItemView 不支持的文件类型:${item.fileType}")
@@ -174,6 +189,125 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
}
}
private fun startPlayHightPriorityMediaItem(isOnVideoError:Boolean,who:Int){
CallerLogger.d(TAG,"检测播放站点介绍:$who")
val currentPosition = mViewPager.currentItem
if(mItemViewList.isEmpty()){
CallerLogger.d(TAG,"view 没有初始化")
return
}
if(hightPriorityMediaItem.size<1){
CallerLogger.d(TAG,"站点视频播放结束没有了")
val currentMediaItem = mDataList[currentPosition]
// 恢复数据 重新播放
when (val itemView = mItemViewList[currentPosition]) {
is AdvanceVideoView -> {
if(itemView.isTempPlayer){
CallerLogger.d(TAG,"删除临时view 和data")
mItemViewList.remove(itemView)
var tempDeleteItem:MediaItem?=null
mDataList.forEach {
if(it.isTemp){
tempDeleteItem = it
}
}
mDataList.remove(tempDeleteItem)
notifyDataSetChanged()
mViewPager.currentItem = 0
mViewPager.setCurrentItem(0, true)
return
}
CallerLogger.d(TAG,"恢复原有视频播放信息${currentMediaItem}")
itemView.onVideoReset()
if (isOnVideoError) {
// 删除上一个缓存的视频
itemView.clearLocalErrorVideo()
}
itemView.initVideoUrlData(currentMediaItem.fileUrl,currentMediaItem.coverImageUrl,currentMediaItem.priority)
itemView.setThumbImageViewVisible()
itemView.startPlayVideo(videoPlayLifecycleCallBack)
}
}
// 播放完高优视频
startLoopPlay()
return
}
val currentMediaItem = hightPriorityMediaItem.first()
when (val itemView = mItemViewList[currentPosition]) {
// 当前正在播放视频
is AdvanceVideoView -> {
MediaPlayLogger.printInfoLog("startPlayHightPriorityMediaItem: AdvanceVideoView, url=${currentMediaItem.fileUrl}")
itemView.onVideoReset()
if (isOnVideoError) {
// 删除上一个缓存的视频
itemView.clearLocalErrorVideo()
}
itemView.initVideoUrlData(currentMediaItem.fileUrl,currentMediaItem.coverImageUrl,currentMediaItem.priority)
itemView.setThumbImageViewVisible()
itemView.startPlayVideo(hightPriorityVideoPlayLifecycleCallBack)
if(hightPriorityMediaItem.size>0) {
hightPriorityMediaItem.removeFirst()
}
}
// 当前正在播放图片
is AdvanceImageView -> {
// 正在播放图片
MediaPlayLogger.printInfoLog("startPlayHightPriorityMediaItem: AdvanceImageView, url=${currentMediaItem.fileUrl}")
// 停止倒计时
cancelImageCountDownTimer()
// 寻找 视频Item
mDataList.forEachIndexed { index, mediaItem ->
// 广告中有视频播放器
if(mediaItem.fileType==MediaItem.MEDIA_TYPE_VIDEO){
mViewPager.post {
mViewPager.currentItem = index
mViewPager.setCurrentItem(index, true)
}
return
}
}
CallerLogger.d(TAG,"没有视频VIew 创建临时View 和data")
// 当前播放列表中没有视频
// TODO: 创建临时view去播放视频
val mediaItem = MediaItem(
MediaItem.PrioritySite,
currentMediaItem.fileUrl,
MediaItem.MEDIA_TYPE_VIDEO,
"",
"",
true
)
mDataList.add(mediaItem)
addItemView(mediaItem)
notifyDataSetChanged()
mViewPager.currentItem = mItemViewList.size-1
mViewPager.setCurrentItem(mItemViewList.size-1, true)
}
else -> {
MediaPlayLogger.printErrorLog("startLoopPlay 不支持的文件类型:${currentMediaItem.fileType}, url=${currentMediaItem.fileUrl}")
}
}
}
private var hightPriorityVideoPlayLifecycleCallBack = object : GSYSampleCallBack() {
override fun onPrepared(url: String?, vararg objects: Any?) {
CallerLogger.d(MediaLoopPlayView.TAG, "onPrepared")
}
override fun onAutoComplete(url: String?, vararg objects: Any?) {
CallerLogger.d(MediaLoopPlayView.TAG, "onAutoComplete")
startPlayHightPriorityMediaItem(false,3)
}
override fun onPlayError(url: String?, vararg objects: Any?) {
super.onPlayError(url, *objects)
CallerLogger.d(MediaLoopPlayView.TAG, "onPlayError, error=${objects}")
startPlayHightPriorityMediaItem(true,4)
}
}
private var videoPlayLifecycleCallBack = object : GSYSampleCallBack() {
override fun onPrepared(url: String?, vararg objects: Any?) {
@@ -245,7 +379,8 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
currentItemView.clearLocalErrorVideo()
}
if (mItemViewList.size == 1) {
currentItemView.startPlay(currentMediaItem.fileUrl)
currentItemView.initVideoUrlData(currentMediaItem.fileUrl,currentMediaItem.coverImageUrl,currentMediaItem.priority)
currentItemView.startPlayVideo(videoPlayLifecycleCallBack)
return
}
}
@@ -303,7 +438,11 @@ class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter
"onPageScrollStateChanged, state = $state, currentItem = $currentPosition, lastPosition = $mLastViewPagerPosition"
)
if (mItemViewList.size > 1) { //多于1才会循环跳转
startLoopPlay()
if(hightPriorityMediaItem.size>0){
startPlayHightPriorityMediaItem(false,5)
}else {
startLoopPlay()
}
mLastViewPagerPosition = currentPosition
}
}

View File

@@ -15,6 +15,7 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
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.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
@@ -37,6 +38,9 @@ class AdvanceVideoView @JvmOverloads constructor(
private var thumbnailImageUrl: String = ""
private var videoUrl: String = ""
private var priority:Int = MediaItem.PrioritySite
var isTempPlayer = false
private set
private val downListener = object : IDownloadListener {
override fun onStart(url: String) {
@@ -61,7 +65,9 @@ class AdvanceVideoView @JvmOverloads constructor(
if (url == videoUrl) {
//下载完成
ThreadUtils.runOnUiThread {
startPlay(Uri.fromFile(File(path)).toString())
if(priority!=MediaItem.PrioritySite) {
startPlay(Uri.fromFile(File(path)).toString())
}
}
MediaPlayLogger.printInfoLog("download finished, 开始播放downloadUrl=${videoUrl}")
} else {//如果当前文件不存在再次去下载当前的
@@ -72,7 +78,9 @@ class AdvanceVideoView @JvmOverloads constructor(
if (FileUtils.isFileExists(path)) {
Logger.d(MediaLoopPlayView.TAG, "video play download, had download, startPlay")
ThreadUtils.runOnUiThread {
startPlay(Uri.fromFile(File(path)).toString())
if(priority!=MediaItem.PrioritySite) {
startPlay(Uri.fromFile(File(path)).toString())
}
}
MediaPlayLogger.printInfoLog("download finished, 开始播放downloadUrl=${videoUrl}")
} else {
@@ -116,14 +124,20 @@ class AdvanceVideoView @JvmOverloads constructor(
containerLayout?.addView(videoPlayerView, videoPlayerViewLayoutParams)
}
fun initVideoUrlData(videoUrl: String, thumbnailImageUrl: String,priority:Int,isTempPlayer:Boolean = false) {
this.isTempPlayer = isTempPlayer
initVideoUrlData(videoUrl,thumbnailImageUrl,priority)
}
/**
* 初始化数据
*/
fun initVideoUrlData(videoUrl: String, thumbnailImageUrl: String) {
fun initVideoUrlData(videoUrl: String, thumbnailImageUrl: String,priority:Int) {
// https://img.zhidaozhixing.com/fileServer/online_car_hailing/1676357834634/5.m4v
// https://img.zhidaozhixing.com/fileServer/online_car_hailing/1676360274126/10.mp4
this.videoUrl = videoUrl
this.thumbnailImageUrl = thumbnailImageUrl
this.priority = priority
}
/**
@@ -132,6 +146,19 @@ class AdvanceVideoView @JvmOverloads constructor(
fun startPlayVideo(onCompletionListener: GSYSampleCallBack) {
//首先根据url检查video是否有已经下载完的本地视频文件
gsyVideoPlayerLifecycleCallback = onCompletionListener
videoPlayerView?.thumbImageView = thumbnailImageView
thumbnailImageView?.setImageResource(R.drawable.video_holder)
thumbnailImageView?.also {
Glide.with(context).asBitmap().load(thumbnailImageUrl)
.apply(
RequestOptions().useUnlimitedSourceGeneratorsPool(true)
.placeholder(R.drawable.video_holder)
.error(R.drawable.video_holder)
.fallback(R.drawable.video_holder)
.centerCrop()
)
.into(it)
}
if (MediaFileCacheManager.isLocalCacheFileExists(context, this.videoUrl)) {
val localVideoCacheFilePath = MediaFileCacheManager.getCacheFileFullPathByUrl(
context, this.videoUrl
@@ -144,19 +171,6 @@ class AdvanceVideoView @JvmOverloads constructor(
MediaLoopPlayView.TAG, "播放视频videoUri=$realUri"
)
} else {
thumbnailImageView?.setImageResource(R.drawable.video_holder)
videoPlayerView?.thumbImageView = thumbnailImageView
thumbnailImageView?.also {
Glide.with(context).asBitmap().load(thumbnailImageUrl)
.apply(
RequestOptions().useUnlimitedSourceGeneratorsPool(true)
.placeholder(R.drawable.video_holder)
.error(R.drawable.video_holder)
.fallback(R.drawable.video_holder)
.centerCrop()
)
.into(it)
}
setThumbImageViewVisible()
startDownLoadVideoFile()
@@ -179,11 +193,7 @@ class AdvanceVideoView @JvmOverloads constructor(
private fun startDownLoadVideoFile() {
//下载视频,下载成功后再播放
MediaPlayLogger.printInfoLog( "startDownLoadVideoFile, downloadUrl=${this.videoUrl}")
MediaFileCacheManager.downloadFile(
context,
videoUrl,
downListener
)
MediaFileCacheManager.downloadFile(videoUrl, downListener)
}
fun clearLocalErrorVideo() {
@@ -199,7 +209,7 @@ class AdvanceVideoView @JvmOverloads constructor(
Logger.d(MediaLoopPlayView.TAG, "startPlay")
gsyVideoPlayerOptionBuilder = GSYVideoOptionBuilder()
gsyVideoPlayerOptionBuilder
?.setUrl(localVideoPath) // "/data/user/0/com.mogo.launcher.f/files/video/"
?.setUrl(localVideoPath) // "/sdcard/mogo/media"
?.setPlayTag(MediaFileCacheManager.getCacheFileName(videoUrl))
?.setCacheWithPlay(false)
?.setThumbPlay(false)

View File

@@ -3,11 +3,19 @@ package com.mogo.och.common.module.wigets.media
import com.mogo.commons.mvp.MvpFragment
import com.mogo.commons.mvp.Presenter
import com.mogo.eagle.core.function.main.MainMoGoApplication
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.R
import com.mogo.och.common.module.biz.media.IMediaDispatch
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.manager.download.DownloadManager
import com.mogo.och.common.module.utils.RxUtils
import com.shuyu.gsyvideoplayer.GSYVideoManager
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_video_player.acb_add_site_video
import kotlinx.android.synthetic.main.fragment_video_player.imageVideoRotationView
/**
@@ -15,7 +23,7 @@ import kotlinx.android.synthetic.main.fragment_video_player.imageVideoRotationVi
* @date: 2022/4/12
*/
class MediaPlayerFragment :
MvpFragment<MediaPlayerFragment?, MediaPlayerPresenter?>() {
MvpFragment<MediaPlayerFragment?, MediaPlayerPresenter?>(), IMediaDispatch {
companion object {
private val TAG = MediaPlayerFragment::class.java.simpleName
@@ -36,6 +44,13 @@ class MediaPlayerFragment :
}
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)
}
MediaManager.addListener(TAG,this)
MediaFileCacheManager.createFileCacheDir(MainMoGoApplication.getApp().applicationContext)
MediaDataSourceManager.init(TAG, object : IMediaDataSourceListener {
override fun onMediaDataSourceChanged(list: List<MediaItem>) {
@@ -56,6 +71,22 @@ class MediaPlayerFragment :
})
}
fun setHightPriorityMediaItem(list: MutableList<MediaItem>){
context?.let {context->
val cacheList = list.filter {
if(!MediaFileCacheManager.isLocalCacheFileExists(context,it.fileUrl)){
DownloadManager.downloadVideoFile(it.fileUrl,null)
}
MediaFileCacheManager.isLocalCacheFileExists(context,it.fileUrl)
}
ThreadUtils.runOnUiThread {
imageVideoRotationView.setsetHightPriorityMediaItem(cacheList.toMutableList())
}
}
}
override fun onPause() {
super.onPause()
imageVideoRotationView.setPause()
@@ -69,8 +100,19 @@ class MediaPlayerFragment :
override fun onDestroy() {
MediaDataSourceManager.unInit(TAG)
GSYVideoManager.releaseAllVideos()
MediaManager.removeListener(TAG)
super.onDestroy()
}
private var fisrtData: Disposable? = null
override fun diapatchMedia(list: MutableList<MediaItem>) {
if(RxUtils.isNotDisposed(fisrtData)){
return
}
fisrtData = RxUtils.createSubscribe(3_000) {}
setHightPriorityMediaItem(list)
}
}
class MediaPlayerPresenter(view: MediaPlayerFragment?) :

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

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:drawable="@drawable/common_button_cancle_click" android:state_pressed="true"/>
<item android:drawable="@drawable/common_button_cancle_normal" android:state_pressed="false"/>
<item android:drawable="@drawable/common_button_cancle_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_99000000"/>
<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,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="@color/common_3B3D44" android:endColor="@color/common_2E323A" android:angle="270"/>
<stroke android:color="@color/color_666C6C6C" android:width="@dimen/dp_2"/>
<corners android:radius="@dimen/dp_50"/>
</shape>

View File

@@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/dp_890"
android:layout_height="@dimen/dp_780"
<com.mogo.och.common.module.wigets.OCHRoundConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="MissingDefaultResource"
android:background="@drawable/bind_driver_qr_bg">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/dp_900"
android:layout_height="@dimen/dp_745"
android:background="@drawable/common_qr_dialog"
app:roundLayoutRadius="@dimen/dp_50">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/qr_title"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bind_driver_qr_title"
android:gravity="center"
android:textSize="@dimen/dp_56"
android:layout_marginTop="@dimen/dp_48"
android:textSize="@dimen/dp_45"
android:layout_marginTop="@dimen/dp_75"
android:textColor="@android:color/white"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
@@ -23,33 +24,27 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/qr_bm"
android:layout_width="@dimen/dp_357"
android:layout_height="@dimen/dp_357"
android:layout_width="@dimen/dp_300"
android:layout_height="@dimen/dp_300"
android:padding="8dp"
android:background="@android:color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qr_title"
app:layout_constraintBottom_toTopOf="@+id/line"/>
<View
android:id="@+id/line"
android:layout_width="match_parent"
android:layout_height="2px"
android:background="@color/qr_line_bg_color"
app:layout_constraintBottom_toTopOf="@+id/bind_qr_cancel"
app:layout_constraintLeft_toLeftOf="parent"/>
app:layout_constraintBottom_toTopOf="@+id/bind_qr_cancel"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bind_qr_cancel"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_162"
android:layout_width="@dimen/dp_356"
android:layout_height="@dimen/dp_120"
android:gravity="center"
android:background="@drawable/common_button_cancle"
android:text="@string/qr_cancel"
android:textSize="@dimen/dp_52"
android:layout_marginBottom="@dimen/dp_65"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textColor="@android:color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.mogo.och.common.module.wigets.OCHRoundConstraintLayout>

View File

@@ -8,6 +8,16 @@
android:background="@drawable/bg_bone_dialog"
app:roundLayoutRadius="@dimen/dp_50">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/common_dialog_close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/common_dialog_close"
android:layout_marginEnd="@dimen/dp_50"
android:layout_marginTop="@dimen/dp_50"
android:layout_width="@dimen/dp_60"
android:layout_height="@dimen/dp_60"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/common_dialog_status"
android:layout_width="@dimen/dp_140"

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_439"
android:layout_height="@dimen/dp_333"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_feedback_status"
android:layout_width="@dimen/dp_140"
android:layout_height="@dimen/dp_140"
android:src="@drawable/common_feedback_success" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_feedback_status_describe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打点成功"
android:textSize="@dimen/dp_38"
android:textColor="@color/white"
android:layout_marginTop="@dimen/dp_28"/>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -1,10 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="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"
android:layout_width="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"
android:layout_height="@dimen/dp_30"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -8,7 +8,8 @@
<color name="taxi_111533">#111533</color>
<color name="taxi_878890">#878890</color>
<color name="taxi_EF262C">#EF262C</color>
<color name="taxi_4D000000">#4D000000</color>
<color name="common_color_4D000000">#4D000000</color>
<color name="common_color_99000000">#99000000</color>
<color name="och_dialog_bg_color">#3B4577</color>
@@ -35,4 +36,6 @@
<color name="common_B3FFFFFF">#B3FFFFFF</color>
<color name="common_cccccc">#CCCCCC</color>
<color name="common_f7151d41">#F7151D41</color>
<color name="common_3B3D44">#3B3D44</color>
<color name="common_2E323A">#2E323A</color>
</resources>

View File

@@ -25,7 +25,7 @@
<string name="request_error_tip">请求出现异常,请稍后重试</string>
<string name="qr_cancel">取消</string>
<string name="bind_driver_qr_title">扫描二维码完成车辆绑定</string>
<string name="bind_driver_qr_title">请扫码绑定</string>
<string name="common_change2_autopilot2_manual">自动驾驶已退出,请立即接管,注意周边环境 小心驾驶</string>
<string name="common_change2_pxjs_manual">平行驾驶已退出,请立即接管,注意周边环境 小心驾驶</string>

View File

@@ -1,5 +1,10 @@
package com.mogo.och.data.bean;
import com.mogo.eagle.core.data.map.MogoLocation;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Objects;
/**
@@ -21,6 +26,7 @@ public class BusStationBean {
private String introduction;// 站点简介
private boolean isPlayTts;
private int pointType; // 1:途径点 2:禁行点 3:站点
private List<SiteIntroduce> videoList;
public String getNameKr() {
return nameKr;
@@ -118,6 +124,14 @@ public class BusStationBean {
isPlayTts = playTts;
}
public List<SiteIntroduce> getVideoList() {
return videoList;
}
public void setVideoList(List<SiteIntroduce> videoList) {
this.videoList = videoList;
}
public int getPointType() {
return pointType;
}
@@ -130,23 +144,40 @@ public class BusStationBean {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BusStationBean that = (BusStationBean) o;
return siteId == that.siteId
&& seq == that.seq
&& Double.compare(that.gcjLon, gcjLon) == 0
&& Double.compare(that.gcjLat, gcjLat) == 0
&& Double.compare(that.lon, lon) == 0
&& Double.compare(that.lat, lat) == 0
&& Double.compare(gcjLon, that.gcjLon) == 0
&& Double.compare(gcjLat, that.gcjLat) == 0
&& Double.compare(lon, that.lon) == 0
&& Double.compare(lat, that.lat) == 0
&& drivingStatus == that.drivingStatus
&& leaving == that.leaving
&& leaving == that.leaving && isPlayTts == that.isPlayTts
&& pointType == that.pointType
&& name.equals(that.name)
&& (nameKr == null || nameKr.equals(that.nameKr));
&& Objects.equals(name, that.name)
&& Objects.equals(nameKr, that.nameKr)
&& Objects.equals(introduction, that.introduction)
&& Objects.equals(videoList, that.videoList);
}
@Override
public int hashCode() {
return Objects.hash(siteId, name, nameKr, seq, gcjLon, gcjLat, lon, lat, drivingStatus, leaving,pointType);
int result = siteId;
result = 31 * result + Objects.hashCode(name);
result = 31 * result + Objects.hashCode(nameKr);
result = 31 * result + seq;
result = 31 * result + Double.hashCode(gcjLon);
result = 31 * result + Double.hashCode(gcjLat);
result = 31 * result + Double.hashCode(lon);
result = 31 * result + Double.hashCode(lat);
result = 31 * result + drivingStatus;
result = 31 * result + Boolean.hashCode(leaving);
result = 31 * result + Objects.hashCode(introduction);
result = 31 * result + Boolean.hashCode(isPlayTts);
result = 31 * result + pointType;
result = 31 * result + Objects.hashCode(videoList);
return result;
}
@Override
@@ -165,6 +196,15 @@ public class BusStationBean {
", introduction='" + introduction + '\'' +
", isPlayTts=" + isPlayTts +
", pointType=" + pointType +
", videoList=" + videoList +
'}';
}
@NotNull
public MogoLocation toMogoLocation() {
MogoLocation result = new MogoLocation();
result.setLatitude(gcjLat);
result.setLongitude(gcjLon);
return result;
}
}

View File

@@ -0,0 +1,59 @@
package com.mogo.och.data.bean;
import java.util.Objects;
public class SiteIntroduce {
private int type;
private String url;
private int seq;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SiteIntroduce that = (SiteIntroduce) o;
return type == that.type && seq == that.seq && Objects.equals(url, that.url);
}
@Override
public int hashCode() {
int result = type;
result = 31 * result + Objects.hashCode(url);
result = 31 * result + seq;
return result;
}
@Override
public String toString() {
return "SiteIntroduce{" +
"type=" + type +
", url='" + url + '\'' +
", seq=" + seq +
'}';
}
}