Commit 9862f973 by 刘鹏

Merge branch 'd/4.3.93_muse' into feat/lp/lp_muse

# Conflicts:
#	config.gradle
#	m-user/src/main/java/com/yidianling/user/mine/MineFragment.java
#	m-user/src/main/java/com/yidianling/user/mine/MineFragment.kt
parents cc9283e1 7838e90a
......@@ -30,6 +30,9 @@ import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.api.IConsultantService
import com.yidianling.fm.api.service.IFMService
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.service.MeditationWindowService
import com.yidianling.tests.home.NewTestHomeActivity
import com.yidianling.user.StatusUtils
import com.yidianling.user.ui.collect.CollectSexAndBirthActivity
......@@ -37,6 +40,7 @@ import com.yidianling.user.ui.login.OneKeyLoginHelp
import com.yidianling.user.widget.SecretDescriptionDialog
import com.yidianling.user.widget.SecretDialog
import com.yidianling.user.widget.SecretDialog.OnSecretDialogListener
import de.greenrobot.event.EventBus
import kotlinx.android.synthetic.main.activity_main.*
......@@ -52,6 +56,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
private var secretDialog: SecretDialog? = null
protected var playService: PlayService? = null
private var meditationIntent:Intent?=null
override fun getContentViewId(): Int {
return R.id.lce_content_view
}
......@@ -74,6 +80,7 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
override fun initDataAndEvent() {
EventBus.getDefault().register(this)
// YDLavManager.instances.init(this, "3387e9b251f3491e9221a9877e8f7830")
YdlCommonRouterManager.initYdlCommonRoute(PlatformTempCommonRouteImpl())
......@@ -82,6 +89,10 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// 初始化一键登录sdk
OneKeyLoginHelp.sdkInit(this, OneKeyLoginHelp.YDL_USER_APP, PhoneNumberAuthHelper.SERVICE_TYPE_LOGIN)
bindService()
meditationIntent = Intent(this,MeditationWindowService::class.java)
startService(meditationIntent)
reLoadData()
requestPermission()
bt_mdt.setOnClickListener {
......@@ -268,11 +279,22 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// ModularServiceManager.provide(IConsultantService::class.java).hideConsultAssistantDialog()
}
fun onEvent(event:MeditationFloatEvent){
}
override fun onDestroy() {
if (serviceConnection != null) {
unbindService(serviceConnection)
}
if(meditationIntent!=null){
EventBus.getDefault().post(MeditationFloatEvent(false))
MediaPlayerManager.getInstance(this)?.stop()
stopService(meditationIntent)
}
if(EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().unregister(this)
}
super.onDestroy()
}
......@@ -286,7 +308,6 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
}
}
private fun showEnsureDialog() {
secretDialog = SecretDialog(this, object : OnSecretDialogListener {
override fun onCancel() {
......
......@@ -21,9 +21,9 @@ import java.util.List;
public final class DemoGlobalConfig implements IConfigModule {
String APP_DOMAIN = "https://api.github.com/";
// public static String appEnv = YDLConstants.ENV_AUTO_TEST;
// public static String appEnv = YDLConstants.ENV_TEST;
public static String appEnv = YDLConstants.ENV_TEST;
// public static String appEnv = YDLConstants.ENV_NEW_TEST;//配置未上传到maven库
public static String appEnv = YDLConstants.ENV_PROD;
// public static String appEnv = YDLConstants.ENV_PROD;
@Override
public void injectAppLifecycle(@NotNull Context context, @NotNull List<IAppLifecycles> lifecycles) {
lifecycles.add(new DemoAppLifecycles());
......
......@@ -8,13 +8,13 @@ ext {
"m-confide" : "0.0.49.74",
"m-consultant" : "0.0.60.25",
"m-fm" : "0.0.30.08",
"m-user" : "0.0.62.11",
"m-home" : "0.0.23.49",
"m-user" : "0.0.62.12",
"m-home" : "0.0.23.58",
"m-im" : "0.0.21.44",
"m-dynamic" : "0.0.7.73",
"m-article" : "0.0.0.10",
"m-muse" : "0.0.28.29",
"m-muse" : "0.0.28.37",
"m-tests" : "0.0.24.18",
"m-course" : "0.0.43.37",
......@@ -95,11 +95,13 @@ ext {
"m-fm" : "0.0.30.08",
"m-user" : "0.0.62.11",
"m-home" : "0.0.23.49",
"m-user" : "0.0.62.12",
"m-home" : "0.0.23.58",
"m-im" : "0.0.21.44",
"m-dynamic" : "0.0.7.73",
"m-article" : "0.0.0.8",
"m-muse" : "0.0.28.29",
"m-muse" : "0.0.28.37",
"m-tests" : "0.0.24.18",
"m-course" : "0.0.43.37",
//-------------- 业务模块 API 层 --------------
......
......@@ -68,7 +68,6 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.fragment:fragment-ktx:1.2.4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation project(path: ':m-user')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
......@@ -104,5 +103,6 @@ dependencies {
}
api rootProject.ext.dependencies["ydl-webview"]
api rootProject.ext.dependencies["ydl-media"]
api rootProject.ext.dependencies["ydl-media"]
}
}
......@@ -11,25 +11,23 @@ import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.launcher.ARouter
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.Utils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.common.tools.ToastUtil
import com.yidianling.home.constants.HomeBIConstants
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.user.ui.login.OneKeyLoginHelp
import com.yidianling.user.api.service.IUserService
import kotlinx.android.synthetic.ydl.home_fragment.*
class MeditationTypeAdapter(
private val context: Context,
private val data: List<MeditationModuleBean.MeditationDetail>,
private val moreLink: String,
private val data: List<MeditationModuleBean.MeditationDetail>?,
private val moreLink: String?,
private val homeLink:String?=null,
private val cateId:Long?=null,
private val mark:Int?=null,
private val meditationType: Int
private val meditationType: Int? = null
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
......@@ -56,21 +54,29 @@ class MeditationTypeAdapter(
is MeditationTypeViewHolder -> {
holder.ivType?.let {
Glide.with(context)
.load(data[position].coverImageUrl)
.load(data?.get(position)?.coverImageUrl)
.transition(DrawableTransitionOptions.withCrossFade())
.into(it)
}
holder.tvName?.let {
it.text = data[position].title
it.text = data?.get(position)?.title ?: ""
}
holder.cvLayout?.setOnClickListener {
if (meditationType == 0){
if (!OneKeyLoginHelp.startLoginByStatus(context, true)) {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if(!ModularServiceManager.provide(IUserService::class.java).loginByOneKeyLogin(context,true)){
return@setOnClickListener
}
if(data==null){
return@setOnClickListener
}
ARouter.getInstance().build("/muse/play")
.withLong("MEDITATION_ID", data[position].meditationId)
.withLong("MEDITATION_ID", data[position]?.meditationId)
.withInt("MEDITATION_TYPE", meditationType)
.withFloat("MEDIA_DURATION", data[position].duration?:0.0f)
.withString("MEDIA_URL", data[position].mediaIdCoverImageUrl)
......@@ -81,7 +87,10 @@ class MeditationTypeAdapter(
//防止连击
return@setOnClickListener
}
val homeLink = "${homeLink}mark=$mark&cateId=$cateId&meditationId=${data[position].meditationId}"
if(data==null){
return@setOnClickListener
}
val homeLink = "${homeLink}mark=$mark&cateId=$cateId&meditationId=${data[position]?.meditationId}"
if (!homeLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(homeLink, null))
}
......@@ -105,17 +114,17 @@ class MeditationTypeAdapter(
}
override fun getItemCount(): Int {
return if (data.isNotEmpty()) {
return if (data?.isNotEmpty() == true) {
data.size + 1
} else {
data.size
0
}
}
override fun getItemId(position: Int) = position.toLong()
override fun getItemViewType(position: Int): Int {
return if (data.isNotEmpty() && position == data.size) {
return if (data?.isNotEmpty() == true && position == data.size) {
FOOTER_TYPE
} else {
CONTENT_TYPE
......
package com.yidianling.home.router
import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.yidianling.im.api.service.IImService
import com.yidianling.user.api.service.IAppService
import com.yidianling.user.api.service.IUserService
/**
* author : liupeng
*/
object HomeIn {
fun getImService(): IImService {
return ModularServiceManager.provide(IImService::class.java)
}
fun getUserService(): IUserService {
return ModularServiceManager.provide(IUserService::class.java)
}
fun isLogin(): Boolean {
return getUserService()?.isLogin()?:false
}
fun loginWayIntent(activity: Activity): Intent? {
return getUserService()?.loginWayIntent(activity)
}
/**
* 私聊
*/
fun startChat(context: AppCompatActivity, toUid: String, flag: Int, canTalk: Int) {
getImService().startChat(context,toUid,flag,canTalk)
}
/**
* 调用优先使用一键登录,并返回调用时的登录状态,
* @param isOpenDialog true:一键登录使用弹窗展示 false:一键登录使用全屏模式
* @return true:已登录,不触发登录跳转,false:未登录,优先一键登录
* */
fun loginByOneKeyLogin(context: Context, isOpenDialog: Boolean) :Boolean{
return getUserService().loginByOneKeyLogin(context,isOpenDialog)
}
}
\ No newline at end of file
package com.yidianling.home.adapter
import android.content.Context
import android.graphics.Color
import android.media.MediaPlayer
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.LogUtil
import com.yidianling.home.R
import com.yidianling.home.constract.HomeViewConfig
import com.yidianling.home.event.HomeImpl
import com.yidianling.home.model.bean.*
import com.yidianling.home.ui.view.*
import kotlin.properties.Delegates
import kotlinx.android.synthetic.ydl.home_muse_view.view.*
/**
......@@ -227,6 +228,17 @@ class YdlHomeAdapter(private val mContext: Context,
}
//壹点*冥想模块
is HomeMuseViewHolder -> {
holder.museViewView.iv_video_background?.visibility = View.VISIBLE
holder.museViewView.video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
holder.museViewView.video_view?.iv_video_background?.visibility = View.GONE
holder.museViewView.video_view?.setBackgroundColor(Color.TRANSPARENT)
}
true
}
holder.museViewView.video_view?.start()
holder.museViewView.initData(list[holder.viewType].meditationBean)
}
//心灵*电台模块
......
......@@ -2,7 +2,9 @@ package com.yidianling.home.ui.fragment
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
import android.os.Build
import android.text.TextUtils
import android.view.View
......@@ -41,6 +43,9 @@ import com.yidianling.home.ui.view.HomeSpaceItemDecoration
import com.yidianling.home.utils.HomeAnimUtils
import com.yidianling.user.api.service.IUserService
import kotlinx.android.synthetic.ydl.home_fragment.*
import kotlinx.android.synthetic.ydl.home_fragment.tab_layout
import kotlinx.android.synthetic.ydl.home_muse_view.*
import kotlinx.android.synthetic.ydl.home_muse_view.view.*
import kotlin.properties.Delegates
......@@ -523,6 +528,16 @@ open class YdlHomeFragment : BaseMvpFragment<IHomeContract.View, HomePresenterIm
ActionCountUtils.count(HomeBIConstants.YDL_USER_MAIN_PAGE_VISIT)
ActionCountUtils.count("daoyi_advertisement_page|daoyi_advertisement_visit","1")
showConsultAssistantDialog()
iv_video_background?.visibility = View.VISIBLE
video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
iv_video_background?.visibility = View.GONE
video_view?.setBackgroundColor(Color.TRANSPARENT)
}
true
}
video_view?.start()
}
}
......@@ -533,6 +548,7 @@ open class YdlHomeFragment : BaseMvpFragment<IHomeContract.View, HomePresenterIm
ActionCountUtils.count(HomeBIConstants.YDL_HOME_DWELL_TIME,(endTime-startTime).toString())
startTime=0L
}
video_view?.pause()
}
/**
......
......@@ -2,6 +2,7 @@ package com.yidianling.home.ui.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
import android.text.SpannableString
......@@ -12,14 +13,13 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.google.gson.Gson
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydlcommon.utils.Utils
import com.yidianling.common.tools.ToastUtil
import com.yidianling.home.MeditationViewPagerAdapter
import com.yidianling.home.R
import com.yidianling.home.constract.HomeViewConfig
......@@ -74,31 +74,61 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
}
video_view?.setOnClickListener {
// homeEvent?.museMoreClick(Gson().toJson(bean))
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if (!moreLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(moreLink, null))
}
}
iv_video_background?.setOnClickListener {
// homeEvent?.museMoreClick(Gson().toJson(bean))
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if (!moreLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(moreLink, null))
}
}
val greeting = bean.mditationIndexInfo?.greetings?:"你好"
tv_time.text = greeting
val slogan =
if (bean.mditationIndexInfo?.desc.isNullOrBlank()){
"无常的日子里,呼吸间拾起力量"
}else{
bean?.mditationIndexInfo?.desc
bean.mditationIndexInfo?.desc
}
tv_meditation_slogan.text = slogan
val videoUrl = bean?.mditationIndexInfo?.videoLink
val videoUrl = bean.mditationIndexInfo?.videoLink
val videoThumbnailUrl = bean.mditationIndexInfo?.mditationIndexUrl
if (videoUrl.isNullOrBlank()){
Glide.with(this)
.load(bean.mditationIndexInfo?.mditationIndexUrl)
.load(videoThumbnailUrl)
.transition(withCrossFade())
.into(iv_video_background)
}else{
GlideApp.with(this)
.load(videoUrl)
.load(videoThumbnailUrl)
.transition(withCrossFade())
.into(iv_video_background)
video_view?.setVideoPath(videoUrl)
video_view?.setOnErrorListener { mp, what, extra ->
Glide.with(this)
.load(bean.mditationIndexInfo?.mditationIndexUrl)
.transition(withCrossFade())
.into(iv_video_background)
true
}
......@@ -106,7 +136,8 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
it?.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
iv_video_background.visibility = GONE
iv_video_background.visibility = View.GONE
video_view.setBackgroundColor(Color.TRANSPARENT)
}
true
}
......@@ -117,7 +148,7 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
}
bean?.mditationListResponse?.forEach {
bean.mditationListResponse?.forEach {
meditationTitles.add(it.comment)
}
......@@ -125,7 +156,7 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
tab_layout.addOnTabSelectedListener(object :TabLayout.OnTabSelectedListener{
override fun onTabSelected(tab: TabLayout.Tab?) {
var text:String? = tab?.text.toString().trim() ?: return
var text:String? = tab?.text.toString().trim()
val spStr = SpannableString(text)
val styleSpan = StyleSpan(Typeface.BOLD)
spStr.setSpan(styleSpan,0,text?.length?:0,Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
......@@ -133,7 +164,7 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
var text:String? = tab?.text.toString().trim() ?: return
var text:String? = tab?.text.toString().trim()
val spStr = SpannableString(text)
val styleSpan = StyleSpan(Typeface.NORMAL)
spStr.setSpan(styleSpan,0,text?.length?:0,Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
......
......@@ -23,12 +23,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.yidianling.home.widget.AdaptiveVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false" />
......@@ -36,7 +34,7 @@
android:id="@+id/iv_video_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
android:scaleType="fitCenter"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
......
......@@ -54,19 +54,16 @@ dependencies {
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation project(path: ':ydl-webview')
implementation project(path: ':ydl-platform')
implementation project(path: ':ydl-platform')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.github.weidongjian:androidWheelView:1.0.0'
implementation 'com.github.feeeei:CircleSeekbar:v1.1.2'
// solve build problem
// cannot access 'androidx.lifecycle.hasdefaultviewmodelproviderfactory'
// Comment out when compiling
// implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation "com.alibaba:arouter-api:$arouter_api"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
......@@ -76,11 +73,17 @@ dependencies {
//开发时使用
api project(":ydl-platform")
implementation project(':ydl-media')
implementation modularPublication('com.ydl:m-user-api')
implementation project(':ydl-flutter-base')
implementation project(':ydl-webview')
} else {
//发布时使用
api rootProject.ext.dependencies["ydl-media"]
compileOnly rootProject.ext.dependencies["ydl-m-user-api"]
api (rootProject.ext.dependencies["ydl-webview"]){
transitive = true
}
api (rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yidianling.muse">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application>
<activity
android:name=".activity.MuseActivity"
......@@ -18,5 +21,8 @@
android:name=".activity.MeditationTimeOffActivity"
android:screenOrientation="portrait"
android:theme="@style/platform_NoTitleTheme" />
<service android:name=".service.MeditationWindowService"/>
</application>
</manifest>
......@@ -16,7 +16,9 @@ class MeditationPlayModuleBean : HomeItemBaseBean {
var mediaList: ArrayList<MeditationDetail>? = null
data class MeditationDetail(
val mediaId:Long,
val mediaType:Int? = null,
val mediaId:Long?=null,
val meditationId:Long,
val title:String,
val author:String,
val coverImageUrl:String,
......@@ -30,4 +32,8 @@ class MeditationPlayModuleBean : HomeItemBaseBean {
val coverImageUrlIcon:String
)
override fun toString(): String {
return "MeditationPlayModuleBean(meditationId=$meditationId, mediaId=$mediaId, mediaType=$mediaType, playDetailUrl=$playDetailUrl, mediaList=$mediaList)"
}
}
\ No newline at end of file
package com.yidianling.muse.event
import com.yidianling.muse.bean.MeditationPlayModuleBean
class MeditationFloatEvent(
val show: Boolean,
val meditationDetail: MeditationPlayModuleBean.MeditationDetail?=null
)
\ No newline at end of file
......@@ -3,9 +3,10 @@ package com.yidianling.muse.helper
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import com.ydl.ydlcommon.utils.LogUtil
class FloatViewTouchListener(val wl: WindowManager.LayoutParams,val windowManager: WindowManager):
View.OnTouchListener{
class FloatViewTouchListener(val wl: WindowManager.LayoutParams, val windowManager: WindowManager) :
View.OnTouchListener {
private var x = 0
private var y = 0
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
......@@ -26,6 +27,8 @@ View.OnTouchListener{
x += movedX
y += movedY
}
LogUtil.d("Lancet=======","nowY=====$nowY")
LogUtil.d("Lancet=======","movedY=====$movedY")
//更新悬浮窗位置
windowManager.updateViewLayout(view, wl)
}
......
package com.yidianling.muse.helper
import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import java.io.IOException
import kotlin.properties.Delegates
class MediaPlayerManager private constructor() {
......@@ -12,38 +11,44 @@ class MediaPlayerManager private constructor() {
private var listener:OnMediaPlayerManagerListener?=null
fun setAudioPath(path: String){
val attrs = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
.build()
mPath = path
if(mMediaPlayer.isPlaying) mMediaPlayer.reset()
mMediaPlayer.setDataSource(mContext, Uri.parse(path))
mMediaPlayer.prepareAsync()
mMediaPlayer.setOnPreparedListener {
mMediaPlayer?.reset()
mMediaPlayer?.setAudioAttributes(attrs)
mMediaPlayer?.setDataSource(path)
mMediaPlayer?.prepareAsync()
mMediaPlayer?.setOnPreparedListener {
listener?.onPrepared(it)
}
}
fun getMediaPlayer():MediaPlayer = mMediaPlayer
fun getMediaPlayer():MediaPlayer? = mMediaPlayer
fun getAudioPath():String? = mPath
fun isPlaying() = mMediaPlayer.isPlaying
fun isPlaying() = mMediaPlayer?.isPlaying
fun play() {
if (mMediaPlayer.isPlaying) return
mMediaPlayer.start()
if (mMediaPlayer?.isPlaying == true) return
mMediaPlayer?.start()
}
fun pause() {
if (mMediaPlayer.isPlaying) mMediaPlayer.pause()
if (mMediaPlayer?.isPlaying == true) mMediaPlayer?.pause()
}
fun seekTo(position: Int) {
mMediaPlayer.seekTo(position)
mMediaPlayer?.seekTo(position)
}
fun stop() {
if (mMediaPlayer!!.isPlaying) {
mMediaPlayer.reset()
}
mMediaPlayer?.reset()
}
fun release() {
......@@ -58,7 +63,7 @@ class MediaPlayerManager private constructor() {
private var mContext: Context by Delegates.notNull()
private var mMediaPlayer:MediaPlayer by Delegates.notNull()
private var mMediaPlayer:MediaPlayer? = null
private var mPath:String? = null
......
package com.yidianling.muse.helper
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
object MeditationViewModel: ViewModel() {
//悬浮窗口创建 移除 基于无障碍服务
var isShowWindow = MutableLiveData<Boolean>()
//悬浮窗口创建 移除
var isShowSuspendWindow = MutableLiveData<Boolean>()
//悬浮窗口显示 隐藏
var isVisible = MutableLiveData<Boolean>()
}
\ No newline at end of file
package com.yidianling.muse.service
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.os.Build
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.LifecycleService
import com.bumptech.glide.Glide
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.yidianling.home.http.MuseHttp
import com.yidianling.muse.R
import com.yidianling.muse.activity.PlayMeditationActivity
import com.yidianling.muse.bean.MeditationPlayModuleBean
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.FloatViewTouchListener
import com.yidianling.muse.helper.MediaPlayerManager
import de.greenrobot.event.EventBus
import io.feeeei.circleseekbar.CircleSeekBar
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.*
import kotlin.math.roundToInt
class MeditationWindowService : LifecycleService() {
private lateinit var mWindowManager: WindowManager
private var floatRootView: View? = null
private var ivClose: ImageView? = null
private var ivCover: ImageView? = null
private var tvTitle: TextView? = null
private var ivProgress: CircleSeekBar? = null
private var ivPlayOrPause: ImageView? = null
private var mMediaPlayer: MediaPlayer? = null
private var mTimer = Timer()
private var mCurrentMeditation: MeditationPlayModuleBean.MeditationDetail? = null
private var windowIsShow = false
override fun onCreate() {
super.onCreate()
EventBus.getDefault().register(this)
}
private fun showWindow() {
mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
val outMetrics = DisplayMetrics()
mWindowManager.defaultDisplay.getMetrics(outMetrics)
var layoutParams = WindowManager.LayoutParams().apply {
type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
format = PixelFormat.RGBA_8888
width = outMetrics.widthPixels - dp2px(32F)
height = WRAP_CONTENT
gravity = Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM
}
floatRootView =
LayoutInflater.from(this).inflate(R.layout.layout_meditation_play_float_view, null)
ivClose = floatRootView?.findViewById(R.id.iv_close)
ivCover = floatRootView?.findViewById(R.id.iv_cover)
tvTitle = floatRootView?.findViewById(R.id.tv_title)
ivProgress = floatRootView?.findViewById(R.id.progress_bar)
ivPlayOrPause = floatRootView?.findViewById(R.id.iv_play_status)
floatRootView?.setOnTouchListener(FloatViewTouchListener(layoutParams, mWindowManager))
mWindowManager.addView(floatRootView, layoutParams)
windowIsShow = true
}
fun onEventMainThread(event: MeditationFloatEvent) {
if (!event.show) {
hideFloatWindow()
}
if (event.show && event.meditationDetail != null) {
if (!windowIsShow) {
showWindow()
}
updateFloatView(event.meditationDetail)
}
}
private fun updateFloatView(meditation: MeditationPlayModuleBean.MeditationDetail) {
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
floatRootView?.setOnClickListener {
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.mediaType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.flags = FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
ivProgress?.maxProcess = mMediaPlayer?.duration ?: 0
ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
Glide.with(floatRootView!!)
.load(meditation.coverImageUrl)
.into(ivCover!!)
tvTitle?.text = meditation.title
ivPlayOrPause?.setOnClickListener {
if (mMediaPlayer?.isPlaying == true) {
MediaPlayerManager.getInstance(this)?.pause()
if (meditation.meditationId != null && meditation.mediaId != null) {
MuseHttp.getInstance().postMeditationPlayRecord(
meditationId = meditation.meditationId!!.toInt(),
isQuit = 1, mediaId = meditation.mediaId!!,
playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0,
isComplete = 0
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
}, {
object : ThrowableConsumer() {
override fun accept(msg: String) {
}
}
})
}
} else {
MediaPlayerManager.getInstance(this)?.play()
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
}
mTimer.schedule(object : TimerTask() {
override fun run() {
ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
}
}, 0, 50)
mMediaPlayer?.setOnCompletionListener {
postPlayRecord(
0, (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0,
1,
meditation.meditationId.toInt(),
meditation.mediaId ?: 0L
)
}
ivClose?.setOnClickListener {
postPlayRecord(
1, (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0,
0,
meditation.meditationId.toInt(),
meditation.mediaId ?: 0L
)
MediaPlayerManager.getInstance(this)?.stop()
hideFloatWindow()
}
}
private fun hideFloatWindow() {
if (floatRootView != null && floatRootView?.windowToken != null) {
if (mWindowManager != null) {
windowIsShow = false
mTimer.cancel()
mWindowManager.removeViewImmediate(floatRootView)
}
}
}
override fun onDestroy() {
super.onDestroy()
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this)
}
}
private fun dp2px(dp: Float): Int {
val scale = resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
private fun postPlayRecord(
isQuit: Int,
playTime: Int,
isComplete: Int,
meditationId: Int,
mediaId: Long
) {
MuseHttp.getInstance().postMeditationPlayRecord(
meditationId = meditationId,
isQuit = isQuit, mediaId = mediaId,
playTime = playTime,
isComplete = isComplete
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
}, {
object : ThrowableConsumer() {
override fun accept(msg: String) {
}
}
})
}
}
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="8dp"
android:height="9dp"
android:viewportWidth="8"
android:viewportHeight="9">
<path
android:pathData="M6.64877,5.7528L1.82138,8.7257C1.46481,8.94528 0.99774,8.83422 0.77811,8.47766C0.7045,8.35811 0.66553,8.22046 0.66553,8.08006L0.66553,0.84302C0.66553,0.42426 1.005,0.08478 1.42377,0.08478C1.56418,0.08478 1.70181,0.12375 1.82138,0.19738L6.64877,3.17028C7.36191,3.60946 7.58401,4.54359 7.14481,5.25674C7.02051,5.4586 6.85062,5.62849 6.64877,5.7528L6.64877,5.7528Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="9dp"
android:height="9dp"
android:viewportWidth="9"
android:viewportHeight="9">
<path
android:pathData="M1.97559,0.16724C2.66594,0.16724 3.22559,0.72688 3.22559,1.41724L3.22559,6.91724C3.22559,7.60759 2.66594,8.16724 1.97559,8.16724C1.28523,8.16724 0.72559,7.60759 0.72559,6.91724L0.72559,1.41724C0.72559,0.72688 1.28523,0.16724 1.97559,0.16724Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M6.97559,0.16724C7.66594,0.16724 8.22559,0.72688 8.22559,1.41724L8.22559,6.91724C8.22559,7.60759 7.66594,8.16724 6.97559,8.16724C6.28523,8.16724 5.72559,7.60759 5.72559,6.91724L5.72559,1.41724C5.72559,0.72688 6.28523,0.16724 6.97559,0.16724Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
......@@ -2,6 +2,9 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/bg_play_meditation_float_view"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
......@@ -9,9 +12,8 @@
android:id="@+id/csl_root_layout"
android:layout_width="match_parent"
android:layout_height="56dp"
tools:background="@drawable/play_float_background"
android:background="@drawable/bg_play_meditation_float_view"
android:layout_marginHorizontal="16dp">
tools:background="@drawable/play_float_background">
<ImageView
android:id="@+id/iv_close"
......@@ -40,6 +42,7 @@
android:id="@+id/iv_cover"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
android:src="@drawable/platform_loading_logo"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
......@@ -67,17 +70,23 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ProgressBar
<io.feeeei.circleseekbar.CircleSeekBar
android:id="@+id/progress_bar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center" />
android:layout_gravity="center"
app:wheel_unreached_color="#FF282E3F"
app:wheel_reached_color="#FFFFFF"
app:wheel_unreached_width="2dp"
app:wheel_reached_width="2dp"/>
<ImageView
android:id="@+id/iv_play_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="5dp"
android:layout_gravity="center"
android:src="@drawable/icon_meditation_float_pause"/>
</FrameLayout>
......
......@@ -483,13 +483,6 @@ public class MineFragment extends BaseFragment implements SwipeRefreshLayout.OnR
return;
}
ModularServiceManager.INSTANCE.provide(ICourseService.class).startMyCourseActivity(mActivity);
} else if (id == R.id.ll_meditation){ //冥想
if (!OneKeyLoginHelp.INSTANCE.startLoginByStatus(mActivity,true)) {
return;
}
H5Params h5Params3 = new H5Params(HttpConfig.Companion.getMH5_URL() + "meditation?hideNavBar=1", null);
NewH5Activity.start(getActivity(), h5Params3);
} else if (id == R.id.ll_call_order) {//倾诉
ActionCountUtils.Companion.count(YDL_USER_MY_MIDDLE_TYPE_CLICK,"倾诉记录");
if (!OneKeyLoginHelp.INSTANCE.startLoginByStatus(mActivity,true)) {
......
......@@ -116,6 +116,9 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
rootView.findViewById<View>(R.id.ll_my_test_log).setOnClickListener(this)
//客服
rootView.findViewById<View>(R.id.ll_service).setOnClickListener(this)
//冥想
rootView.findViewById<View>(R.id.ll_meditation).setOnClickListener(this)
init()
GlideApp.with(this).load("https://static.yidianling.com/banner/bottombanner@2x.png")
.into(iv_mine_logo)
......@@ -130,14 +133,10 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
.getGlobalInfo()?.info && null != PlatformRamImpl.getInstance()
.getGlobalInfo()?.info?.app_share
) {
share_title =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.title.toString()
share_context =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.descrip.toString()
share_head =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.cover_url.toString()
share_url =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.dl_url.toString()
share_title = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.title.toString()
share_context = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.descrip.toString()
share_head = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.cover_url.toString()
share_url = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.dl_url.toString()
}
}
......@@ -492,6 +491,9 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
} else if (id == R.id.jtv_test) { //debug下任意门入口
jtv_test?.postDelayed({ YdlBuryPointUtil.sendPv("PvEvent") }, 300)
jtv_test?.postDelayed({ YdlBuryPointUtil.sendClick("ClickEvent") }, 500)
} else if (id == R.id.ll_meditation) { //冥想
val h5Params3 = H5Params(MH5_URL + "meditation?hideNavBar=1", null)
NewH5Activity.start(activity, h5Params3)
}
}
......
......@@ -51,7 +51,6 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation project(path: ':ydl-platform')
kapt 'com.alibaba:arouter-compiler:1.2.2'
api rootProject.ext.dependencies["ydl-user-router"]
api fileTree(include: ['*.jar'], dir: 'libs')
......
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