[广告]
[播放广告+插播站点视频]
This commit is contained in:
yangyakun
2025-07-29 11:48:15 +08:00
parent 03963e18f3
commit 571ea76936
16 changed files with 753 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
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
@@ -20,6 +21,7 @@ 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
@@ -46,6 +48,10 @@ class MediaProvider : MediaService, CallerBase<IVideoListener>() {
removeListener(tag)
}
override fun doSomeAfterAddListener(tag: String, listener: IVideoListener) {
MediaDataSourceManager.dispatchMediaData()
}
override fun postSiteIntroduceInfo(list: MutableList<MediaItem>) {
M_LISTENERS.forEach {
it.value.diapatchMedia(list)
@@ -157,6 +163,10 @@ class MediaProvider : MediaService, CallerBase<IVideoListener>() {
return VideoPlayerFragment()
}
override fun getAdView(context: Context): View {
return AdMediaView(context)
}
override fun createCacheFileDir() {
MediaFileCacheManager.createFileCacheDir(MainMoGoApplication.getApp().applicationContext)
}

View File

@@ -222,6 +222,11 @@ object MediaDataSourceManager {
MediaPlayLogger.printInfoLog("下发新MediaData给监听者dataSize=${newDataList.size}")
}
fun dispatchMediaData(){
MediaPlayLogger.printInfoLog("注册后下发新MediaData给监听者dataSize=${mLastMediaDataSourceList.size}")
MediaServiceManager.invokeMediaSourceDataChange(mLastMediaDataSourceList)
}
}
interface IMediaNetworkApi {

View File

@@ -5,7 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
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.BarUtils
import com.mogo.och.common.module.R
import com.mogo.och.biz.R
class MediaPlayerActivity : AppCompatActivity() {
@@ -13,7 +13,7 @@ class MediaPlayerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_video_player)
setContentView(R.layout.biz_activity_video_player)
val fragment = VideoPlayerFragment()
supportFragmentManager.beginTransaction().add(R.id.videoPlayerContainer, fragment)
.commitAllowingStateLoss()

View File

@@ -53,8 +53,8 @@ class VideoPlayerFragment :
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)
MediaServiceManager.invokeCreateCacheFileDir()
MediaManager.addListener(TAG,this)
MediaDataSourceManager.init()
}

View File

@@ -0,0 +1,190 @@
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.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) {
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) {
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) {
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)
}
}
}

View File

@@ -0,0 +1,303 @@
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.MediaManager
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()
MediaManager.removeListener(TAG)
}
fun setAdMediaCallback(viewCallback: AdMediaViewCallback) {
this.viewCallback = viewCallback
MediaServiceManager.invokeCreateCacheFileDir()
MediaManager.addListener(TAG,this)
MediaDataSourceManager.init()
}
/**
* 分发广告数据
*/
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)
}
}

View File

@@ -0,0 +1,147 @@
package com.mogo.och.biz.media.video.ads
import android.content.Context
import android.media.AudioManager
import android.util.AttributeSet
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.och.biz.media.video.MediaLoopPlayView
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import me.jessyan.autosize.utils.AutoSizeUtils
class AdVideoPlayer : StandardGSYVideoPlayer {
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 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
}
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
}
}
}

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

