diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/MediaProvider.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/MediaProvider.kt index d45ced5549..e4c7eaad9d 100644 --- a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/MediaProvider.kt +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/MediaProvider.kt @@ -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() { removeListener(tag) } + override fun doSomeAfterAddListener(tag: String, listener: IVideoListener) { + MediaDataSourceManager.dispatchMediaData() + } + override fun postSiteIntroduceInfo(list: MutableList) { M_LISTENERS.forEach { it.value.diapatchMedia(list) @@ -157,6 +163,10 @@ class MediaProvider : MediaService, CallerBase() { return VideoPlayerFragment() } + override fun getAdView(context: Context): View { + return AdMediaView(context) + } + override fun createCacheFileDir() { MediaFileCacheManager.createFileCacheDir(MainMoGoApplication.getApp().applicationContext) } diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaDataSourceManager.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaDataSourceManager.kt index 5dc56ad745..6296c8007d 100644 --- a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaDataSourceManager.kt +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaDataSourceManager.kt @@ -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 { diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaPlayerActivity.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaPlayerActivity.kt index 5624e8e5f6..26554d3b75 100644 --- a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaPlayerActivity.kt +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/MediaPlayerActivity.kt @@ -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() diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/VideoPlayerFragment.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/VideoPlayerFragment.kt index 80769e1afd..bdc5a403b8 100644 --- a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/VideoPlayerFragment.kt +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/VideoPlayerFragment.kt @@ -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() } diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaView.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaView.kt new file mode 100644 index 0000000000..319a6d653d --- /dev/null +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaView.kt @@ -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 { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + MediaPlayLogger.printErrorLog("图片加载失败:${e?.message}") + return false + } + + override fun onResourceReady( + resource: Bitmap?, + model: Any?, + target: Target?, + 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) + } + } + +} \ No newline at end of file diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaViewModel.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaViewModel.kt new file mode 100644 index 0000000000..c695aa0524 --- /dev/null +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdMediaViewModel.kt @@ -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() + // 正在播放 + private var currentPlayingIndex = 0 + private var currentPlayingItem:MediaItem?=null + + private var stationInfomation = mutableListOf() + 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) { + // 图片直接加入播放列表 视频检查是否缓存成功 没有缓存先缓存 缓存完再进行播放 + CallerLogger.d(TAG,"收到数据-${list}") + val templateList = mutableListOf() + 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("downListener,percent=$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) { + CallerLogger.d(TAG,"收到数据-${list}") + if(list.isEmpty()){ + return + } + // 开始插播 + if(currentPlayingItem?.isImageType()==true){ + RxUtils.disposeSubscribe(playImageDisposable) + } + val templateList = mutableListOf() + 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("downListener,percent=$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) + + } + + +} + diff --git a/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdVideoPlayer.kt b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdVideoPlayer.kt new file mode 100644 index 0000000000..ba8ab6bcf4 --- /dev/null +++ b/OCH/common/biz/src/main/java/com/mogo/och/biz/media/video/ads/AdVideoPlayer.kt @@ -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, "AdvanceGSYVideoPlayer,hideAllWidget") + } + + override fun changeUiToNormal() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToNormal-hide") + hideWidget() + } + + override fun changeUiToPreparingShow() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToPreparingShow-hide") + hideWidget() + } + + override fun changeUiToPlayingShow() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToPlayingShow") + setCacheImageViewGone() + } + + override fun changeUiToPauseShow() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToPauseShow-hide") +// startPlayLogic() + } + + override fun changeUiToCompleteShow() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToCompleteShow") + setCacheImageViewGone() + } + + override fun changeUiToPlayingBufferingShow() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToPlayingBufferingShow") + hideWidget() + } + + override fun changeUiToError() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,changeUiToError") + 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, "AdvanceGSYVideoPlayer,setCacheImageViewVisible") + setViewShowState(mThumbImageViewLayout, VISIBLE) +// setViewShowState(mThumbImageView, VISIBLE) + } + + fun setCacheImageViewGone() { + Logger.d(MediaLoopPlayView.TAG, "AdvanceGSYVideoPlayer,setCacheImageViewGone") + 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 + } + } +} \ No newline at end of file diff --git a/OCH/common/common/src/main/res/layout/activity_video_player.xml b/OCH/common/biz/src/main/res/layout/biz_activity_video_player.xml similarity index 100% rename from OCH/common/common/src/main/res/layout/activity_video_player.xml rename to OCH/common/biz/src/main/res/layout/biz_activity_video_player.xml diff --git a/OCH/common/biz/src/main/res/layout/biz_ad_video_image.xml b/OCH/common/biz/src/main/res/layout/biz_ad_video_image.xml new file mode 100644 index 0000000000..6efc41a14d --- /dev/null +++ b/OCH/common/biz/src/main/res/layout/biz_ad_video_image.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/common/common/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt b/OCH/common/common/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt index b94666098f..a78e1f1354 100644 --- a/OCH/common/common/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt +++ b/OCH/common/common/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt @@ -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() + introductionList.add( + MediaItem( + MediaItem.PrioritySite, "https://img.zhidaohulian.com/fileServer/defaultPath/d3468de5e877cc98931611f8cd4ff211/mogo.mp4", + MediaItem.MEDIA_TYPE_VIDEO,"","") + ) + MediaManager.postSiteIntroduceInfo(introductionList) + } collisionRisk -> { CallerCollisionRiskManager.invokeCollisionRisk() } diff --git a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaManager.kt b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaManager.kt index 641b39c3bd..ef41a2e131 100644 --- a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaManager.kt +++ b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaManager.kt @@ -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() } diff --git a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaService.kt b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaService.kt index bcdded825c..787be3b1fa 100644 --- a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaService.kt +++ b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/MediaService.kt @@ -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() diff --git a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/data/MediaItem.kt b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/data/MediaItem.kt index 9152b3294d..e8b91949b7 100644 --- a/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/data/MediaItem.kt +++ b/OCH/common/common/src/main/java/com/mogo/och/common/module/biz/media/data/MediaItem.kt @@ -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 + } + } \ No newline at end of file diff --git a/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/download/DownloadManager.kt b/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/download/DownloadManager.kt index 2520ff1378..5b7f66969c 100644 --- a/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/download/DownloadManager.kt +++ b/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/download/DownloadManager.kt @@ -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() + @Volatile + private var waitDownLoadList = mutableListOf() 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() } diff --git a/OCH/shuttle/passenger_weaknet/src/main/java/b2/com/mogo/och/shuttle/weaknet/passenger/ui/PM2BaseFragment.kt b/OCH/shuttle/passenger_weaknet/src/main/java/b2/com/mogo/och/shuttle/weaknet/passenger/ui/PM2BaseFragment.kt index 48f23dbe42..d77c5f028b 100644 --- a/OCH/shuttle/passenger_weaknet/src/main/java/b2/com/mogo/och/shuttle/weaknet/passenger/ui/PM2BaseFragment.kt +++ b/OCH/shuttle/passenger_weaknet/src/main/java/b2/com/mogo/och/shuttle/weaknet/passenger/ui/PM2BaseFragment.kt @@ -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 { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainMoGoApplication.java b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainMoGoApplication.java index 4fa08617f8..80ac75b516 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainMoGoApplication.java +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainMoGoApplication.java @@ -43,7 +43,7 @@ public abstract class MainMoGoApplication extends AbsMogoApplication { //启动业务 CallerStartUpManager.initStageOne(); // Crash 日志收集 - initCrashConfig(); +// initCrashConfig(); initLogConfig(); initTipToast();