Commit d254304b by 刘鹏

Merge remote-tracking branch 'origin/feat/qj/new_nim2' into feat/lp/lp_nim2

# Conflicts:
#	app/src/main/java/com/ydl/component/MainActivity.kt
#	build.gradle
#	m-im/build.gradle
#	m-im/src/main/java/com/yidianling/im/helper/NimUICallInit.java
#	m-muse/build.gradle
#	settings.gradle
#	ydl-media/build.gradle
parents 40a5a6e7 385cfcd1
......@@ -177,6 +177,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.github.feeeei:CircleSeekbar:v1.1.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation(rootProject.ext.dependencies["appcompat-v7"])
testImplementation 'junit:junit:4.13.2'
......
......@@ -6,13 +6,21 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.os.IBinder
import android.provider.Settings
import android.text.TextUtils
import android.util.DisplayMetrics
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.launcher.ARouter
import com.bumptech.glide.Glide
import com.tbruyelle.rxpermissions2.RxPermissions
import com.tencent.qcloud.tuicore.calling.trtccalling.model.TRTCCalling
import com.tencent.qcloud.tuicore.calling.videocall.Constant
......@@ -26,16 +34,23 @@ import com.ydl.component.route.PlatformTempCommonRouteImpl
import com.ydl.component.rtc.MDTLoginActivity
import com.ydl.confide.home.ConfideHomeActivity
import com.ydl.media.audio.PlayService
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.mvp.lce.BaseLceActivity
import com.ydl.ydlcommon.router.YdlCommonRouterManager
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
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.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.helper.FloatViewTouchListener
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.user.api.service.IUserService
import com.yidianling.user.ui.collect.CollectSexAndBirthActivity
......@@ -43,7 +58,16 @@ import com.yidianling.user.ui.login.OneKeyLoginHelp
import com.yidianling.user.widget.SecretDialog
import com.yidianling.user.widget.SecretDialog.OnSecretDialogListener
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 java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
/**
......@@ -56,12 +80,10 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// private var secretDescriptionDialog: SecretDescriptionDialog? = null
private var serviceConnection: ServiceConnection? = null
private var meditationServiceConnection: ServiceConnection? = null
private var secretDialog: SecretDialog? = null
protected var playService: PlayService? = null
protected var meditationService: MeditationWindowService? = null
private var mFloatDisposable:Disposable?=null
override fun getContentViewId(): Int {
return R.id.lce_content_view
......@@ -99,7 +121,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
2
)
bindService()
bindMeditationService()
initMeditationObserver()
reLoadData()
requestPermission()
......@@ -277,11 +300,18 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun bindMeditationService() {
val intent = Intent()
intent.setClass(this, MeditationWindowService::class.java)
meditationServiceConnection = MeditationServiceConnection()
bindService(intent, meditationServiceConnection, Context.BIND_AUTO_CREATE)
private fun initMeditationObserver(){
mFloatDisposable = Observable.interval(500,TimeUnit.MILLISECONDS)
.filter { true }
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
if (!windowIsShow && mToShowWindow){
showWindow()
}else if (windowIsShow && !mToShowWindow){
hideFloatWindow()
}
mCurrentMeditation?.let { it1 -> updateFloatView(it1) }
}
}
override fun onResume() {
......@@ -318,11 +348,14 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
if (serviceConnection != null) {
unbindService(serviceConnection)
}
if (meditationServiceConnection != null) {
EventBus.getDefault().post(MeditationFloatEvent(false))
MediaPlayerManager.getInstance(this)?.stop()
unbindService(meditationServiceConnection)
}
MediaPlayerManager.getInstance(this)?.stop()
hideFloatWindow()
mDisposable?.dispose()
mFloatDisposable?.dispose()
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this)
}
......@@ -339,17 +372,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() {
secretDialog = SecretDialog(this, object : OnSecretDialogListener {
override fun onCancel() {
......@@ -367,4 +389,333 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
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>)
}
}
}
......@@ -14,7 +14,7 @@ buildscript {
ydlrouter_version = '1.2.3'
constrait_support_version = '1.0.2'
componentVersion = "0.3.0.4-SNAPSHOT"
componentVersion = "0.3.0.5-SNAPSHOT"
}
repositories {
mavenCentral()
......@@ -51,6 +51,7 @@ allprojects { p ->
url 'http://maven.aliyun.com/nexus/content/groups/public/'
allowInsecureProtocol true
}
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
mavenLocal()
}
}
......
......@@ -63,7 +63,11 @@ dependencies {
implementation rootProject.ext.dependencies["BaseRecyclerViewAdapterHelper"]
api 'com.tencent.tbs.tbssdk:sdk:43903'
implementation('com.netease.yunxin.kit:call-ui:1.5.6')
implementation('com.netease.yunxin.kit:call-ui:1.5.9-SNAPSHOT') {
exclude group: "com.netease.nimlib", module: "avsignalling"
exclude group: "com.netease.nimlib", module: "basesdk"
}
implementation "com.netease.nimlib:avsignalling:9.1.1"
api project(':ydl-webview')
api project(':ydl-platform')
......
......@@ -31,7 +31,7 @@ import java.io.IOException;
* 云信sdk 自定义的SDK选项设置
*/
class NimSDKOptionConfig {
public class NimSDKOptionConfig {
static SDKOptions prepareSDKOptions(Context context, Class activity, IMInitConfigBean configBean) {
SDKOptions options = new SDKOptions();
......@@ -93,7 +93,7 @@ class NimSDKOptionConfig {
* 配置 APP 保存图片/语音/文件/log等数据的目录
* 这里示例用SD卡的应用扩展存储目录
*/
static String getAppCacheDir(Context context) {
public static String getAppCacheDir(Context context) {
String storageRootPath = null;
try {
// SD卡应用扩展存储区(APP卸载后,该目录下被清除,用户也可以在设置界面中手动清除),请根据APP对数据缓存的重要性及生命周期来决定是否采用此缓存目录.
......
......@@ -19,6 +19,7 @@ import com.ydl.ydlcommon.modular.ModularServiceManagerKt;
import com.ydl.ydlcommon.utils.log.XLog;
import com.yidianling.im.R;
import com.yidianling.im.config.NimApplication;
import com.yidianling.im.config.NimSDKOptionConfig;
import com.yidianling.im.http.ImHttpImpl;
import com.yidianling.user.api.bean.UserResponseBean;
import com.yidianling.user.api.service.IUserService;
......@@ -46,6 +47,7 @@ public class NimUICallInit {
CallKitUIOptions options = new CallKitUIOptions.Builder()
// 必要:音视频通话 sdk appKey,用于通话中使用
.rtcAppKey(appKey)
.logRootPath(NimSDKOptionConfig.getAppCacheDir(context) + "/yidianling")
// 必要:当前用户 AccId
.currentUserAccId(userId)
.currentUserRtcUId(Long.parseLong(userId))
......
......@@ -26,7 +26,5 @@
android:screenOrientation="portrait"
android:theme="@style/un_full_screen_activity"/>
<service android:name=".service.MeditationWindowService"/>
</application>
</manifest>
......@@ -453,7 +453,7 @@ class PlayMeditationActivity : BaseActivity() {
meditation = currentMeditation?.copy(
meditationType = mMeditationType, meditationId =
mMeditationId ?: 0
)
),meditations = meditations
)
EventBus.getDefault().post(event)
......@@ -1070,7 +1070,7 @@ class PlayMeditationActivity : BaseActivity() {
}
override fun onBackPressed() {
val event = MeditationFloatEvent(true, meditation = currentMeditation)
val event = MeditationFloatEvent(true, meditation = currentMeditation,meditations = meditations)
EventBus.getDefault().post(event)
super.onBackPressed()
}
......
......@@ -7,6 +7,6 @@ class MeditationFloatEvent(
val stop: Boolean? = null,
val time: Long? = 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