@@ -41,6 +41,8 @@ import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.biz.birdge.BridgeManager
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.biz.order.OrderManager
import com.mogo.och.common.module.debug.location.MogoLocationExit
import com.mogo.och.common.module.manager.loop.BizLoopManager
@@ -81,6 +83,7 @@ object DebugDataDispatch {
const val vlmImage = "vlmImage"
const val pncAction = "pncAction"
const val collisionRisk = "CollisionRisk"
const val mediaStationMedia = "stationMedia"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "location" --es path "1111/11111"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "pncAction"
@@ -101,6 +104,7 @@ object DebugDataDispatch {
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "ota" --ei "ota" 1
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "vlmMessage" --es message "前方100米有道路施工施工长度100米影响第1、2车道通行。" --ei id 128 --ef time 1880.0
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "vlmImage" --ef time 1880.0
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "stationMedia"
// adb shell am broadcast -a com.hmi.v2x.trafficlight -f 0x011000000 --ei trafficLightCheckType 1 --ei trafficLightCountDown 0 --ez trafficLightIsShow true // 红绿灯
@@ -115,6 +119,15 @@ object DebugDataDispatch {
}
when (type) {
mediaStationMedia -> {
val introductionList = mutableListOf<MediaItem>()
introductionList.add(
MediaItem(
MediaItem.PrioritySite, "https://img.zhidaohulian.com/fileServer/defaultPath/d3468de5e877cc98931611f8cd4ff211/mogo.mp4",
MediaItem.MEDIA_TYPE_VIDEO,"","")
)
MediaManager.postSiteIntroduceInfo(introductionList)
}
collisionRisk -> {
CallerCollisionRiskManager.invokeCollisionRisk()
}

View File

@@ -1,5 +1,7 @@
package com.mogo.och.common.module.biz.media
import android.content.Context
import android.view.View
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.och.common.module.biz.media.data.MediaItem
@@ -101,6 +103,10 @@ object MediaManager {
return mediaService?.getAdFragment()
}
fun getAdView(context: Context): View?{
return mediaService?.getAdView(context)
}
fun createCacheFileDir() {
mediaService?.createCacheFileDir()
}

View File

@@ -1,5 +1,7 @@
package com.mogo.och.common.module.biz.media
import android.content.Context
import android.view.View
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.facade.template.IProvider
import com.mogo.och.common.module.biz.media.data.MediaItem
@@ -63,6 +65,8 @@ interface MediaService : IProvider {
fun getAdFragment() :Fragment
fun getAdView(context: Context): View
fun createCacheFileDir()
fun initMediaData()

View File

@@ -6,7 +6,9 @@ data class MediaItem(
var fileType: Int,
var coverImageUrl: String,
var title: String,
val isTemp: Boolean = false
val isTemp: Boolean = false,
var localPath:String = "",
var pausePosition:Long = 0,
) {
companion object {
const val MEDIA_TYPE_IMAGE = 1
@@ -29,5 +31,23 @@ data class MediaItem(
return this.fileType == MEDIA_TYPE_VIDEO
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MediaItem
if (fileType != other.fileType) return false
if (fileUrl != other.fileUrl) return false
return true
}
override fun hashCode(): Int {
var result = fileType
result = 31 * result + fileUrl.hashCode()
return result
}
}

View File

@@ -8,6 +8,7 @@ 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.mogo.logger.CallerLogger
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
@@ -22,7 +23,8 @@ object DownloadManager {
private const val TAG = "DownloadManager"
private val waitDownLoadList = mutableListOf<OchDownLoad>()
@Volatile
private var waitDownLoadList = mutableListOf<OchDownLoad>()
private val context: Context?=AbsMogoApplication.getApp()
@@ -67,7 +69,7 @@ object DownloadManager {
private fun getCacheFileName(mediaUrl: String): String {
val fileSuffix = FileUtils.getExtension(mediaUrl)
if (TextUtils.isEmpty(fileSuffix)) {
Log.e(TAG, "getCacheFileName 根据url获取文件后缀不合法mediaUrl=$mediaUrl")
CallerLogger.e(TAG,"getCacheFileName 根据url获取文件后缀不合法mediaUrl=$mediaUrl")
return ""
}
return EncryptUtils.encryptMD5ToString(mediaUrl) + FileUtils.EXTENSION_SEPARATOR + fileSuffix
@@ -78,12 +80,14 @@ object DownloadManager {
com.mogo.eagle.core.utilcode.util.FileUtils.delete(localVideoPath)
}
OchChainLogManager.writechainLogDownload("删除本地文件","localVideoPath:${localVideoPath}")
CallerLogger.d(TAG,"删除本地文件 localVideoPath:${localVideoPath}")
}
fun downloadVideoFile(mediaUrl: String, listener: IDownloadListener?) {
if (!RegexUtils.isURL(mediaUrl)) {
OchChainLogManager.writechainLogDownload("准备下载","url 错误 ${mediaUrl}")
CallerLogger.d(TAG,"准备下载 url 错误 ${mediaUrl}")
return
}
val downloadUrl = mediaUrl
@@ -98,6 +102,7 @@ object DownloadManager {
}
@Synchronized
private fun go2Download(){
if(waitDownLoadList.isEmpty()){
return
@@ -106,6 +111,7 @@ object DownloadManager {
// 临时文件存在 需要删除重新下载
if (com.mogo.eagle.core.utilcode.util.FileUtils.isFileExists(first.downloadDir+File.separator+first.downloadFileName)) {
OchChainLogManager.writechainLogDownload("删除临时文件","文件名称:${first.downloadDir+File.separator+first.downloadFileName}")
CallerLogger.d(TAG,"删除临时文件 文件名称:${first.downloadDir+File.separator+first.downloadFileName}")
clearLocalFile(first.downloadDir+File.separator+first.downloadFileName)
}
// 改名后文件存在 不需要下载
@@ -114,10 +120,12 @@ object DownloadManager {
waitDownLoadList.removeFirst()
}
OchChainLogManager.writechainLogDownload("取消下载文件已存在","信息:${first}")
CallerLogger.d(TAG,"取消下载文件已存在 信息:${first}")
go2Download()
return
}
OchChainLogManager.writechainLogDownload("准备下载","信息:${first}")
CallerLogger.d(TAG,"准备下载信息:${first}")
DownloadUtils.downLoad(
context,
first.downloadUrl,
@@ -126,6 +134,7 @@ object DownloadManager {
object :IDownloadListener{
override fun onStart(url: String) {
OchChainLogManager.writechainLogDownload("开始下载","url:${url}")
CallerLogger.d(TAG,"开始下载 url:${url}")
first.listener?.onStart(url)
}
@@ -136,6 +145,7 @@ object DownloadManager {
override fun onFinished(url: String, path: String) {
OchChainLogManager.writechainLogDownload("下载成功","url:${url}---path:${path}")
CallerLogger.d(TAG,"下载成功-url:${url}---path:${path}")
if(waitDownLoadList.size>0) {
waitDownLoadList.removeFirst()
}
@@ -151,9 +161,11 @@ object DownloadManager {
override fun onError(url: String, error: String?) {
first.listener?.onError(url,error)
OchChainLogManager.writechainLogDownload("下载错误","url:${url}---error:${error}")
CallerLogger.d(TAG,"下载成功","下载错误","url:${url}---error:${error}")
clearLocalFile(first.downloadDir+File.separator+first.downloadFileName)
if(first.downLoadCount>=5){
OchChainLogManager.writechainLogDownload("下载错误5次可终点关注","url:${url}---error:${error}")
CallerLogger.d(TAG,"下载错误5次可终点关注","url:${url}---error:${error}")
if(waitDownLoadList.size>0) {
waitDownLoadList.removeFirst()
}

View File

@@ -41,6 +41,7 @@ class PM2BaseFragment :
private var drivingFragment: PM2DrivingInfoFragment? = null
private var hdMapFragment: PM2HPMapFragment? = null
private var mediaFragment: Fragment? = null
private var mediaView: View? = null
// 视频直播流
private val ochTransform = object : OchTransformDispatch {
@@ -99,11 +100,20 @@ class PM2BaseFragment :
childFragmentManager.beginTransaction().add(R.id.hd_map_fragment, hdMapFragment!!)
.show(hdMapFragment!!).commitAllowingStateLoss()
if (mediaFragment == null) {
mediaFragment = MediaManager.Video.getAdFragment()
// if (mediaFragment == null) {
// mediaFragment = MediaManager.Video.getAdFragment()
// }
if (mediaView==null&&context!=null) {
context?.let {
mediaView = MediaManager.Video.getAdView(it)
}
}
childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
.show(mediaFragment!!).commitAllowingStateLoss()
mediaView?.let {
video_fragment.addView(it)
}
// childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
// .show(mediaFragment!!).commitAllowingStateLoss()
test1.onClick {

View File

@@ -43,7 +43,7 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
//启动业务
CallerStartUpManager.initStageOne();
// Crash 日志收集
initCrashConfig();
// initCrashConfig();
initLogConfig();
initTipToast();