Commit 4e7da677 by 王佳洋

1,音频播放页从老的音视频页面移过来的逻辑bug修正

2,音频播放页接口接入
3,老的悬浮窗代码优化
4,老的悬浮窗缺省逻辑补充
5,AudioPlay逻辑梳理
parent d79b500f
...@@ -91,17 +91,22 @@ public class PlayFragment extends Fragment implements View.OnClickListener, ...@@ -91,17 +91,22 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
} }
@Override @Override
public boolean onPreLoad(int playPosition) {
return true;
}
@Override
public void onLoad(Music music) { public void onLoad(Music music) {
onChangeImpl(music); onChangeImpl(music);
} }
@Override @Override
public void onPlayerStart() { public void onStartPlay() {
ivPlay.setSelected(true); ivPlay.setSelected(true);
} }
@Override @Override
public void onPlayerPause() { public void onPausePlay() {
ivPlay.setSelected(false); ivPlay.setSelected(false);
} }
...@@ -206,7 +211,7 @@ public class PlayFragment extends Fragment implements View.OnClickListener, ...@@ -206,7 +211,7 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
} }
void play() { void play() {
AudioPlayer.Companion.get().playPause(); AudioPlayer.Companion.get().playOrPause();
} }
void next() { void next() {
......
...@@ -148,7 +148,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo ...@@ -148,7 +148,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo
override fun videoShowClick(index: Int, data: List<ConfideHomeBodyBean>?) { override fun videoShowClick(index: Int, data: List<ConfideHomeBodyBean>?) {
val dataJson = if (data != null) JSON.toJSONString(data) else null val dataJson = if (data != null) JSON.toJSONString(data) else null
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
PlayerFloatHelper.updatePlayState() PlayerFloatHelper.updatePlayState()
route(mContext, ConfideRoute.R_VIDEO_SHOW, "initPos" to index, "initData" to dataJson) route(mContext, ConfideRoute.R_VIDEO_SHOW, "initPos" to index, "initData" to dataJson)
} }
...@@ -255,7 +255,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo ...@@ -255,7 +255,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo
if (TextUtils.isEmpty(cachePlayUrl)) { if (TextUtils.isEmpty(cachePlayUrl)) {
return return
} }
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
confideHomeView.updataPlayStatu(cacheType, cacheIndex!!, cacheSubIndex, true) confideHomeView.updataPlayStatu(cacheType, cacheIndex!!, cacheSubIndex, true)
} }
...@@ -263,7 +263,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo ...@@ -263,7 +263,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo
* 暂停播放音频文件 * 暂停播放音频文件
*/ */
override fun pauseVoice() { override fun pauseVoice() {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
PlayerFloatHelper.updatePlayState() PlayerFloatHelper.updatePlayState()
//因为9999 类型不存在 所以就能把状态全部置为暂停状态了 偷个懒 //因为9999 类型不存在 所以就能把状态全部置为暂停状态了 偷个懒
confideHomeView.updataPlayStatu(9999, 0, 0, false) confideHomeView.updataPlayStatu(9999, 0, 0, false)
...@@ -272,7 +272,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo ...@@ -272,7 +272,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo
override fun destoryPlayer() { override fun destoryPlayer() {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.playTempData = hashMapOf<String,String>() PlayerFloatHelper.playTempData = hashMapOf<String,String>()
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
floatViewClickListener?.let { PlayerFloatHelper.removeClickListener(it) }; floatViewClickListener?.let { PlayerFloatHelper.removeClickListener(it) };
} }
......
...@@ -14,6 +14,7 @@ tv.danmaku.ijk.media.player_arm64 ...@@ -14,6 +14,7 @@ tv.danmaku.ijk.media.player_arm64
"/> "/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application> <application>
<!--课程首页--> <!--课程首页-->
......
package com.yidianling.course.bean
/**
* 咨询师上线状态
*/
data class CourseConsultant(var doctorId: Int,
var doctorUid: Int,
var doctorName: String,
var doctorHead: String,
var isOnline: Int // 1在线 0不在线
)
\ No newline at end of file
...@@ -740,7 +740,7 @@ class CourseListContainerActivity : BaseActivity(), PtrHandler, LoadMoreHandler ...@@ -740,7 +740,7 @@ class CourseListContainerActivity : BaseActivity(), PtrHandler, LoadMoreHandler
if (!PlayerFloatHelper.isCanClick) { if (!PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(this) PlayerFloatHelper.removeView(this)
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
......
...@@ -16,7 +16,6 @@ import com.ydl.media.audio.model.Music ...@@ -16,7 +16,6 @@ import com.ydl.media.audio.model.Music
import com.ydl.media.view.PlayerFloatHelper import com.ydl.media.view.PlayerFloatHelper
import com.ydl.webview.H5Params import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydlcommon.base.BaseMvpActivity import com.ydl.ydlcommon.base.BaseMvpActivity
import com.ydl.ydlcommon.bean.ShareData import com.ydl.ydlcommon.bean.ShareData
import com.ydl.ydlcommon.data.PlatformDataManager import com.ydl.ydlcommon.data.PlatformDataManager
...@@ -31,12 +30,10 @@ import com.yidianling.course.BuildConfig ...@@ -31,12 +30,10 @@ import com.yidianling.course.BuildConfig
import com.yidianling.course.CourseConstants import com.yidianling.course.CourseConstants
import com.yidianling.course.R import com.yidianling.course.R
import com.yidianling.course.bean.CourseExtraBean import com.yidianling.course.bean.CourseExtraBean
import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.coursePlay.presenter.AudioPlayPresenter import com.yidianling.course.coursePlay.presenter.AudioPlayPresenter
import com.yidianling.course.coursePlay.presenter.IAudioPlayContract import com.yidianling.course.coursePlay.presenter.IAudioPlayContract
import com.yidianling.course.router.CourseIn import com.yidianling.course.router.CourseIn
import com.yidianling.course.widget.CourseListDialog import com.yidianling.course.widget.CourseListDialog
import com.yidianling.course.widget.CourseListListener
import com.yidianling.course.widget.CourseSpeedDialog import com.yidianling.course.widget.CourseSpeedDialog
import com.yidianling.ydl_pay.common.CommonPayDialog import com.yidianling.ydl_pay.common.CommonPayDialog
import jp.wasabeef.glide.transformations.BlurTransformation import jp.wasabeef.glide.transformations.BlurTransformation
...@@ -88,7 +85,7 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -88,7 +85,7 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
mPresenter.share() mPresenter.share()
} }
audio_play.mListener = { playPosition -> audio_play.mListener = { playPosition ->
mPresenter.togglePlaying(playPosition) mPresenter.isCanLoad(playPosition)
} }
} }
...@@ -96,6 +93,11 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -96,6 +93,11 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
CourseIn.loginByOneKeyLogin(mContext, true) CourseIn.loginByOneKeyLogin(mContext, true)
} }
override fun goToConsultantInfo(url: String) {
mPresenter.showFloatView()
NewH5Activity.start(this, H5Params(url, ""))
}
override fun commonPayDialog(userInfo: YdlUserInfo, courseId: String) { override fun commonPayDialog(userInfo: YdlUserInfo, courseId: String) {
CommonPayDialog.Build(mContext) CommonPayDialog.Build(mContext)
.setCourseId(courseId) .setCourseId(courseId)
...@@ -114,8 +116,12 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -114,8 +116,12 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
.setIsTestEnvironment(BuildConfig.DEBUG).build().show() .setIsTestEnvironment(BuildConfig.DEBUG).build().show()
} }
override fun play(playPosition: Int) { override fun setTitle(title: String) {
audio_play.play(playPosition) tv_title.text = title
}
override fun load() {
audio_play.load(mPresenter.getPlayPosition())
} }
override fun buyCourseTipDialog() { override fun buyCourseTipDialog() {
...@@ -171,7 +177,7 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -171,7 +177,7 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
} }
} }
override fun updateView(bean: CourseExtraBean, currentPosition: Int, list: List<CourseMediaBean>, from: Int) { override fun updateView(bean: CourseExtraBean, from: Int) {
bean.let { bean.let {
Glide.with(this) Glide.with(this)
.load(it.pic) .load(it.pic)
...@@ -187,18 +193,20 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -187,18 +193,20 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.apply(RequestOptions.bitmapTransform(RoundedCorners(RxImageTool.dp2px(8f)))) .apply(RequestOptions.bitmapTransform(RoundedCorners(RxImageTool.dp2px(8f))))
.into(iv_pic) .into(iv_pic)
GlideApp.with(this).load(it.doctorHead).error(R.drawable.course_head_place_hold_pic) Glide.with(this).load(it.doctorHead).error(R.drawable.course_head_place_hold_pic)
.into(iv_icon) .into(iv_icon)
tv_title.text = it.title tv_title.text = mPresenter.getPlayList().elementAtOrNull(mPresenter.getPlayPosition())?.title.orEmpty()
tv_name.text = it.doctorName tv_name.text = it.doctorName
iv_icon.setOnClickListener { consultantClick() }
tv_name.setOnClickListener { consultantClick() }
tv_detail.setOnClickListener { _ -> detailClick(it) } tv_detail.setOnClickListener { _ -> detailClick(it) }
iv_detail.setOnClickListener { _ -> detailClick(it) } iv_detail.setOnClickListener { _ -> detailClick(it) }
tv_speed.setOnClickListener { speedClick() } tv_speed.setOnClickListener { speedClick() }
iv_speed.setOnClickListener { speedClick() } iv_speed.setOnClickListener { speedClick() }
tv_list.setOnClickListener { _ -> listClick(it, currentPosition, list) } tv_list.setOnClickListener { _ -> listClick(it) }
iv_list.setOnClickListener { _ -> listClick(it, currentPosition, list) } iv_list.setOnClickListener { _ -> listClick(it) }
audio_play.setData(mPresenter.getPlayPosition(), mPresenter.convertToMusics(), from)
} }
audio_play.setData(currentPosition, mPresenter.convertToMusics(list), bean.isBuy, from)
} }
override fun setNonWifiTips(show: Boolean) { override fun setNonWifiTips(show: Boolean) {
...@@ -209,13 +217,9 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -209,13 +217,9 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
override fun audioPausePlay() = audio_play.pausePlay() override fun audioPausePlay() = audio_play.pausePlay()
override fun getAudioPath(): String = audio_play.getAudioMusic()?.path.orEmpty()
override fun getAudioMusic(): Music? = audio_play.getAudioMusic() override fun getAudioMusic(): Music? = audio_play.getAudioMusic()
override fun close() { override fun close() = finish()
finish()
}
private fun detailClick(extra: CourseExtraBean) { private fun detailClick(extra: CourseExtraBean) {
if (TextUtils.isEmpty(extra.id)) { if (TextUtils.isEmpty(extra.id)) {
...@@ -239,25 +243,21 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon ...@@ -239,25 +243,21 @@ class AudioPlayActivity : BaseMvpActivity<IAudioPlayContract.View, IAudioPlayCon
}, "courseSpeed") }, "courseSpeed")
} }
private fun listClick(extra: CourseExtraBean, currentPosition: Int, playList: List<CourseMediaBean>) { private fun listClick(extra: CourseExtraBean) {
extra.let { extra.let {
showFragment(mCourseListDialog?.also { showFragment(mCourseListDialog?.also {
it.setCurrentPosition(currentPosition) it.setCurrentPosition(mPresenter.getPlayPosition())
} ?: CourseListDialog().also { dialog -> } ?: CourseListDialog().also { dialog ->
mCourseListDialog = dialog mCourseListDialog = dialog
mCourseListDialog?.setData(it.isBuy, currentPosition, playList) dialog.setData(it.isBuy, mPresenter.getPlayPosition(), mPresenter.getPlayList())
dialog.mListener = object : CourseListListener { dialog.mView = this
override fun addCourseOrder() { dialog.mPresenter = mPresenter
mPresenter.addCourseOrder() }, "courseList")
} }
override fun togglePlaying(position: Int) {
mPresenter.togglePlaying(position)
} }
} private fun consultantClick() {
}, "courseList") mPresenter.getConsultantInfo()
}
} }
override fun onResume() { override fun onResume() {
......
...@@ -392,12 +392,12 @@ class CoursePlayActivity : BaseActivity() { ...@@ -392,12 +392,12 @@ class CoursePlayActivity : BaseActivity() {
try { try {
if (play_type == 1) { if (play_type == 1) {
//视频播放销毁音频服务 //视频播放销毁音频服务
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_CONFIDE || PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_FM) { if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_CONFIDE || PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_FM) {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -484,7 +484,7 @@ class CoursePlayActivity : BaseActivity() { ...@@ -484,7 +484,7 @@ class CoursePlayActivity : BaseActivity() {
if (index < playList.size && this.index != index) { if (index < playList.size && this.index != index) {
if (!playList[index].isDemo && !courPlayBean!!.courseExtra.isBuy) { if (!playList[index].isDemo && !courPlayBean!!.courseExtra.isBuy) {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
if (videoView != null) { if (videoView != null) {
...@@ -521,7 +521,7 @@ class CoursePlayActivity : BaseActivity() { ...@@ -521,7 +521,7 @@ class CoursePlayActivity : BaseActivity() {
frame_video_play.visibility = View.VISIBLE frame_video_play.visibility = View.VISIBLE
frame_audio_play.visibility = View.GONE frame_audio_play.visibility = View.GONE
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
(playVideoView as CoursePlayItemViewVideo)?.play(index) (playVideoView as CoursePlayItemViewVideo)?.play(index)
} }
......
...@@ -2,6 +2,7 @@ package com.yidianling.course.coursePlay.model ...@@ -2,6 +2,7 @@ package com.yidianling.course.coursePlay.model
import com.ydl.ydlcommon.data.http.BaseResponse import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlcommon.mvp.base.BaseModel import com.ydl.ydlcommon.mvp.base.BaseModel
import com.yidianling.course.bean.CourseConsultant
import com.yidianling.course.bean.CourseMediaDetailBean import com.yidianling.course.bean.CourseMediaDetailBean
import com.yidianling.course.coursePlay.presenter.IAudioPlayContract import com.yidianling.course.coursePlay.presenter.IAudioPlayContract
import com.yidianling.course.net.CourseRetrofitUtils import com.yidianling.course.net.CourseRetrofitUtils
...@@ -13,4 +14,8 @@ class AudioPlayModelImpl : BaseModel(), IAudioPlayContract.Model { ...@@ -13,4 +14,8 @@ class AudioPlayModelImpl : BaseModel(), IAudioPlayContract.Model {
return CourseRetrofitUtils.getCoursePlayData(courseId.toString()) return CourseRetrofitUtils.getCoursePlayData(courseId.toString())
} }
override fun getConsultantInfo(courseId: Int): Observable<BaseResponse<CourseConsultant>> {
return CourseRetrofitUtils.getConsultantInfo(courseId.toString())
}
} }
\ No newline at end of file
...@@ -10,9 +10,11 @@ import com.ydl.ydlcommon.data.http.RxUtils ...@@ -10,9 +10,11 @@ import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.mvp.base.BasePresenter import com.ydl.ydlcommon.mvp.base.BasePresenter
import com.ydl.ydlcommon.router.IYDLRouterConstant import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.ydl.ydlcommon.router.YdlCommonRouterManager import com.ydl.ydlcommon.router.YdlCommonRouterManager
import com.ydl.ydlcommon.utils.extend.ifNotNull
import com.ydl.ydlnet.client.observer.CommonObserver import com.ydl.ydlnet.client.observer.CommonObserver
import com.yidianling.common.tools.ToastUtil import com.yidianling.common.tools.ToastUtil
import com.yidianling.course.bean.COURSE_AUDIO import com.yidianling.course.bean.COURSE_AUDIO
import com.yidianling.course.bean.CourseConsultant
import com.yidianling.course.bean.CourseMediaBean import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.bean.CourseMediaDetailBean import com.yidianling.course.bean.CourseMediaDetailBean
import com.yidianling.course.coursePlay.model.AudioPlayModelImpl import com.yidianling.course.coursePlay.model.AudioPlayModelImpl
...@@ -26,8 +28,7 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -26,8 +28,7 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
private val ROUTER_PARAMS = "routerParam" private val ROUTER_PARAMS = "routerParam"
private var mFrom: Int = 0 private var mFrom: Int = 0
private var mReceiverPlayUrl: String? = null // 外部选中要播放的音/视频文件地址 private var mPlayUrl: String? = null // 外部选中要播放的音频文件地址
private var mIsFromFloatView = false // 是否是悬浮窗进入
private var mCourPlayBean: CourseMediaDetailBean? = null private var mCourPlayBean: CourseMediaDetailBean? = null
private val mPlayList: ArrayList<CourseMediaBean> = ArrayList() // 播放列表 private val mPlayList: ArrayList<CourseMediaBean> = ArrayList() // 播放列表
private var mCurrentPosition = 0 private var mCurrentPosition = 0
...@@ -51,19 +52,9 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -51,19 +52,9 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
} }
//正常跳转所传参数 //正常跳转所传参数
mCourseId = it.getIntExtra("course_id", 0) mCourseId = it.getIntExtra("course_id", 0)
mReceiverPlayUrl = it.getStringExtra("coursePlayUrl") mPlayUrl = it.getStringExtra("coursePlayUrl")
mIsFromFloatView = it.getBooleanExtra("isFromFloatView", false) val isFromFloatView = it.getBooleanExtra("isFromFloatView", false)
if (!TextUtils.isEmpty(mReceiverPlayUrl) && mIsFromFloatView) mView.setNonWifiTips(!isFromFloatView)
mView.setNonWifiTips(false)
try {
if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_COURSE
&& mView.audioIsPlaying()
&& TextUtils.isEmpty(mReceiverPlayUrl)
) {
mReceiverPlayUrl = mView.getAudioPath()
}
} catch (e: Exception) {
}
mFrom = it.getIntExtra("from", 0) mFrom = it.getIntExtra("from", 0)
if (mCourseId == 0) { if (mCourseId == 0) {
ToastUtil.toastShort("参数错误") ToastUtil.toastShort("参数错误")
...@@ -99,17 +90,42 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -99,17 +90,42 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
response.data?.let { bean -> response.data?.let { bean ->
mCourPlayBean = bean mCourPlayBean = bean
setPlayList(bean) setPlayList(bean)
if (!TextUtils.isEmpty(mReceiverPlayUrl)) { if (!mPlayUrl.isNullOrEmpty()) {
mCurrentPosition = mPlayList.indexOfLast { val regex = Regex("(?<=video).*?(?=&token)")
TextUtils.equals(mReceiverPlayUrl, it.url) || TextUtils.equals( val playUrl = regex.find(mPlayUrl!!)?.value
mReceiverPlayUrl!!.replace( val position = mPlayList.indexOfLast {
"http", playUrl == regex.find(it.url)?.value
"https"
), it.url
)
} }
mCurrentPosition = if (-1 == position) 0 else position
}
mView.updateView(bean.courseExtra, mFrom)
} ?: let {
ToastUtil.toastShort("解析出错")
}
} else {
ToastUtil.toastShort(response.msg)
}
}
}
})
}
override fun getConsultantInfo() {
mModel.getConsultantInfo(mCourseId)
.compose(RxUtils.applySchedulers())
.subscribe(object : CommonObserver<BaseResponse<CourseConsultant>>() {
override fun onError(s: String?) {}
override fun onSuccess(resp: BaseResponse<CourseConsultant>?) {
resp?.let { response ->
if (response.code == 200) {
response.data?.let { info ->
if (1 == info.isOnline) {
mView.goToConsultantInfo(info.doctorHead)
} else {
ToastUtil.toastShort("该咨询师未上线")
} }
mView.updateView(bean.courseExtra, mCurrentPosition, mPlayList, mFrom)
} ?: let { } ?: let {
ToastUtil.toastShort("解析出错") ToastUtil.toastShort("解析出错")
} }
...@@ -138,19 +154,18 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -138,19 +154,18 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
} }
} }
override fun convertToMusics(list: List<CourseMediaBean>): ArrayList<Music> { override fun convertToMusics(): ArrayList<Music> {
val musics = ArrayList<Music>() val musics = ArrayList<Music>()
try { mCourPlayBean?.courseExtra?.let { extra ->
for (i in list.indices) { mPlayList.forEach { bean ->
musics.add(Music().apply { musics.add(Music().apply {
path = list[i].url path = bean.url
coverPath = mCourPlayBean?.courseExtra?.pic coverPath = extra.pic
title = list[i].title title = bean.title
artist = list[i].doctorName artist = bean.doctorName
canPlay = extra.isBuy || bean.isDemo
}) })
} }
} catch (e: Exception) {
e.printStackTrace()
} }
return musics return musics
} }
...@@ -168,23 +183,26 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -168,23 +183,26 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
mView.commonPayDialog(userInfo, mCourseId.toString()) mView.commonPayDialog(userInfo, mCourseId.toString())
} }
override fun togglePlaying(playPosition: Int) { override fun getPlayPosition(): Int = mCurrentPosition
if (playPosition >= mPlayList.size || playPosition < 0) { override fun getPlayList(): List<CourseMediaBean> = mPlayList
ToastUtil.toastShort("暂无内容")
} else if (mCurrentPosition != playPosition) { override fun togglePlay(playPosition: Int) {
mCurrentPosition = playPosition if (isCanLoad(playPosition)) {
mCourPlayBean?.courseExtra?.let { mView.load()
if (isCanPlay(it.isBuy)) mView.play(mCurrentPosition)
}
} }
} }
private fun isCanPlay(isBuy: Boolean): Boolean { override fun isCanLoad(playPosition: Int): Boolean {
mPlayList.elementAtOrNull(mCurrentPosition)?.let { ifNotNull(
if (!it.isDemo && !isBuy) { mCourPlayBean?.courseExtra,
mPlayList.elementAtOrNull(playPosition)
) { extra, bean ->
if (!bean.isDemo && !extra.isBuy) {
if (mView.audioIsPlaying()) mView.audioPausePlay() if (mView.audioIsPlaying()) mView.audioPausePlay()
mView.buyCourseTipDialog() mView.buyCourseTipDialog()
} else if (it.mediaType == COURSE_AUDIO) { } else if (bean.mediaType == COURSE_AUDIO) {
mCurrentPosition = playPosition
mView.setTitle(bean.title)
return true return true
} }
} }
...@@ -197,11 +215,7 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont ...@@ -197,11 +215,7 @@ class AudioPlayPresenter : BasePresenter<IAudioPlayContract.View, IAudioPlayCont
override fun showFloatView() { override fun showFloatView() {
if (mView.audioIsPlaying() && PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_COURSE) { if (mView.audioIsPlaying() && PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_COURSE) {
mView.getAudioMusic()?.coverPath = mCourPlayBean?.courseExtra?.pic
mView.getAudioMusic()?.artist = mCourPlayBean?.courseExtra?.doctorName
PlayerFloatHelper.playTempData.clear() PlayerFloatHelper.playTempData.clear()
val hashMap = HashMap<String, String>() val hashMap = HashMap<String, String>()
hashMap["course_id"] = mCourseId.toString() hashMap["course_id"] = mCourseId.toString()
hashMap["media_type"] = COURSE_AUDIO.toString() hashMap["media_type"] = COURSE_AUDIO.toString()
......
...@@ -8,6 +8,7 @@ import com.ydl.ydlcommon.mvp.base.IModel ...@@ -8,6 +8,7 @@ import com.ydl.ydlcommon.mvp.base.IModel
import com.ydl.ydlcommon.mvp.base.IPresenter import com.ydl.ydlcommon.mvp.base.IPresenter
import com.ydl.ydlcommon.mvp.base.IView import com.ydl.ydlcommon.mvp.base.IView
import com.ydl.ydlcommon.router.YdlUserInfo import com.ydl.ydlcommon.router.YdlUserInfo
import com.yidianling.course.bean.CourseConsultant
import com.yidianling.course.bean.CourseExtraBean import com.yidianling.course.bean.CourseExtraBean
import com.yidianling.course.bean.CourseMediaBean import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.bean.CourseMediaDetailBean import com.yidianling.course.bean.CourseMediaDetailBean
...@@ -22,7 +23,7 @@ interface IAudioPlayContract { ...@@ -22,7 +23,7 @@ interface IAudioPlayContract {
fun dismissProgressDialog() fun dismissProgressDialog()
fun updateView(bean: CourseExtraBean, currentPosition: Int, list: List<CourseMediaBean>, from: Int) fun updateView(bean: CourseExtraBean, from: Int)
fun setNonWifiTips(show: Boolean) fun setNonWifiTips(show: Boolean)
...@@ -30,19 +31,21 @@ interface IAudioPlayContract { ...@@ -30,19 +31,21 @@ interface IAudioPlayContract {
fun audioPausePlay() fun audioPausePlay()
fun getAudioPath(): String
fun getAudioMusic(): Music? fun getAudioMusic(): Music?
fun loginByOneKeyLogin() fun loginByOneKeyLogin()
fun goToConsultantInfo(url: String)
fun commonPayDialog(userInfo: YdlUserInfo, courseId: String) fun commonPayDialog(userInfo: YdlUserInfo, courseId: String)
fun buyCourseTipDialog() fun buyCourseTipDialog()
fun shareDialog(share: ShareData?) fun shareDialog(share: ShareData?)
fun play(playPosition: Int) fun setTitle(title: String)
fun load()
fun close() fun close()
} }
...@@ -56,21 +59,31 @@ interface IAudioPlayContract { ...@@ -56,21 +59,31 @@ interface IAudioPlayContract {
fun getCoursePlayData() fun getCoursePlayData()
fun getConsultantInfo()
fun addCourseOrder() fun addCourseOrder()
fun togglePlaying(playPosition: Int) fun getPlayPosition(): Int
fun getPlayList(): List<CourseMediaBean>
fun togglePlay(playPosition: Int)
fun isCanLoad(playPosition: Int): Boolean
fun share() fun share()
fun showFloatView() fun showFloatView()
fun convertToMusics(list: List<CourseMediaBean>): ArrayList<Music> fun convertToMusics(): ArrayList<Music>
} }
interface Model : IModel { interface Model : IModel {
fun getCoursePlayData(courseId: Int) : Observable<BaseResponse<CourseMediaDetailBean>> fun getCoursePlayData(courseId: Int): Observable<BaseResponse<CourseMediaDetailBean>>
fun getConsultantInfo(courseId: Int): Observable<BaseResponse<CourseConsultant>>
} }
......
...@@ -124,7 +124,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -124,7 +124,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
NewH5Activity.start(mFragment!!.activity, h5Params) NewH5Activity.start(mFragment!!.activity, h5Params)
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
CourseSendPlugin.sendMsg(false) CourseSendPlugin.sendMsg(false)
return return
} }
...@@ -166,7 +166,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -166,7 +166,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
} }
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
CourseSendPlugin.sendMsg(false) CourseSendPlugin.sendMsg(false)
} }
} }
...@@ -177,7 +177,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -177,7 +177,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
} }
PAUSECOURSEPLAY -> { PAUSECOURSEPLAY -> {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
PlayerFloatHelper.updatePlayState() PlayerFloatHelper.updatePlayState()
} }
} }
...@@ -196,7 +196,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -196,7 +196,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
IOSPOP -> { IOSPOP -> {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
CourseSendPlugin.sendMsg(false) CourseSendPlugin.sendMsg(false)
mFragment!!.activity?.finish() mFragment!!.activity?.finish()
} }
...@@ -207,7 +207,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -207,7 +207,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
if (PlayerFloatHelper.isShow(mFragment!!.requireActivity())) { if (PlayerFloatHelper.isShow(mFragment!!.requireActivity())) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} else { } else {
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
} }
...@@ -248,7 +248,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -248,7 +248,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
if (PlayerFloatHelper.isShow(mFragment!!.requireActivity())) { if (PlayerFloatHelper.isShow(mFragment!!.requireActivity())) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.requireActivity()) PlayerFloatHelper.removeView(mFragment!!.requireActivity())
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -263,7 +263,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler { ...@@ -263,7 +263,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
override fun onPlayFinish() { override fun onPlayFinish() {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
CourseSendPlugin.sendMsg(false) CourseSendPlugin.sendMsg(false)
} }
......
...@@ -24,7 +24,7 @@ class CoursePlayLifecycle : Application.ActivityLifecycleCallbacks { ...@@ -24,7 +24,7 @@ class CoursePlayLifecycle : Application.ActivityLifecycleCallbacks {
if (!PlayerFloatHelper.isCanClick) { if (!PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(activity!!) PlayerFloatHelper.removeView(activity!!)
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} else { } else {
PlayerFloatHelper.showIfPlaying(activity!!) PlayerFloatHelper.showIfPlaying(activity!!)
if (!TextUtils.isEmpty(PlayerFloatHelper.playTempData["course_id"])) { if (!TextUtils.isEmpty(PlayerFloatHelper.playTempData["course_id"])) {
......
...@@ -8,7 +8,6 @@ import com.alibaba.android.arouter.facade.annotation.Route ...@@ -8,7 +8,6 @@ import com.alibaba.android.arouter.facade.annotation.Route
import com.ydl.course.api.ICourseService import com.ydl.course.api.ICourseService
import com.ydl.media.audio.AudioPlayer import com.ydl.media.audio.AudioPlayer
import com.ydl.media.view.PlayerFloatHelper import com.ydl.media.view.PlayerFloatHelper
import com.yidianling.course.bean.COURSE_AUDIO
import com.yidianling.course.courseNew.CourseTopicActivity import com.yidianling.course.courseNew.CourseTopicActivity
import com.yidianling.course.courseNew.mine.MyCourseActivity import com.yidianling.course.courseNew.mine.MyCourseActivity
import com.yidianling.course.coursePlay.AudioPlayActivity import com.yidianling.course.coursePlay.AudioPlayActivity
...@@ -33,7 +32,7 @@ class CourseServiceImp : ICourseService { ...@@ -33,7 +32,7 @@ class CourseServiceImp : ICourseService {
override fun closePlayer() { override fun closePlayer() {
if (AudioPlayer.get().isPlaying){ if (AudioPlayer.get().isPlaying){
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -50,7 +49,7 @@ class CourseServiceImp : ICourseService { ...@@ -50,7 +49,7 @@ class CourseServiceImp : ICourseService {
} }
override fun pause() { override fun pause() {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
override fun sendLoginStatusToFlutter() { override fun sendLoginStatusToFlutter() {
......
...@@ -100,6 +100,13 @@ public class CourseRetrofitUtils { ...@@ -100,6 +100,13 @@ public class CourseRetrofitUtils {
return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).getCoursePlayData(courseId); return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).getCoursePlayData(courseId);
} }
/**
* 获取咨询师上线状态
*/
public static Observable<BaseResponse<CourseConsultant>> getConsultantInfo(String courseId) {
return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).getConsultantInfo(courseId);
}
public static Observable<BaseAPIResponse<CourseSpecialListBean>> specialListRequest(CourseSpecialListParam param) { public static Observable<BaseAPIResponse<CourseSpecialListBean>> specialListRequest(CourseSpecialListParam param) {
List<FormatText> list = NetworkParamsUtils.getPostList(param); List<FormatText> list = NetworkParamsUtils.getPostList(param);
return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).courseSpecialList(NetworkParamsUtils.getMaps(list)); return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).courseSpecialList(NetworkParamsUtils.getMaps(list));
......
...@@ -5,6 +5,7 @@ import com.ydl.ydlcommon.data.http.BaseResponse; ...@@ -5,6 +5,7 @@ import com.ydl.ydlcommon.data.http.BaseResponse;
import com.yidianling.course.bean.CouponHintResponseBean; import com.yidianling.course.bean.CouponHintResponseBean;
import com.yidianling.course.bean.Course; import com.yidianling.course.bean.Course;
import com.yidianling.course.bean.CourseAddOrderBean; import com.yidianling.course.bean.CourseAddOrderBean;
import com.yidianling.course.bean.CourseConsultant;
import com.yidianling.course.bean.CourseCouponBean; import com.yidianling.course.bean.CourseCouponBean;
import com.yidianling.course.bean.CourseListDataBean; import com.yidianling.course.bean.CourseListDataBean;
import com.yidianling.course.bean.CourseMediaDetailBean; import com.yidianling.course.bean.CourseMediaDetailBean;
...@@ -131,6 +132,11 @@ public interface NetApiStore { ...@@ -131,6 +132,11 @@ public interface NetApiStore {
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA) @Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
Observable<BaseResponse<CourseMediaDetailBean>> getCoursePlayData(@Query("courseId") String courseId); Observable<BaseResponse<CourseMediaDetailBean>> getCoursePlayData(@Query("courseId") String courseId);
//获取咨询师上线状态
@GET("auth/course/getCourseDoctorInfo")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
Observable<BaseResponse<CourseConsultant>> getConsultantInfo(@Query("courseId") String courseId);
//课程专题列表 //课程专题列表
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA) @Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
......
...@@ -4,7 +4,6 @@ import android.annotation.SuppressLint ...@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.text.TextUtils import android.text.TextUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.SeekBar import android.widget.SeekBar
...@@ -31,18 +30,16 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -31,18 +30,16 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
private var mSeekBarIsTouch = false private var mSeekBarIsTouch = false
private var mProgress = 0 private var mProgress = 0
var mNonWifiTips = true var mNonWifiTips = true
var mListener: ((playPosition: Int) -> Boolean)? = null
/**
* 切换前调用 -> 判断切换后 音频 是否符合业务条件
* 切换后调用 -> 若 音频 失效,自动切换至下一个,此时仍需判断是否符合业务条件
*/
var mListener: ((playPosition: Int) -> Unit)? = null
init { init {
AudioPlayer.get().addOnPlayEventListener(this) AudioPlayer.get().addOnPlayEventListener(this)
View.inflate(context, R.layout.audio_play_view, this) View.inflate(context, R.layout.audio_play_view, this)
iv_bg.setOnClickListener { iv_bg.setOnClickListener {
AudioPlayer.get().playPause() if (AudioPlayer.get().isPlaying)
AudioPlayer.get().pausePlayer()
else if (AudioPlayer.get().isPausing)
AudioPlayer.get().startPlayer()
} }
iv_rewind.setOnClickListener { iv_rewind.setOnClickListener {
AudioPlayer.get().seekTo(position = AudioPlayer.get().currentPosition.minus(15000)) AudioPlayer.get().seekTo(position = AudioPlayer.get().currentPosition.minus(15000))
...@@ -51,15 +48,15 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -51,15 +48,15 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
AudioPlayer.get().seekTo(position = AudioPlayer.get().currentPosition.plus(15000)) AudioPlayer.get().seekTo(position = AudioPlayer.get().currentPosition.plus(15000))
} }
iv_pre.setOnClickListener { iv_pre.setOnClickListener {
mListener?.invoke(AudioPlayer.get().playPosition - 1) AudioPlayer.get().prev()
} }
iv_next.setOnClickListener { iv_next.setOnClickListener {
mListener?.invoke(AudioPlayer.get().playPosition + 1) AudioPlayer.get().next()
} }
seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
tv_start.text = getStringTime(progress) tv_progress.text = getStringTime(progress)
mProgress = progress mProgress = progress
} }
} }
...@@ -79,21 +76,21 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -79,21 +76,21 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
}) })
} }
fun setData(playPosition: Int, playList: ArrayList<Music>, isAuto: Boolean, from: Int) { fun setData(playPosition: Int, playList: ArrayList<Music>, from: Int) {
if (playList.isEmpty()) return if (playList.isEmpty()) return
setAutoNext(isAuto) AudioPlayer.get().playMode = PlayModeEnum.LIST
AudioPlayer.get().addPlayList(playList) AudioPlayer.get().addPlayList(playList)
if (isPlaying()) mNonWifiTips = false if (isPlaying()) mNonWifiTips = false
if (RxNetTool.isWifi(context)) { if (RxNetTool.isWifi(context)) {
playAudio(from, playPosition, playList) loadAudio(from, playPosition, playList)
} else { } else {
if (mNonWifiTips) { if (mNonWifiTips) {
showNonWifiTips { showNonWifiTips {
mNonWifiTips = false mNonWifiTips = false
playAudio(from, playPosition, playList) loadAudio(from, playPosition, playList)
} }
} else { } else {
playAudio(from, playPosition, playList) loadAudio(from, playPosition, playList)
} }
} }
} }
...@@ -102,16 +99,17 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -102,16 +99,17 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
block.invoke() block.invoke()
} }
private fun playAudio(from: Int, playPosition: Int, playList: ArrayList<Music>) { private fun loadAudio(from: Int, playPosition: Int, playList: ArrayList<Music>) {
if (isPlaying() && (from == 1 || from == 2)) { if (isPlaying() && (from == 1 || from == 2)) {
if (TextUtils.equals(getCurrentUrl(), playList[playPosition].path)) { if (TextUtils.equals(getCurrentUrl(), playList[playPosition].path)) {
seekbar.max = AudioPlayer.get().getDuration().toInt() seekbar.max = AudioPlayer.get().getDuration().toInt()
tv_duration.text = getStringTime(seekbar.max) tv_duration.text = getStringTime(seekbar.max)
displayPlayStatus(R.drawable.course_pause)
} else { } else {
play(playPosition) load(playPosition)
} }
} else { } else {
play(playPosition) load(playPosition)
} }
} }
...@@ -122,36 +120,31 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -122,36 +120,31 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
return AudioPlayer.get().playMusic?.path.orEmpty() return AudioPlayer.get().playMusic?.path.orEmpty()
} }
fun play(index: Int) { fun load(index: Int) {
PlayerFloatHelper.playingType = PlayTypeEnum.PLAY_TYPE_COURSE PlayerFloatHelper.playingType = PlayTypeEnum.PLAY_TYPE_COURSE
AudioPlayer.get().load(index) AudioPlayer.get().load(index)
} }
/** override fun onPreLoad(playPosition: Int): Boolean {
* 设置自动播放下一曲 return mListener?.invoke(playPosition) ?: true
*/
fun setAutoNext(auto: Boolean) {
if (!auto) {
AudioPlayer.get().playMode = PlayModeEnum.SINGLE
} else {
AudioPlayer.get().playMode = PlayModeEnum.LIST_LOOP
}
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onLoad(music: Music) { override fun onLoad(music: Music) {
displayPlayStatus(R.drawable.course_loading5, true) displayPlayStatus(R.drawable.course_loading5, true)
seekbar.progress = 0 seekbar.progress = 0
tv_start.text = "00:00" tv_progress.text = "00:00"
} }
override fun onPlayerStart() { override fun onStartPlay() {
postDelayed({
displayPlayStatus(R.drawable.course_pause)
}, 200) // 为了列表切换结束后还能看到loading效果
} }
override fun onPrepared(duration: Long) { override fun onPrepared(duration: Long) {
seekbar.max = duration.toInt() seekbar.max = duration.toInt()
tv_duration.text = getStringTime(seekbar.max) tv_duration.text = getStringTime(seekbar.max)
mListener?.invoke(AudioPlayer.get().playPosition)
} }
override fun onBufferingUpdate(percent: Int) { override fun onBufferingUpdate(percent: Int) {
...@@ -160,22 +153,20 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) : ...@@ -160,22 +153,20 @@ class AudioPlayView(context: Context, attrs: AttributeSet?) :
override fun onPublish(percent: Int, currentPosition: Long) { override fun onPublish(percent: Int, currentPosition: Long) {
if (!mSeekBarIsTouch) { if (!mSeekBarIsTouch) {
displayPlayStatus(R.drawable.course_pause) val currentProgress = currentPosition.toInt()
seekbar.progress = currentPosition.toInt() seekbar.progress =
tv_start.text = getStringTime(currentPosition.toInt()) if (seekbar.max - currentProgress < 1000) seekbar.max else currentProgress
tv_progress.text = getStringTime(seekbar.progress)
} }
} }
override fun onComplete() { override fun onComplete() {
tv_progress.text = getStringTime(seekbar.max)
} }
override fun onPlayerPause() { override fun onPausePlay() {
if (isPlaying()) {
displayPlayStatus(R.drawable.course_pause)
} else {
displayPlayStatus(R.drawable.course_play) displayPlayStatus(R.drawable.course_play)
} }
}
private fun displayPlayStatus( private fun displayPlayStatus(
@RawRes @DrawableRes @Nullable resourceId: Int, @RawRes @DrawableRes @Nullable resourceId: Int,
......
...@@ -276,7 +276,7 @@ class CourseItemNewView : ConstraintLayout { ...@@ -276,7 +276,7 @@ class CourseItemNewView : ConstraintLayout {
if (PlayerFloatHelper.isShow(mContext)) { if (PlayerFloatHelper.isShow(mContext)) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mContext) PlayerFloatHelper.removeView(mContext)
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} else { } else {
PlayerFloatHelper.removeView(mContext) PlayerFloatHelper.removeView(mContext)
} }
...@@ -313,7 +313,7 @@ class CourseItemNewView : ConstraintLayout { ...@@ -313,7 +313,7 @@ class CourseItemNewView : ConstraintLayout {
if (PlayerFloatHelper.isShow(mContext)) { if (PlayerFloatHelper.isShow(mContext)) {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mContext) PlayerFloatHelper.removeView(mContext)
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -325,7 +325,7 @@ class CourseItemNewView : ConstraintLayout { ...@@ -325,7 +325,7 @@ class CourseItemNewView : ConstraintLayout {
override fun onPlayFinish() { override fun onPlayFinish() {
PlayerFloatHelper.hide() PlayerFloatHelper.hide()
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
override fun onPauseClick() { override fun onPauseClick() {
......
...@@ -12,9 +12,9 @@ import com.ydl.ydlcommon.base.BaseDialogFragment ...@@ -12,9 +12,9 @@ import com.ydl.ydlcommon.base.BaseDialogFragment
import com.ydl.ydlcommon.utils.extend.gone import com.ydl.ydlcommon.utils.extend.gone
import com.ydl.ydlcommon.utils.extend.invisible import com.ydl.ydlcommon.utils.extend.invisible
import com.ydl.ydlcommon.utils.extend.visible import com.ydl.ydlcommon.utils.extend.visible
import com.ydl.ydlcommon.view.dialog.CommonDialog
import com.yidianling.course.R import com.yidianling.course.R
import com.yidianling.course.bean.CourseMediaBean import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.coursePlay.presenter.IAudioPlayContract
import kotlinx.android.synthetic.main.dialog_course_list.* import kotlinx.android.synthetic.main.dialog_course_list.*
import kotlinx.android.synthetic.main.item_course_playlist.view.* import kotlinx.android.synthetic.main.item_course_playlist.view.*
...@@ -23,7 +23,8 @@ import kotlinx.android.synthetic.main.item_course_playlist.view.* ...@@ -23,7 +23,8 @@ import kotlinx.android.synthetic.main.item_course_playlist.view.*
*/ */
class CourseListDialog : BaseDialogFragment() { class CourseListDialog : BaseDialogFragment() {
var mListener: CourseListListener? = null var mView: IAudioPlayContract.View? = null
var mPresenter: IAudioPlayContract.Presenter? = null
var mCurrentPosition = 0 var mCurrentPosition = 0
private var mAdapter: CourseListDialog.CourseListAdapter? = null private var mAdapter: CourseListDialog.CourseListAdapter? = null
private val mCourseList = mutableListOf<CourseMediaBean>() private val mCourseList = mutableListOf<CourseMediaBean>()
...@@ -88,17 +89,12 @@ class CourseListDialog : BaseDialogFragment() { ...@@ -88,17 +89,12 @@ class CourseListDialog : BaseDialogFragment() {
tv_title.text = bean.title tv_title.text = bean.title
setOnClickListener { setOnClickListener {
if (mCurrentPosition == position) return@setOnClickListener if (mCurrentPosition == position) {
if (!bean.isDemo && !mIsBuy) { dismissAllowingStateLoss()
CommonDialog(context) return@setOnClickListener
.setMessage("\n购买课程,获取完整课程内容\n")
.setLeftOnclick("放弃") {}
.setRightClick("购买") {
//跳转支付页
mListener?.addCourseOrder()
} }
.setCancelAble(false) if (!bean.isDemo && !mIsBuy) {
.show() mView?.buyCourseTipDialog()
} else { } else {
PlayProgressUtil.saveProgress( PlayProgressUtil.saveProgress(
context, context,
...@@ -107,7 +103,7 @@ class CourseListDialog : BaseDialogFragment() { ...@@ -107,7 +103,7 @@ class CourseListDialog : BaseDialogFragment() {
) )
mCurrentPosition = position mCurrentPosition = position
notifyDataSetChanged() notifyDataSetChanged()
mListener?.togglePlaying(position) mPresenter?.togglePlay(position)
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
} }
...@@ -119,8 +115,3 @@ class CourseListDialog : BaseDialogFragment() { ...@@ -119,8 +115,3 @@ class CourseListDialog : BaseDialogFragment() {
} }
} }
interface CourseListListener {
fun addCourseOrder()
fun togglePlaying(position: Int)
}
\ No newline at end of file
...@@ -47,11 +47,11 @@ class HPlayView : RelativeLayout, OnPlayerEventListener { ...@@ -47,11 +47,11 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
AudioPlayer.get().addOnPlayEventListener(this) AudioPlayer.get().addOnPlayEventListener(this)
course_audio_play_icon.setOnClickListener { course_audio_play_icon.setOnClickListener {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
img_gif.setOnClickListener { img_gif.setOnClickListener {
if (!AudioPlayer.get().isPlaying) { if (!AudioPlayer.get().isPlaying) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
} }
...@@ -138,6 +138,7 @@ class HPlayView : RelativeLayout, OnPlayerEventListener { ...@@ -138,6 +138,7 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
} }
} }
override fun onPreLoad(playPosition: Int): Boolean = true
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onLoad(music: Music) { override fun onLoad(music: Music) {
...@@ -150,11 +151,11 @@ class HPlayView : RelativeLayout, OnPlayerEventListener { ...@@ -150,11 +151,11 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
text_start_time.text = "00:00" text_start_time.text = "00:00"
} }
override fun onPlayerStart() { override fun onStartPlay() {
setGifVisibity(true) setGifVisibity(true)
} }
override fun onPlayerPause() { override fun onPausePlay() {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
setGifVisibity(true) setGifVisibity(true)
} else { } else {
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
android:id="@+id/tv_name" android:id="@+id/tv_name"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:paddingStart="8dp"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="13sp" android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@id/iv_icon" app:layout_constraintBottom_toBottomOf="@id/iv_icon"
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
android:progress="0" /> android:progress="0" />
<TextView <TextView
android:id="@+id/tv_start" android:id="@+id/tv_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="00:00" tools:text="00:00"
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
android:layout_height="66dp" android:layout_height="66dp"
app:roundPercent="1" app:roundPercent="1"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/tv_start" app:layout_constraintTop_toBottomOf="@id/tv_progress"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:background="@android:color/white"/> android:background="@android:color/white"/>
......
...@@ -591,18 +591,23 @@ public class FMDetailActivity extends BaseActivity implements View.OnClickListen ...@@ -591,18 +591,23 @@ public class FMDetailActivity extends BaseActivity implements View.OnClickListen
} }
@Override @Override
public boolean onPreLoad(int playPosition) {
return true;
}
@Override
public void onLoad(@NotNull Music music) { public void onLoad(@NotNull Music music) {
} }
@Override @Override
public void onPlayerStart() { public void onStartPlay() {
iv_play.setImageResource(R.drawable.fm_stop_2); iv_play.setImageResource(R.drawable.fm_stop_2);
fmSurfaceView.playTimer(); fmSurfaceView.playTimer();
} }
@Override @Override
public void onPlayerPause() { public void onPausePlay() {
iv_play.setImageResource(R.drawable.fm_play_2); iv_play.setImageResource(R.drawable.fm_play_2);
fmSurfaceView.stopTimer(); fmSurfaceView.stopTimer();
} }
......
...@@ -55,7 +55,7 @@ class FMServiceImpl : IFMService { ...@@ -55,7 +55,7 @@ class FMServiceImpl : IFMService {
*/ */
override fun closePlayer() { override fun closePlayer() {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
......
...@@ -27,7 +27,7 @@ class MuseActivity : BaseFlutterActivity() { ...@@ -27,7 +27,7 @@ class MuseActivity : BaseFlutterActivity() {
* 如果正在播放音乐,则停止播放所有音乐 * 如果正在播放音乐,则停止播放所有音乐
*/ */
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -36,6 +36,6 @@ class MuseActivity : BaseFlutterActivity() { ...@@ -36,6 +36,6 @@ class MuseActivity : BaseFlutterActivity() {
/** /**
* 退出冥想模块的时候,关闭音乐播放 * 退出冥想模块的时候,关闭音乐播放
*/ */
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
} }
...@@ -111,7 +111,7 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -111,7 +111,7 @@ class PlayMeditationActivity : BaseActivity() {
PlayerFloatHelper.removeView(mContext) PlayerFloatHelper.removeView(mContext)
PlayerFloatHelper.playTempData.clear() PlayerFloatHelper.playTempData.clear()
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer() mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
......
...@@ -93,7 +93,7 @@ class MusePlugin : MethodChannel.MethodCallHandler { ...@@ -93,7 +93,7 @@ class MusePlugin : MethodChannel.MethodCallHandler {
} }
// 暂停(销毁)音乐 // 暂停(销毁)音乐
ACTION_STOP_MUSIC -> { ACTION_STOP_MUSIC -> {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
// 设置默认时间 // 设置默认时间
ACTION_SET_DEFAULT_TIME -> { ACTION_SET_DEFAULT_TIME -> {
......
package com.yidianling.muse.helper
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.graphics.Point
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.core.view.ViewCompat
import com.alibaba.android.arouter.launcher.ARouter
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.view.PlayTypeEnum
import com.yidianling.common.tools.RxImageTool
class MeditationPlayWindowController {
companion object {
@SuppressLint("StaticFieldLeak")
private var mPlayerFloatView: MeditationFloatWindow? = null
//已添加悬浮窗页面全路径名
private var showingPageName: String? = null
private var wm: WindowManager? = null
var isCanClick = true
var playingType = PlayTypeEnum.PLAY_TYPE_NONE
var playTempData = hashMapOf<String, String>()
/**
* 如果有音频正在播放则显示
*/
fun showIfPlaying(context: Context) {
if (MediaPlayerManager.getInstance(context)?.isPlaying() == true) {
show(context)
mPlayerFloatView?.updatePlayState()
} else {
hide()
}
}
/**
* 显示悬浮控件
*/
fun show(
context: Context,
playTypeEnum: PlayTypeEnum = PlayTypeEnum.PLAY_TYPE_NONE,
playData: HashMap<String, String> = hashMapOf<String, String>()
) {
playingType = playTypeEnum
if (playData.size > 0) {
this.playTempData.putAll(playData)
}
if (mPlayerFloatView == null) {
mPlayerFloatView = MeditationFloatWindow(context)
mPlayerFloatView?.addFloatClickListener(object :
MeditationFloatWindow.FloatViewPlayListener {
override fun onPauseClick() {
}
override fun onStartClick() {
}
override fun onPlayFinish() {
}
})
}
if (showingPageName != context::class.qualifiedName) {
mPlayerFloatView?.resetWm(context)
addFloatToWm(context)
}
mPlayerFloatView?.resetView()
mPlayerFloatView?.visibility = View.VISIBLE
mPlayerFloatView?.setPlayingState()
}
fun hide() {
mPlayerFloatView?.visibility = View.GONE
}
fun addClickListener(listener: MeditationFloatWindow.FloatViewPlayListener) {
mPlayerFloatView?.addFloatClickListener(listener)
}
fun removeClickListener(listener: MeditationFloatWindow.FloatViewPlayListener) {
mPlayerFloatView?.removeFloatClickListener(listener)
}
fun isShow(context: Context): Boolean {
return !TextUtils.isEmpty(showingPageName) && showingPageName == context::class.qualifiedName && mPlayerFloatView?.visibility == View.VISIBLE
}
fun removeView(context: Context) {
if (TextUtils.isEmpty(showingPageName) || showingPageName != context::class.qualifiedName) {
return
}
mPlayerFloatView?.visibility = View.GONE
wm?.removeViewImmediate(mPlayerFloatView)
showingPageName = ""
wm = null
}
fun onDestroy() {
if (mPlayerFloatView != null) {
if (!TextUtils.isEmpty(showingPageName)) {
wm?.removeViewImmediate(mPlayerFloatView)
showingPageName = ""
}
mPlayerFloatView?.onDestroy()
mPlayerFloatView?.removeAllViews()
}
}
fun setPlayingState(context: Context) {
show(context)
mPlayerFloatView?.setPlayingState()
}
fun updatePlayState() {
mPlayerFloatView?.updatePlayState()
}
private fun addFloatToWm(context: Context) {
if (wm != null && !TextUtils.isEmpty(showingPageName)) {
if (ViewCompat.isAttachedToWindow(mPlayerFloatView!!)) {
// if (context is Activity && !(context.isFinishing)){
// wm?.removeViewImmediate(mPlayerFloatView)
// }
wm?.removeViewImmediate(mPlayerFloatView)
}
wm = null
}
//获取WindowManager
wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
//设置LayoutParams(全局变量)相关参数
val wmParams = mPlayerFloatView?.wmParams
wmParams?.type = WindowManager.LayoutParams.TYPE_APPLICATION //设置window type
wmParams?.format = PixelFormat.RGBA_8888 //设置图片格式,效果为背景透明
//设置Window flag
wmParams?.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
wmParams?.gravity = Gravity.LEFT or Gravity.TOP //调整悬浮窗口至左上角
//以屏幕左上角为原点,设置x、y初始值
val size = Point()
wm?.defaultDisplay?.getSize(size)
wmParams?.x = 0
wmParams?.y = size.y * 5 / 6
//设置悬浮窗口长宽数据
wmParams?.width = WindowManager.LayoutParams.MATCH_PARENT
wmParams?.height = RxImageTool.dp2px(56f)
//显示myFloatView图像
wm?.addView(mPlayerFloatView, wmParams)
showingPageName = context::class.qualifiedName!!
}
/**
* 打开播放中的页面详情
*/
fun startPlayingActivity(context: Context?, fullScreen: Int = 0) {
if (playingType == PlayTypeEnum.PLAY_TYPE_FM) {
//FM播放页
startFMPlayActivity(context)
} else if (playingType == PlayTypeEnum.PLAY_TYPE_COURSE) {
var url = AudioPlayer.get().playMusic?.path
//课程播放页
startCoursePlayActivity(context, 1, fullScreen, url, true)
}
}
fun startCoursePlayActivity(
context: Context?,
from: Int,
fullScreen: Int = 0,
coursePlayUrl: String? = "",
isFromFloatView: Boolean = false
) {
ARouter.getInstance()
.build("/course/play")
.withInt("course_id", playTempData["course_id"]?.toInt() ?: 0)
.withInt("course_type", 0)
.withString("coursePlayUrl", coursePlayUrl)
.withInt("from", from)
.withBoolean("isFromFloatView", isFromFloatView)
.withInt("fullScreen", fullScreen)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()
}
fun startFMPlayActivity(context: Context?) {
val bundle = Bundle()
bundle.putInt("id", playTempData["fmId"]?.toInt() ?: 0)
ARouter.getInstance().build("/fm/detail")
.withBundle("bundle", bundle)
.navigation()
}
/**
* 获取FM播放Id
*/
fun getFmId(): Int {
return playTempData["fmId"]?.toInt() ?: 0
}
}
}
\ No newline at end of file
...@@ -63,7 +63,7 @@ class AudioPlayer private constructor() { ...@@ -63,7 +63,7 @@ class AudioPlayer private constructor() {
} }
val audioSessionId: Int val audioSessionId: Int
get() = if (mediaPlayer != null)mediaPlayer!!.audioSessionId else 0 get() = if (mediaPlayer != null) mediaPlayer!!.audioSessionId else 0
val currentPosition: Long val currentPosition: Long
get() = if (isPlaying || isPausing) { get() = if (isPlaying || isPausing) {
...@@ -89,8 +89,7 @@ class AudioPlayer private constructor() { ...@@ -89,8 +89,7 @@ class AudioPlayer private constructor() {
val isIdle: Boolean val isIdle: Boolean
get() = state == STATE_IDLE get() = state == STATE_IDLE
var playPosition: Int = 0 private var playPosition: Int = 0
private set
get() { get() {
if (field < 0 || field >= musicList.size) { if (field < 0 || field >= musicList.size) {
field = 0 field = 0
...@@ -103,10 +102,12 @@ class AudioPlayer private constructor() { ...@@ -103,10 +102,12 @@ class AudioPlayer private constructor() {
* 默认为列表循环 * 默认为列表循环
*/ */
var playMode = PlayModeEnum.LIST_LOOP var playMode = PlayModeEnum.LIST_LOOP
/** /**
* 是否自动保存播放进度 * 是否自动保存播放进度
*/ */
var autoSaveProgress = false var autoSaveProgress = false
/** /**
* 是否显示通知栏 * 是否显示通知栏
*/ */
...@@ -131,6 +132,7 @@ class AudioPlayer private constructor() { ...@@ -131,6 +132,7 @@ class AudioPlayer private constructor() {
LogUtil.e(e.message) LogUtil.e(e.message)
} }
mediaPlayer!!.setOnPreparedListener { mediaPlayer!!.setOnPreparedListener {
// TODO: 2022/8/4 startPlayer 和 onPrepared 调用顺序不对
if (isPreparing) { if (isPreparing) {
if (autoSaveProgress) { if (autoSaveProgress) {
//自动播放 //自动播放
...@@ -163,13 +165,17 @@ class AudioPlayer private constructor() { ...@@ -163,13 +165,17 @@ class AudioPlayer private constructor() {
listener.onComplete() listener.onComplete()
} }
if (playMode == PlayModeEnum.SINGLE) { when (playMode) {
stopPlayer() PlayModeEnum.SINGLE -> { // 这是老逻辑
resetPlayer()
playMode = PlayModeEnum.LIST_LOOP playMode = PlayModeEnum.LIST_LOOP
return@setOnCompletionListener
} }
PlayModeEnum.LIST -> {
next() if (playPosition >= musicList.lastIndex) pausePlayer()
else next()
}
else -> next()
}
} }
handler = Handler(Looper.getMainLooper()) handler = Handler(Looper.getMainLooper())
noisyReceiver = NoisyAudioStreamReceiver() noisyReceiver = NoisyAudioStreamReceiver()
...@@ -202,7 +208,6 @@ class AudioPlayer private constructor() { ...@@ -202,7 +208,6 @@ class AudioPlayer private constructor() {
} }
musicList.clear() musicList.clear()
musicList.addAll(music) musicList.addAll(music)
playMode = PlayModeEnum.LIST_LOOP
autoSaveProgress = false autoSaveProgress = false
} }
...@@ -251,19 +256,17 @@ class AudioPlayer private constructor() { ...@@ -251,19 +256,17 @@ class AudioPlayer private constructor() {
* 加载指定索引的音乐 * 加载指定索引的音乐
*/ */
fun load(index: Int) { fun load(index: Int) {
if (musicList.isEmpty()) return
var position = index var position = index
if (musicList.isEmpty()) {
return
}
if (position < 0) { if (position < 0) {
position = musicList.size - 1 position = musicList.size - 1
} else if (position >= musicList.size) { } else if (position >= musicList.size) {
position = 0 position = 0
} }
listeners.forEach {
if (!it.onPreLoad(position)) return
}
playPosition = position playPosition = position
val music = playMusic val music = playMusic
try { try {
...@@ -298,7 +301,7 @@ class AudioPlayer private constructor() { ...@@ -298,7 +301,7 @@ class AudioPlayer private constructor() {
playPosition -= 1 playPosition -= 1
next() next()
} else { } else {
stopPlayer() resetPlayer()
for (listener in listeners) { for (listener in listeners) {
listener.onLoad(playMusic!!) listener.onLoad(playMusic!!)
} }
...@@ -309,10 +312,10 @@ class AudioPlayer private constructor() { ...@@ -309,10 +312,10 @@ class AudioPlayer private constructor() {
/** /**
* 暂停或者播放音乐 * 暂停或者播放音乐
*/ */
fun playPause() { fun playOrPause() {
when { when {
isPreparing -> { isPreparing -> {
stopPlayer() resetPlayer()
} }
isPlaying -> { isPlaying -> {
pausePlayer() pausePlayer()
...@@ -343,7 +346,7 @@ class AudioPlayer private constructor() { ...@@ -343,7 +346,7 @@ class AudioPlayer private constructor() {
} }
context!!.registerReceiver(noisyReceiver, noisyFilter) context!!.registerReceiver(noisyReceiver, noisyFilter)
for (listener in listeners) { for (listener in listeners) {
listener.onPlayerStart() listener.onStartPlay()
} }
} }
...@@ -374,14 +377,14 @@ class AudioPlayer private constructor() { ...@@ -374,14 +377,14 @@ class AudioPlayer private constructor() {
} }
for (listener in listeners) { for (listener in listeners) {
listener.onPlayerPause() listener.onPausePlay()
} }
} }
/** /**
* 停止播放器 * 停止播放器
*/ */
fun stopPlayer() { fun resetPlayer() {
if (isIdle) { if (isIdle) {
return return
} }
...@@ -395,16 +398,21 @@ class AudioPlayer private constructor() { ...@@ -395,16 +398,21 @@ class AudioPlayer private constructor() {
/** /**
* 下一首 * 下一首
*/ */
operator fun next() { fun next() {
if (musicList.isEmpty()) { if (musicList.isEmpty()) {
return return
} }
val position = when (playMode) { val position = when (playMode) {
PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size) PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size)
PlayModeEnum.SINGLE_LOOP -> playPosition PlayModeEnum.SINGLE_LOOP -> playPosition
PlayModeEnum.LIST_LOOP -> playPosition + 1 PlayModeEnum.LIST_LOOP -> if (playPosition >= musicList.lastIndex) 0 else playPosition + 1
PlayModeEnum.LIST -> if (playPosition >= musicList.lastIndex) -1 else playPosition + 1
else -> playPosition + 1 else -> playPosition + 1
} }
if (-1 == position) {
ToastUtil.toastShort("暂无内容")
return
}
load(position) load(position)
} }
...@@ -415,13 +423,18 @@ class AudioPlayer private constructor() { ...@@ -415,13 +423,18 @@ class AudioPlayer private constructor() {
if (musicList.isEmpty()) { if (musicList.isEmpty()) {
return return
} }
val playPosition = when (playMode) { val position = when (playMode) {
PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size) PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size)
PlayModeEnum.SINGLE_LOOP -> playPosition PlayModeEnum.SINGLE_LOOP -> playPosition
PlayModeEnum.LIST_LOOP -> playPosition - 1 PlayModeEnum.LIST_LOOP -> if (playPosition <= 0) musicList.lastIndex else playPosition - 1
PlayModeEnum.LIST -> if (playPosition <= 0) -1 else playPosition - 1
else -> playPosition - 1 else -> playPosition - 1
} }
load(playPosition) if (-1 == position) {
ToastUtil.toastShort("暂无内容")
return
}
load(position)
} }
/** /**
...@@ -479,6 +492,8 @@ class AudioPlayer private constructor() { ...@@ -479,6 +492,8 @@ class AudioPlayer private constructor() {
} }
companion object { companion object {
// TODO: 2022/8/4 缺少完成状态和出错状态,目前看代码逻辑是
// TODO: 2022/8/4 正常播放完,到下一首加载前都是 STATE_PLAYING 状态,如果播放链接出错,则到下一首加载前是 STATE_PREPARING 状态
private val STATE_IDLE = 0 private val STATE_IDLE = 0
private val STATE_PREPARING = 1 private val STATE_PREPARING = 1
private val STATE_PLAYING = 2 private val STATE_PLAYING = 2
......
...@@ -6,18 +6,27 @@ import com.ydl.media.audio.model.Music ...@@ -6,18 +6,27 @@ import com.ydl.media.audio.model.Music
/** /**
* Created by haorui on 2019-10-27 . * Created by haorui on 2019-10-27 .
* Des:播放进度监听器 * Des:播放进度监听器
*
* todo: [onStartPlay]和[onPrepared]调用顺序有问题,不改是因为多处调用
*/ */
interface OnPlayerEventListener { interface OnPlayerEventListener {
/** /**
* 加载歌曲 * 加载之前
* @return true: 可加载
*/
fun onPreLoad(playPosition: Int): Boolean = true
/**
* 加载之后
*/ */
fun onLoad(music: Music) fun onLoad(music: Music)
/** /**
* 开始播放 * 开始播放
*
*/ */
fun onPlayerStart() fun onStartPlay()
/** /**
* 准备完成 * 准备完成
...@@ -39,12 +48,12 @@ interface OnPlayerEventListener { ...@@ -39,12 +48,12 @@ interface OnPlayerEventListener {
fun onPublish(percent: Int,currentPosition: Long) fun onPublish(percent: Int,currentPosition: Long)
/** /**
* 单曲播放完成 * 播放完成
*/ */
fun onComplete() fun onComplete()
/** /**
* 暂停播放 * 暂停播放
*/ */
fun onPlayerPause() fun onPausePlay()
} }
...@@ -56,7 +56,7 @@ class PlayService : Service() { ...@@ -56,7 +56,7 @@ class PlayService : Service() {
} }
private fun stop() { private fun stop() {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
NotifyManager.get().cancelAll() NotifyManager.get().cancelAll()
} }
......
...@@ -5,6 +5,8 @@ package com.ydl.media.audio.enums ...@@ -5,6 +5,8 @@ package com.ydl.media.audio.enums
* Des: 播放模式 * Des: 播放模式
*/ */
enum class PlayModeEnum(private val value: Int) { enum class PlayModeEnum(private val value: Int) {
//列表
LIST(-1),
//列表循环 //列表循环
LIST_LOOP(0), LIST_LOOP(0),
//随机播放 //随机播放
......
...@@ -23,11 +23,11 @@ class MediaSessionManager private constructor() { ...@@ -23,11 +23,11 @@ class MediaSessionManager private constructor() {
private val callback = object : MediaSessionCompat.Callback() { private val callback = object : MediaSessionCompat.Callback() {
override fun onPlay() { override fun onPlay() {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
override fun onPause() { override fun onPause() {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
override fun onSkipToNext() { override fun onSkipToNext() {
...@@ -39,7 +39,7 @@ class MediaSessionManager private constructor() { ...@@ -39,7 +39,7 @@ class MediaSessionManager private constructor() {
} }
override fun onStop() { override fun onStop() {
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
override fun onSeekTo(pos: Long) { override fun onSeekTo(pos: Long) {
......
...@@ -22,6 +22,7 @@ import com.ydl.media.audio.PlayService ...@@ -22,6 +22,7 @@ import com.ydl.media.audio.PlayService
import com.ydl.media.audio.constants.Extras import com.ydl.media.audio.constants.Extras
import com.ydl.media.audio.model.Music import com.ydl.media.audio.model.Music
import com.ydl.media.audio.receiver.StatusBarReceiver import com.ydl.media.audio.receiver.StatusBarReceiver
import com.ydl.ydlcommon.router.YdlCommonOut
import java.util.* import java.util.*
...@@ -77,20 +78,18 @@ class NotifyManager private constructor() { ...@@ -77,20 +78,18 @@ class NotifyManager private constructor() {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val pendingIntent = val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
var remoteViews = getRemoteViews(context, music, isPlaying) val remoteViews = getRemoteViews(context, music, isPlaying)
val builder: NotificationCompat.Builder val builder: NotificationCompat.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (Build.VERSION.SDK_INT >= 26) {
val channelId = "app_play_intent_service_channel_id" val channelId = "app_play_intent_service_channel_id"
val channelName = "壹点灵心理咨询" val channelName = "壹点灵心理咨询"
val notificationManager = val notificationManager =
context.getSystemService("notification") as NotificationManager context.getSystemService("notification") as NotificationManager
val notificationChannel = NotificationChannel(channelId, channelName, 2) val notificationChannel = NotificationChannel(channelId, channelName, 2)
notificationManager.createNotificationChannel(notificationChannel) notificationManager.createNotificationChannel(notificationChannel)
builder = NotificationCompat.Builder(context, channelId) NotificationCompat.Builder(context, channelId)
} else { } else {
builder = NotificationCompat.Builder(context) NotificationCompat.Builder(context)
} }
builder builder
...@@ -112,7 +111,7 @@ class NotifyManager private constructor() { ...@@ -112,7 +111,7 @@ class NotifyManager private constructor() {
private fun getRemoteViews(context: Context, music: Music, isPlaying: Boolean): RemoteViews { private fun getRemoteViews(context: Context, music: Music, isPlaying: Boolean): RemoteViews {
val title = music.title val title = music.title
val subtitle = music.artist + "-" + music.album val subtitle = music.artist + if (null == music.album) "" else "-" + music.album
val remoteViews = RemoteViews(context.packageName, R.layout.notification) val remoteViews = RemoteViews(context.packageName, R.layout.notification)
...@@ -122,7 +121,7 @@ class NotifyManager private constructor() { ...@@ -122,7 +121,7 @@ class NotifyManager private constructor() {
val isLightNotificationTheme = isLightNotificationTheme(playService) val isLightNotificationTheme = isLightNotificationTheme(playService)
val playIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR) val playIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR)
playIntent.setPackage("com.cxzapp.xinlizixun") playIntent.setPackage(YdlCommonOut.getApp().packageName)
playIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_PLAY_PAUSE) playIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_PLAY_PAUSE)
val playPendingIntent = val playPendingIntent =
PendingIntent.getBroadcast(context, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.getBroadcast(context, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT)
...@@ -133,7 +132,7 @@ class NotifyManager private constructor() { ...@@ -133,7 +132,7 @@ class NotifyManager private constructor() {
remoteViews.setOnClickPendingIntent(R.id.iv_play_pause, playPendingIntent) remoteViews.setOnClickPendingIntent(R.id.iv_play_pause, playPendingIntent)
val nextIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR) val nextIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR)
nextIntent.setPackage("com.cxzapp.xinlizixun") nextIntent.setPackage(YdlCommonOut.getApp().packageName)
nextIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_NEXT) nextIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_NEXT)
val nextPendingIntent = val nextPendingIntent =
PendingIntent.getBroadcast(context, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.getBroadcast(context, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT)
......
...@@ -17,6 +17,8 @@ class Music : Serializable { ...@@ -17,6 +17,8 @@ class Music : Serializable {
var duration: Long = 0 // 持续时间 var duration: Long = 0 // 持续时间
var path: String? = null // 播放地址 var path: String? = null // 播放地址
var canPlay: Boolean = true // 是否能播放
override fun equals(o: Any?): Boolean { override fun equals(o: Any?): Boolean {
if (o !is Music) { if (o !is Music) {
return false return false
......
...@@ -14,6 +14,6 @@ import com.ydl.media.audio.AudioPlayer ...@@ -14,6 +14,6 @@ import com.ydl.media.audio.AudioPlayer
class NoisyAudioStreamReceiver : BroadcastReceiver() { class NoisyAudioStreamReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
} }
...@@ -21,7 +21,7 @@ class RemoteControlReceiver : BroadcastReceiver() { ...@@ -21,7 +21,7 @@ class RemoteControlReceiver : BroadcastReceiver() {
} }
when (event.keyCode) { when (event.keyCode) {
KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_MEDIA_PAUSE, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_HEADSETHOOK -> AudioPlayer.get().playPause() KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_MEDIA_PAUSE, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_HEADSETHOOK -> AudioPlayer.get().playOrPause()
KeyEvent.KEYCODE_MEDIA_NEXT -> AudioPlayer.get().next() KeyEvent.KEYCODE_MEDIA_NEXT -> AudioPlayer.get().next()
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> AudioPlayer.get().prev() KeyEvent.KEYCODE_MEDIA_PREVIOUS -> AudioPlayer.get().prev()
} }
......
...@@ -23,7 +23,7 @@ class StatusBarReceiver : BroadcastReceiver() { ...@@ -23,7 +23,7 @@ class StatusBarReceiver : BroadcastReceiver() {
if (TextUtils.equals(extra, EXTRA_NEXT)) { if (TextUtils.equals(extra, EXTRA_NEXT)) {
AudioPlayer.get().next() AudioPlayer.get().next()
} else if (TextUtils.equals(extra, EXTRA_PLAY_PAUSE)) { } else if (TextUtils.equals(extra, EXTRA_PLAY_PAUSE)) {
AudioPlayer.get().playPause() AudioPlayer.get().playOrPause()
} }
} }
......
...@@ -56,7 +56,7 @@ class PlayerFloatHelper { ...@@ -56,7 +56,7 @@ class PlayerFloatHelper {
/** /**
* 显示悬浮控件 * 显示悬浮控件
*/ */
fun show(context: Context, playTypeEnum: PlayTypeEnum = PlayTypeEnum.PLAY_TYPE_NONE, playData:HashMap<String,String> = hashMapOf<String,String>()) { fun show(context: Context, playTypeEnum: PlayTypeEnum = PlayTypeEnum.PLAY_TYPE_NONE, playData:HashMap<String,String> = hashMapOf()) {
playingType = playTypeEnum playingType = playTypeEnum
if (playData.size>0){ if (playData.size>0){
......
...@@ -63,18 +63,16 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) { ...@@ -63,18 +63,16 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) {
} }
PlayerFloatHelper.removeView(ctx) PlayerFloatHelper.removeView(ctx)
PlayerFloatHelper.playTempData.clear() PlayerFloatHelper.playTempData.clear()
AudioPlayer.get().stopPlayer() AudioPlayer.get().resetPlayer()
} }
play_state.setOnClickListener { play_state.setOnClickListener {
if (AudioPlayer.get().isPlaying) { if (AudioPlayer.get().isPlaying) {
play_state.setImageResource(R.drawable.ico_yyfc_play) AudioPlayer.get().pausePlayer()
AudioPlayer.get().playPause()
mListeners.forEach { mListeners.forEach {
it.onPauseClick() it.onPauseClick()
} }
} else { } else if (AudioPlayer.get().isPausing) {
play_state.setImageResource(R.drawable.ico_yyfc_pause) AudioPlayer.get().startPlayer()
AudioPlayer.get().playPause()
mListeners.forEach { mListeners.forEach {
it.onStartClick() it.onStartClick()
} }
...@@ -84,24 +82,40 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) { ...@@ -84,24 +82,40 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) {
mStateChangeListener = object : OnPlayerEventListener { mStateChangeListener = object : OnPlayerEventListener {
override fun onComplete() { override fun onComplete() {
updatePlayState() tv_start.text = getStringTime(AudioPlayer.get().getDuration().toInt())
play_state.setImageResource(R.drawable.ico_yyfc_play)
mListeners.forEach { mListeners.forEach {
it.onPlayFinish() it.onPlayFinish()
} }
} }
override fun onPreLoad(playPosition: Int): Boolean {
AudioPlayer.get().getMusicList().elementAtOrNull(playPosition)?.let {
if (it.canPlay) {
tv_title.text = it.title
tv_name.text = it.artist
return true
} else {
AudioPlayer.get().next()
}
}
return true
}
override fun onLoad(music: Music) { override fun onLoad(music: Music) {
} }
override fun onPlayerStart() { override fun onStartPlay() {
play_state.setImageResource(R.drawable.ico_yyfc_pause)
} }
override fun onPlayerPause() { override fun onPausePlay() {
play_state.setImageResource(R.drawable.ico_yyfc_play)
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onPublish(percent: Int, currentPosition: Long) { override fun onPublish(percent: Int, currentPosition: Long) {
tv_now_playing_time.text = getStringTime(currentPosition.toInt()) tv_start.text = getStringTime(currentPosition.toInt())
} }
override fun onBufferingUpdate(percent: Int) { override fun onBufferingUpdate(percent: Int) {
...@@ -109,6 +123,7 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) { ...@@ -109,6 +123,7 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onPrepared(duration: Long) { override fun onPrepared(duration: Long) {
setDuration()
updatePlayState() updatePlayState()
} }
} }
...@@ -142,9 +157,13 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) { ...@@ -142,9 +157,13 @@ class PlayerFloatView(private val ctx: Context) : FrameLayout(ctx) {
} else { } else {
AudioPlayer.get().playMusic?.artist AudioPlayer.get().playMusic?.artist
} }
tv_duration.text = " / ${getStringTime(AudioPlayer.get().getDuration().toInt())}" setDuration()
} }
@SuppressLint("SetTextI18n")
private fun setDuration() {
tv_duration.text = " / ${getStringTime(AudioPlayer.get().getDuration().toInt())}"
}
private fun getStringTime(time: Int): String { private fun getStringTime(time: Int): String {
if (time <= 0) return "00:00" if (time <= 0) return "00:00"
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
tools:text="丁sir" /> tools:text="丁sir" />
<TextView <TextView
android:id="@+id/tv_now_playing_time" android:id="@+id/tv_start"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@id/tv_title" app:layout_constraintStart_toStartOf="@id/tv_title"
...@@ -71,8 +71,8 @@ ...@@ -71,8 +71,8 @@
android:id="@+id/tv_duration" android:id="@+id/tv_duration"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBaseline_toBaselineOf="@id/tv_now_playing_time" app:layout_constraintBaseline_toBaselineOf="@id/tv_start"
app:layout_constraintStart_toEndOf="@id/tv_now_playing_time" app:layout_constraintStart_toEndOf="@id/tv_start"
android:textColor="#BFBFBF" android:textColor="#BFBFBF"
android:textSize="10sp" android:textSize="10sp"
tools:text=" / 30:28" /> tools:text=" / 30:28" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment