Commit cd0c4e62 by 刘鹏

Merge branch 'feat/lancet/meditation_optimize' into 'd/v4.4.05'

remove  MeditationService

See merge request app_android_lib/YDL-Component!268
parents e0af8ed2 e41cb057
...@@ -6,13 +6,21 @@ import android.content.ComponentName ...@@ -6,13 +6,21 @@ import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.provider.Settings import android.provider.Settings
import android.text.TextUtils import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.Log import android.util.Log
import android.view.*
import android.widget.ImageView
import android.widget.TextView
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.android.arouter.launcher.ARouter
import com.bumptech.glide.Glide
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper
import com.tbruyelle.rxpermissions2.RxPermissions import com.tbruyelle.rxpermissions2.RxPermissions
import com.tencent.qcloud.tuicore.calling.trtccalling.model.TRTCCalling import com.tencent.qcloud.tuicore.calling.trtccalling.model.TRTCCalling
...@@ -27,16 +35,23 @@ import com.ydl.component.route.PlatformTempCommonRouteImpl ...@@ -27,16 +35,23 @@ import com.ydl.component.route.PlatformTempCommonRouteImpl
import com.ydl.component.rtc.MDTLoginActivity import com.ydl.component.rtc.MDTLoginActivity
import com.ydl.confide.home.ConfideHomeActivity import com.ydl.confide.home.ConfideHomeActivity
import com.ydl.media.audio.PlayService import com.ydl.media.audio.PlayService
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.modular.ModularServiceManager import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.mvp.lce.BaseLceActivity import com.ydl.ydlcommon.mvp.lce.BaseLceActivity
import com.ydl.ydlcommon.router.YdlCommonRouterManager import com.ydl.ydlcommon.router.YdlCommonRouterManager
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.common.tools.LogUtil import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.ToastUtil import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.api.IConsultantService import com.yidianling.consultant.api.IConsultantService
import com.yidianling.fm.api.service.IFMService import com.yidianling.fm.api.service.IFMService
import com.yidianling.home.http.MuseHttp
import com.yidianling.muse.activity.PlayMeditationActivity
import com.yidianling.muse.bean.MeditationPlayModuleBean
import com.yidianling.muse.constants.MuseBIConstants
import com.yidianling.muse.event.MeditationFloatEvent import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.FloatViewTouchListener
import com.yidianling.muse.helper.MediaPlayerManager import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.service.MeditationWindowService import com.yidianling.muse.utils.MediaPlayerTimeUtil
import com.yidianling.tests.home.NewTestHomeActivity import com.yidianling.tests.home.NewTestHomeActivity
import com.yidianling.user.api.service.IUserService import com.yidianling.user.api.service.IUserService
import com.yidianling.user.ui.collect.CollectSexAndBirthActivity import com.yidianling.user.ui.collect.CollectSexAndBirthActivity
...@@ -45,7 +60,16 @@ import com.yidianling.user.widget.SecretDescriptionDialog ...@@ -45,7 +60,16 @@ import com.yidianling.user.widget.SecretDescriptionDialog
import com.yidianling.user.widget.SecretDialog import com.yidianling.user.widget.SecretDialog
import com.yidianling.user.widget.SecretDialog.OnSecretDialogListener import com.yidianling.user.widget.SecretDialog.OnSecretDialogListener
import de.greenrobot.event.EventBus import de.greenrobot.event.EventBus
import io.feeeei.circleseekbar.CircleSeekBar
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
/** /**
...@@ -58,12 +82,10 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -58,12 +82,10 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// private var secretDescriptionDialog: SecretDescriptionDialog? = null // private var secretDescriptionDialog: SecretDescriptionDialog? = null
private var serviceConnection: ServiceConnection? = null private var serviceConnection: ServiceConnection? = null
private var meditationServiceConnection: ServiceConnection? = null
private var secretDialog: SecretDialog? = null private var secretDialog: SecretDialog? = null
protected var playService: PlayService? = null protected var playService: PlayService? = null
protected var meditationService: MeditationWindowService? = null private var mFloatDisposable:Disposable?=null
override fun getContentViewId(): Int { override fun getContentViewId(): Int {
return R.id.lce_content_view return R.id.lce_content_view
...@@ -101,7 +123,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -101,7 +123,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
PhoneNumberAuthHelper.SERVICE_TYPE_LOGIN PhoneNumberAuthHelper.SERVICE_TYPE_LOGIN
) )
bindService() bindService()
bindMeditationService()
initMeditationObserver()
reLoadData() reLoadData()
requestPermission() requestPermission()
...@@ -279,11 +302,18 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -279,11 +302,18 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
} }
private fun bindMeditationService() { private fun initMeditationObserver(){
val intent = Intent() mFloatDisposable = Observable.interval(500,TimeUnit.MILLISECONDS)
intent.setClass(this, MeditationWindowService::class.java) .filter { true }
meditationServiceConnection = MeditationServiceConnection() .observeOn(AndroidSchedulers.mainThread())
bindService(intent, meditationServiceConnection, Context.BIND_AUTO_CREATE) .subscribe {
if (!windowIsShow && mToShowWindow){
showWindow()
}else if (windowIsShow && !mToShowWindow){
hideFloatWindow()
}
mCurrentMeditation?.let { it1 -> updateFloatView(it1) }
}
} }
override fun onResume() { override fun onResume() {
...@@ -320,11 +350,14 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -320,11 +350,14 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
if (serviceConnection != null) { if (serviceConnection != null) {
unbindService(serviceConnection) unbindService(serviceConnection)
} }
if (meditationServiceConnection != null) {
EventBus.getDefault().post(MeditationFloatEvent(false)) MediaPlayerManager.getInstance(this)?.stop()
MediaPlayerManager.getInstance(this)?.stop()
unbindService(meditationServiceConnection) hideFloatWindow()
}
mDisposable?.dispose()
mFloatDisposable?.dispose()
if (EventBus.getDefault().isRegistered(this)) { if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this) EventBus.getDefault().unregister(this)
} }
...@@ -341,17 +374,6 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -341,17 +374,6 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
} }
} }
private inner class MeditationServiceConnection : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
meditationService = (service as MeditationWindowService.MeditationBinder).service
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
private fun showEnsureDialog() { private fun showEnsureDialog() {
secretDialog = SecretDialog(this, object : OnSecretDialogListener { secretDialog = SecretDialog(this, object : OnSecretDialogListener {
override fun onCancel() { override fun onCancel() {
...@@ -369,4 +391,333 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>( ...@@ -369,4 +391,333 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
secretDialog!!.show() secretDialog!!.show()
} }
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 mMeditations = mutableListOf<MeditationPlayModuleBean.MeditationDetail>()
private var windowIsShow = false
private var mToShowWindow = false
private var mUpdate = false
private var mObservable: Observable<Long>? = null
private var mObserver: Observer<Long>? = null
private var currentMediaId:Long? = null
private var mDisposable:Disposable?=null
private var currentMeditationIndex = 0
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 = ViewGroup.LayoutParams.WRAP_CONTENT
gravity = Gravity.LEFT or Gravity.TOP
x = outMetrics.widthPixels /2 - width / 2
y = outMetrics.heightPixels - dp2px(140F)
}
floatRootView =
LayoutInflater.from(this).inflate(com.yidianling.muse.R.layout.layout_meditation_play_float_view, null)
ivClose = floatRootView?.findViewById(com.yidianling.muse.R.id.iv_close)
ivCover = floatRootView?.findViewById(com.yidianling.muse.R.id.iv_cover)
tvTitle = floatRootView?.findViewById(com.yidianling.muse.R.id.tv_title)
ivProgress = floatRootView?.findViewById(com.yidianling.muse.R.id.progress_bar)
ivPlayOrPause = floatRootView?.findViewById(com.yidianling.muse.R.id.iv_play_status)
floatRootView?.setOnTouchListener(FloatViewTouchListener(layoutParams, mWindowManager))
mWindowManager.addView(floatRootView, layoutParams)
windowIsShow = true
}
fun onEventMainThread(event: Any) {
if (event is com.ydl.ydlcommon.event.MeditationFloatEvent){
mToShowWindow = event.show
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
}
}
}
if (event is MeditationFloatEvent){
mToShowWindow = event.show
if (event.time!=null){
if (event.time!! >0){
initRxTimeOff(event.time!!)
}else{
mDisposable?.dispose()
}
}else{
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
}
}
}
if (event.show!=null && event.show && event.meditation != null && event.meditations!=null) {
mCurrentMeditation = event.meditation
mMeditations.addAll(event.meditations!!)
}
}
}
private fun updateFloatView(meditation: MeditationPlayModuleBean.MeditationDetail) {
currentMediaId = meditation.mediaId
MediaPlayerManager.getInstance(this)?.setMediaId(currentMediaId)
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
tvTitle?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
ivCover?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(com.yidianling.muse.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) {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PAUSE_CLICK,"")
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 {
//悬浮窗播放点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PLAY_CLICK,"")
MediaPlayerManager.getInstance(this)?.play()
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_pause)
}
}
mTimer.schedule(object : TimerTask() {
override fun run() {
ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
}
}, 0, 50)
mMediaPlayer?.setOnCompletionListener {
val duration = meditation?.duration?.toInt()?:0
val currentDuration = (mMediaPlayer?.currentPosition?:0)/1000
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
if(duration == currentDuration){
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 1
)
}
}
switchSound()
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_pause)
}
}
ivClose?.setOnClickListener {
//悬浮窗关闭点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLOSE_CLICK,"")
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
}
MediaPlayerManager.getInstance(this)?.stop()
hideFloatWindow()
}
mUpdate = false
}
private fun hideFloatWindow() {
if (floatRootView != null && floatRootView?.windowToken != null) {
if (mWindowManager != null) {
mWindowManager.removeViewImmediate(floatRootView)
}
}
windowIsShow = false
}
private fun switchSound() {
mMeditations?.forEachIndexed { index, meditationDetail ->
if (meditationDetail.mediaId == mCurrentMeditation?.mediaId) {
currentMeditationIndex = index
}
}
if (currentMeditationIndex < mMeditations.size - 1) {
mCurrentMeditation = mMeditations[currentMeditationIndex + 1]
} else {
mCurrentMeditation = mMeditations[0]
}
mUpdate = true
updateFloatView(mCurrentMeditation!!)
initMediaPlayer(mCurrentMeditation!!.mediaUrl)
}
private fun initMediaPlayer(path: String) {
MediaPlayerManager.getInstance(this)?.setAudioPath(path)
MediaPlayerManager.getInstance(this)
?.setOnPreparedListener(object : MediaPlayerManager.OnMediaPlayerManagerListener {
override fun onPrepared(mediaPlayer: MediaPlayer) {
MediaPlayerManager.getInstance(this@MainActivity)?.play()
}
})
}
private fun dp2px(dp: Float): Int {
val scale = resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
private fun initRxTimeOff(time: Long) {
mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
.take(time / 1000 + 1)
.map { t -> time - t * 1000 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
mObserver = object : Observer<Long> {
override fun onSubscribe(d: Disposable) {
mDisposable = d
}
override fun onNext(t: Long) {
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
if (mMediaPlayer?.isPlaying == true) {
mMediaPlayer?.stop()
ivPlayOrPause?.setImageResource(com.yidianling.muse.R.drawable.icon_meditation_float_pause)
}
hideFloatWindow()
}
}
if (mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
}
} }
...@@ -26,7 +26,5 @@ ...@@ -26,7 +26,5 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/un_full_screen_activity"/> android:theme="@style/un_full_screen_activity"/>
<service android:name=".service.MeditationWindowService"/>
</application> </application>
</manifest> </manifest>
...@@ -453,7 +453,7 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -453,7 +453,7 @@ class PlayMeditationActivity : BaseActivity() {
meditation = currentMeditation?.copy( meditation = currentMeditation?.copy(
meditationType = mMeditationType, meditationId = meditationType = mMeditationType, meditationId =
mMeditationId ?: 0 mMeditationId ?: 0
) ),meditations = meditations
) )
EventBus.getDefault().post(event) EventBus.getDefault().post(event)
...@@ -1070,7 +1070,7 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -1070,7 +1070,7 @@ class PlayMeditationActivity : BaseActivity() {
} }
override fun onBackPressed() { override fun onBackPressed() {
val event = MeditationFloatEvent(true, meditation = currentMeditation) val event = MeditationFloatEvent(true, meditation = currentMeditation,meditations = meditations)
EventBus.getDefault().post(event) EventBus.getDefault().post(event)
super.onBackPressed() super.onBackPressed()
} }
......
...@@ -7,6 +7,6 @@ class MeditationFloatEvent( ...@@ -7,6 +7,6 @@ class MeditationFloatEvent(
val stop: Boolean? = null, val stop: Boolean? = null,
val time: Long? = null, val time: Long? = null,
val meditation: MeditationPlayModuleBean.MeditationDetail? = null, val meditation: MeditationPlayModuleBean.MeditationDetail? = null,
val meditations: ArrayList<MeditationPlayModuleBean.MeditationDetail>? = null val meditations: MutableList<MeditationPlayModuleBean.MeditationDetail>? = null
) )
package com.yidianling.muse.service
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.os.Binder
import android.os.Build
import android.os.IBinder
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.core.app.NotificationCompat
import com.bumptech.glide.Glide
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
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.constants.MuseBIConstants
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.FloatViewTouchListener
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import de.greenrobot.event.EventBus
import io.feeeei.circleseekbar.CircleSeekBar
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.player_control_view.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
class MeditationWindowService : Service() {
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 mMeditations = mutableListOf<MeditationPlayModuleBean.MeditationDetail>()
private var windowIsShow = false
private var mDisposable: Disposable? = null
private var mObservable: Observable<Long>? = null
private var mObserver: Observer<Long>? = null
private var currentMediaId:Long? = null
inner class MeditationBinder : Binder() {
val service: MeditationWindowService
get() = this@MeditationWindowService
}
override fun onCreate() {
super.onCreate()
EventBus.getDefault().register(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel("壹点灵", "play", NotificationManager.IMPORTANCE_HIGH)
manager.createNotificationChannel(channel)
val notification = NotificationCompat.Builder(this, "壹点灵").build()
startForeground(1, notification)
}
}
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.LEFT or Gravity.TOP
x = outMetrics.widthPixels /2 - width / 2
y = outMetrics.heightPixels - dp2px(140F)
}
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: Any) {
if (event is com.ydl.ydlcommon.event.MeditationFloatEvent){
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
hideFloatWindow()
}
hideFloatWindow()
}
}
if (event is MeditationFloatEvent){
if (event.time!=null){
if (event.time>0){
initRxTimeOff(event.time)
}else{
mDisposable?.dispose()
}
}else{
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
hideFloatWindow()
}
hideFloatWindow()
}
if (event.show!=null && event.show && event.meditation != null) {
if (!windowIsShow) {
showWindow()
}
updateFloatView(event.meditation)
}
}
}
}
private fun updateFloatView(meditation: MeditationPlayModuleBean.MeditationDetail) {
currentMediaId = meditation.mediaId
MediaPlayerManager.getInstance(this)?.setMediaId(currentMediaId)
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
tvTitle?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
intent.flags = FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
ivCover?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
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) {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PAUSE_CLICK,"")
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 {
//悬浮窗播放点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PLAY_CLICK,"")
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 {
val duration = meditation?.duration?.toInt()?:0
val currentDuration = (mMediaPlayer?.currentPosition?:0)/1000
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
if(duration == currentDuration){
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 1
)
}
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
}
ivClose?.setOnClickListener {
//悬浮窗关闭点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLOSE_CLICK,"")
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
}
MediaPlayerManager.getInstance(this)?.stop()
hideFloatWindow()
}
}
private fun hideFloatWindow() {
if (floatRootView != null && floatRootView?.windowToken != null) {
if (mWindowManager != null) {
windowIsShow = false
mWindowManager.removeViewImmediate(floatRootView)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun startForegroundService(service: Intent?): ComponentName? {
return super.startForegroundService(service)
}
override fun onDestroy() {
super.onDestroy()
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this)
}
mDisposable?.dispose()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
stopForeground(true)
}
}
override fun onBind(intent: Intent?): IBinder? {
return MeditationBinder()
}
private fun dp2px(dp: Float): Int {
val scale = resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
private fun initRxTimeOff(time: Long) {
mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
.take(time / 1000 + 1)
.map { t -> time - t * 1000 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
mObserver = object : Observer<Long> {
override fun onSubscribe(d: Disposable) {
mDisposable = d
}
override fun onNext(t: Long) {
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
if (mMediaPlayer?.isPlaying == true) {
mMediaPlayer?.stop()
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
hideFloatWindow()
}
}
if (mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
}
}
\ No newline at end of file
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