From 718f31c92e2029d05260810435a2c70cef6e6ce5 Mon Sep 17 00:00:00 2001 From: lmw <125975490@qq.com> Date: 星期四, 24 四月 2025 10:45:55 +0800 Subject: [PATCH] save --- app/src/main/java/com/sinata/xqmuse/MainActivity.kt | 473 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 424 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/sinata/xqmuse/MainActivity.kt b/app/src/main/java/com/sinata/xqmuse/MainActivity.kt index 9978b5e..c341a57 100644 --- a/app/src/main/java/com/sinata/xqmuse/MainActivity.kt +++ b/app/src/main/java/com/sinata/xqmuse/MainActivity.kt @@ -1,49 +1,286 @@ package com.sinata.xqmuse +import android.annotation.SuppressLint import android.content.Intent +import android.net.Uri +import android.os.* +import android.provider.Settings +import android.util.Log +import android.view.Gravity +import android.view.View import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentPagerAdapter import cn.sinata.xldutils.gone import cn.sinata.xldutils.utils.SPUtils +import cn.sinata.xldutils.visible import com.flyco.tablayout.listener.CustomTabEntity import com.flyco.tablayout.listener.OnTabSelectListener -import com.github.zackratos.ultimatebar.UltimateBar +import com.google.gson.Gson +import com.lzf.easyfloat.EasyFloat +import com.lzf.easyfloat.enums.ShowPattern +import com.lzf.easyfloat.enums.SidePattern +import com.lzf.easyfloat.interfaces.OnInvokeView import com.sinata.xqmuse.dialog.TipDialog import com.sinata.xqmuse.network.HttpManager -import com.sinata.xqmuse.network.entity.UserInfo +import com.sinata.xqmuse.network.entity.VoiceDetail +import com.sinata.xqmuse.network.entity.req.ReqAnswer import com.sinata.xqmuse.network.request import com.sinata.xqmuse.ui.TransparentStatusBarActivity import com.sinata.xqmuse.ui.course.CourseFragment import com.sinata.xqmuse.ui.discovery.DiscoveryFragment +import com.sinata.xqmuse.ui.guide.GuideActivity import com.sinata.xqmuse.ui.home.HomeFragment +import com.sinata.xqmuse.ui.login.LoginActivity import com.sinata.xqmuse.ui.mine.MineFragment import com.sinata.xqmuse.ui.mine.ShareActivity import com.sinata.xqmuse.ui.tree.TreeFragment +import com.sinata.xqmuse.utils.AudioUtils import com.sinata.xqmuse.utils.Const import com.sinata.xqmuse.utils.event.EmptyEvent +import com.sinata.xqmuse.utils.event.IntEvent +import com.umeng.socialize.utils.DeviceConfigInternal.context import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.android.synthetic.main.fragment_home.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.jetbrains.anko.startActivity +import org.jetbrains.anko.toast +import xyz.doikki.videoplayer.player.VideoView -class MainActivity : TransparentStatusBarActivity(), OnTabSelectListener{ + +class MainActivity : TransparentStatusBarActivity(), OnTabSelectListener,AudioUtils.OnAudioStatusUpdateListener { override fun setContentView() = R.layout.activity_main private val fragments = arrayListOf<Fragment>() - var homeData: UserInfo? = null //个人信息 + + var teacherVideoView:VideoView? = null + private var bgPlayer:AudioUtils? = null//背景音乐播放器 +// private var thinkBgPlayer:AudioUtils? = null//冥想背景音播放器 +// private var thinkPlayer:AudioUtils? = null//冥想背景音播放器 + + private var guideAudio:String? = null + private var guidePlayer:AudioUtils? = null//引导音频播放器 + + private var thinkHandler:Handler? = null //冥想时间相关 + private var inGuide = false //true 引导中... + + private val isFirst by lazy { intent.getBooleanExtra("isFirst", false) } //首次安装,需要到导师引导页 + + private val MSG_PROGRESS = 0//疗愈进度+1 + private val MSG_TODAY = 1//今日疗愈更新计时 + private val MSG_COUNTDOWN = 2//疗愈倒计时 + + private var lastTodayTime = 0L //上一次今日疗愈获取的时间 + + private var startTime = 0L //开始疗愈的时间戳 + + var hasTreeFirstShow = false //此字段用来判断 树苗的首次弹窗是否已经触发,和isFirst字段配合使用 + var isBGMChanged = false //此字段用来判断 在疗愈播放中,修改了背景音乐,在疗愈结束后 需要更新BGM音源 + + private val EasyFloatTag = "BACKGROUND" + private var floater: EasyFloat.Builder? = null //浮窗 override fun initClick() { + player_close.setOnClickListener { + TipDialog.show(supportFragmentManager, "是否关闭当前音频?", object : TipDialog.OnClickCallback { + override fun onOk() { + EventBus.getDefault().post(EmptyEvent(Const.EventCode.FINISH_THINK)) + } + + override fun onCancel() { + } + }, "确认", "取消") + } + + cl_player.setOnClickListener { + ThinkAudioService.voice?.goDetail(this) + } + + player_play.setOnClickListener { + ThinkAudioService.playing = !ThinkAudioService.playing + if (ThinkAudioService.playing){ + player_play.setImageResource(R.mipmap.player_pause) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.USER_INFO_CHANGED)) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.SERVICE_AUDIO_RESUME)) +// thinkBgPlayer?.resume() +// thinkPlayer?.resume() + thinkHandler?.sendEmptyMessage(MSG_PROGRESS) + startTime = System.currentTimeMillis() + }else{ + player_play.setImageResource(R.mipmap.player_start) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.USER_INFO_CHANGED)) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.SERVICE_AUDIO_PAUSE)) +// thinkBgPlayer?.pause() +// thinkPlayer?.pause() + thinkHandler?.removeMessages(MSG_PROGRESS) + saveThinkRecord() + } + (fragments[0] as HomeFragment).refreshTodayPlayingState() + } } override fun initView() { + EventBus.getDefault().register(this) titleBar.gone() useWhiteTitle() + startBgm() initTab() - EventBus.getDefault().register(this) - getData() if (!intent.getStringExtra("code").isNullOrEmpty()){ startActivity<ShareActivity>("code" to intent.getStringExtra("code")) + } + if (isFirst) //解决首次安装启动eventbus注册慢的问题 + startActivity<GuideActivity>() + + thinkHandler = object :Handler(Looper.myLooper()!!){ + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + when(msg.what){ + MSG_PROGRESS -> { + EventBus.getDefault().post(EmptyEvent(Const.EventCode.SERVICE_AUDIO_PROGRESS)) + sendEmptyMessageDelayed(MSG_PROGRESS, 1000) + if (System.currentTimeMillis() - startTime >= 60000){ + saveThinkRecord() + } + } + MSG_COUNTDOWN -> { + if (System.currentTimeMillis() >= ThinkAudioService.finishTime) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.FINISH_THINK)) + else + sendEmptyMessageDelayed(MSG_COUNTDOWN, 1000) + } + MSG_TODAY -> { //todo 分离hanlder,这个保持原功能,进度和计时相关应放进Service + if (System.currentTimeMillis() - lastTodayTime > 60000) { //距离上次刷新过去了1分钟 + Log.e(Const.Tag, "已经过1分钟,需要重新获取今日疗愈数据") + lastTodayTime = System.currentTimeMillis() + (fragments[0] as HomeFragment).getToday() + } + sendEmptyMessageDelayed(MSG_TODAY, 5000) + } + } + } + } + lastTodayTime = System.currentTimeMillis() + startTodayCheck() + } + + private fun startGuide() { + if (guidePlayer == null) + guidePlayer = AudioUtils() + if (guideAudio.isNullOrEmpty()) + HttpManager.getPlan().request(this){ _, data-> + guideAudio = data + if (inGuide){ + guidePlayer?.setVolume(0.6f) + guidePlayer?.loopPlayMusic(this, data) + } + } + else{ + guidePlayer?.setVolume(0.6f) + guidePlayer?.loopPlayMusic(this, guideAudio) + } + } + + private fun startBgm() { + HttpManager.getHomeBackgroundMusicByUserId().request(this){ _, data-> + if (!data?.audioFile.isNullOrEmpty()){ + if (bgPlayer == null) + bgPlayer = AudioUtils() + val volume = SPUtils.instance().getInt(Const.User.VOLUME, 50) + bgPlayer?.setVolume(volume.toFloat() / 100) + bgPlayer?.loopPlayMusic(this, data?.audioFile) + } + (fragments[0] as HomeFragment).changeBg(data?.imageUrl ?: "", data?.backUrl ?: "") + } + } + + /** + * 开始冥想 + */ + private fun startThink() { + bgPlayer?.pause() + ThinkAudioService.index = 0 + if (ThinkAudioService.voice?.meditationMusicList?.isNullOrEmpty() == false){ + checkFloat() //检测浮窗 + // 启动音乐服务 + val serviceIntent = Intent(this, ThinkAudioService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(serviceIntent) + } else { + startService(serviceIntent) + } + ThinkAudioService.currentDuration = ThinkAudioService.voice?.meditationSecondList?.get(ThinkAudioService.index)?:0 + EventBus.getDefault().post(EmptyEvent(Const.EventCode.GOT_THINK_DURATION)) + ThinkAudioService.playing = true + cl_player.visible() + tv_player.text = ThinkAudioService.voice?.meditationTitle + iv_player.setImageURI(ThinkAudioService.voice?.coverUrl?.split(",")?.firstOrNull()) + player_play.setImageResource(R.mipmap.player_pause) + thinkHandler?.sendEmptyMessage(MSG_PROGRESS) + startTime = System.currentTimeMillis() //记录开始冥想的时间 + (fragments[0] as HomeFragment).refreshTodayPlayingState() //对比当前音频是否是每日疗愈 + } + } + + /** + * 停止冥想 + */ + private fun finishThink(){ + saveThinkRecord() + ThinkAudioService.voice = null + ThinkAudioService.index = 0 + ThinkAudioService.finishTime = 0L + // 停止服务 + stopService(Intent(this, ThinkAudioService::class.java)) + ThinkAudioService.playing = false + thinkHandler?.removeMessages(0) + cl_player.gone() + (fragments[0] as HomeFragment).refreshTodayPlayingState() //对比当前音频是否是每日疗愈 + if (XQApplication.isForeground){ + if (isBGMChanged) //BGM已经被切换,重新播放新BGM + startBgm() + else //BGM未改变,直接续播 + bgPlayer?.resume() + } + } + + /** + * 申请浮窗权限 增加稳定性 + */ + private fun checkFloat() { + if (!Settings.canDrawOverlays(this) && SPUtils.instance().getString("isRefusedFloat").isNullOrEmpty()) { //没有浮窗权限并且没有拒绝过 + TipDialog.show( + supportFragmentManager, + "为了增加后台播放的稳定性,我们需要开启悬浮窗口权限", + object : TipDialog.OnClickCallback { + override fun onOk() { + var intent = Intent( + Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + packageName) + ) + startActivityForResult(intent, 1234) + } + + override fun onCancel() { + } + }, + "去开启", + "取消" + ) + } + } + + + /** + * 保存冥想记录 + */ + private fun saveThinkRecord() { + if (ThinkAudioService.voice == null||startTime == 0L||SPUtils.instance().getString(Const.User.TOKEN).isNullOrEmpty()) + return + val time = ((System.currentTimeMillis() - startTime) / 1000).toInt() + startTime = System.currentTimeMillis() + HttpManager.saveViewingHistory(ThinkAudioService.voice?.id ?: "", time).request(this, false, { _, _ -> + Log.e(Const.Tag, "冥想记录成功:$time 秒") + }){ _, _-> + Log.e(Const.Tag, "冥想记录失败:$time 秒") } } @@ -55,7 +292,7 @@ } private fun initTab() { - val titles = arrayListOf("首页","课程","","疗愈馆","我的") + val titles = arrayListOf("疗愈", "课程", "", "疗愈馆", "我的") val iconChecked = arrayListOf( R.mipmap.home_selected, R.mipmap.play_selected, @@ -76,7 +313,7 @@ fragments.add(DiscoveryFragment()) fragments.add(MineFragment()) view_pager.offscreenPageLimit = fragments.size - view_pager.adapter = object : FragmentPagerAdapter(supportFragmentManager,0) { + view_pager.adapter = object : FragmentPagerAdapter(supportFragmentManager, 0) { override fun getItem(p0: Int): Fragment { return fragments[p0] } @@ -100,77 +337,215 @@ } override fun onTabSelect(position: Int) { - view_pager.currentItem = position - UltimateBar.with(this@MainActivity) - .statusDark(position != 0&&position!=1) - .create().immersionBar() //沉浸状态栏 + if (position == 4 ){ + if (SPUtils.instance().getString(Const.User.TOKEN).isNullOrEmpty()){ + toast("请先登录") + startActivity<LoginActivity>() + tab_bar.currentTab = 0 + return + }else + (fragments[4] as MineFragment).showUserInfo() + } + view_pager.currentItem = position + if (position == 2){ + (fragments[2] as TreeFragment).getTree() + if (cl_player.visibility == View.VISIBLE){ + cl_player.alpha = 0f + cl_player.gone() + } + }else{ + if (cl_player.alpha == 0f){ + cl_player.visible() + cl_player.alpha = 1f + } + } + if (position == 1){ + (fragments[1] as CourseFragment).refreshDataByResume() + } + if (position == 4){ + (fragments[4] as MineFragment).queryUnread() + } + if (position != 1) + EventBus.getDefault().post(EmptyEvent(Const.EventCode.PAUSE_TEACHER_VIDEO)) + if (position == 0){ + (fragments[0] as HomeFragment).refreshDataByResume() + startTodayCheck() + } + else + stopTodayCheck() } override fun onTabReselect(position: Int) { } @Subscribe - fun onSwitch(e:EmptyEvent){ - if (e.code == Const.EventCode.SWITCH_HOME){ + fun onEvent(e: EmptyEvent){ + if (e.code == Const.EventCode.CHANGE_USER){ tab_bar.currentTab = 0 onTabSelect(0) - }else if(e.code == Const.EventCode.CHANGE_STARTCLASS){ + (fragments[0] as HomeFragment).refreshData() + checkAnswer() + }else if (e.code == Const.EventCode.SWITCH_HOME){ + tab_bar.currentTab = 0 + onTabSelect(0) + }else if (e.code == Const.EventCode.SWITCH_COURSE){ tab_bar.currentTab = 1 onTabSelect(1) - }else if(e.code == Const.EventCode.SWITCH_DISCOVERY){ - tab_bar.currentTab = 2 - onTabSelect(2) }else if(e.code == Const.EventCode.CHANGE_EXPLORE){ tab_bar.currentTab = 3 onTabSelect(3) + }else if(e.code == Const.EventCode.APP_FOREGROUND){ + EasyFloat.hide(EasyFloatTag) + if (ThinkAudioService.voice==null) + bgPlayer?.resume() + }else if(e.code == Const.EventCode.APP_BACKGROUND){ + bgPlayer?.pause() + if ( ThinkAudioService.playing && Settings.canDrawOverlays(this) ) { + showFloater() + EasyFloat.show(EasyFloatTag) + } + }else if(e.code == Const.EventCode.CHANGE_BGM){ + if (ThinkAudioService.voice == null) + startBgm() + else + isBGMChanged = true //正在播放疗愈,无法立即切换背景音乐 + }else if(e.code == Const.EventCode.START_THINK){ + startThink() + }else if(e.code == Const.EventCode.FINISH_THINK){ + finishThink() + }else if(e.code == Const.EventCode.PAUSE_OR_RESUME_THINK){ + player_play.callOnClick() + }else if(e.code == Const.EventCode.START_GUIDE_AUDIO){ + inGuide = true + startGuide() + bgPlayer?.pause() + EventBus.getDefault().post(EmptyEvent(Const.EventCode.SERVICE_AUDIO_PAUSE)) + }else if(e.code == Const.EventCode.FINISH_GUIDE_AUDIO){ + inGuide = false + guidePlayer?.stopPlayMusic(false) + if (ThinkAudioService.voice!=null&& ThinkAudioService.playing){ + EventBus.getDefault().post(EmptyEvent(Const.EventCode.SERVICE_AUDIO_RESUME)) + } + if (ThinkAudioService.voice == null) + bgPlayer?.resume() + }else if(e.code == Const.EventCode.REFRESH_PRIVATE){ //重新答题后,刷新私人定制 + (fragments[0] as HomeFragment).getPrivacy() + }else if(e.code == Const.EventCode.THINK_TIMER){ //开启倒计时 + thinkHandler?.sendEmptyMessage(MSG_COUNTDOWN) } } @Subscribe - fun refreshUser(e:EmptyEvent){ - if (e.code == Const.EventCode.USER_INFO_CHANGED) - getData() + fun onIntEvent(e: IntEvent){ + if (e.code == Const.EventCode.THINK_SEEK_PROGRESS){ + EventBus.getDefault().post(IntEvent(Const.EventCode.SERVICE_AUDIO_SEEK,e.i)) + player_play.callOnClick() + } } - private fun getData() { - HttpManager.getUserInfo().request(this){_,data-> - homeData = data - homeData?.apply { - SPUtils.instance().put(Const.User.USER_ID,id).put(Const.User.USER_PHONE,phone).apply() - //判断数据是否完善 - val isHint = SPUtils.instance().getBoolean("isHint") //true 已经提示过 - if (!isHint && (weight.isNullOrEmpty() || birthday.isNullOrEmpty() || height.isNullOrEmpty() || height.toInt() == 0 || waistline.isNullOrEmpty()|| waistline.toInt() == 0)) { - SPUtils.instance().put("isHint",true).apply() - TipDialog.show( - supportFragmentManager, - "完善身体数据后获得更好推荐", - object : TipDialog.OnClickCallback { - override fun onOk() { - } - - override fun onCancel() { - } - }, - "现在就去", - "以后再去" - ) - } + @SuppressLint("HardwareIds") + private fun checkAnswer() { + val answer = SPUtils.instance().getString(Const.User.ANSWER) + if (!answer.isNullOrEmpty()){ //已登录并且有答案 + val reqAnswer = Gson().fromJson(answer, ReqAnswer::class.java) + reqAnswer?.device = Settings.Secure.getString( + contentResolver, + Settings.Secure.ANDROID_ID + ) + HttpManager.saveUserAnswers(reqAnswer).request(this, false, success = { _, _ -> + SPUtils.instance().put(Const.User.ANSWER, "").apply() + Log.e(Const.Tag, "私人定制已保存") + (fragments[0] as HomeFragment).getPrivacy() + }){ _, _-> } - EventBus.getDefault().post(EmptyEvent(Const.EventCode.REFRESH_USER_INFO)) } + } + + private fun showFloater() { + if (floater == null){ + floater = EasyFloat.with(applicationContext) + .setLayout(R.layout.layout_floter, OnInvokeView { + }) + .setShowPattern(ShowPattern.ALL_TIME) + .setSidePattern(SidePattern.RESULT_LEFT) + .setGravity(Gravity.START or Gravity.BOTTOM, 0, 0) + .setDragEnable(true) + .setTag(EasyFloatTag) + .setMatchParent(widthMatch = false, heightMatch = false) + .registerCallback { + touchEvent { view, motionEvent -> + motionEvent.action + } + } + floater?.show() + } + } + + private fun startTodayCheck(){ + thinkHandler?.sendEmptyMessage(MSG_TODAY) + } + + private fun stopTodayCheck(){ + thinkHandler?.removeMessages(MSG_TODAY) } override fun onResume() { super.onResume() - if (tab_bar.currentTab == 2) - (fragments[2] as DiscoveryFragment).getUnread() + if (view_pager.currentItem == 4){ + (fragments[4] as MineFragment).queryUnread() + (fragments[4] as MineFragment).showUserInfo() + } else if (view_pager.currentItem == 0){ + startTodayCheck() + (fragments[0] as HomeFragment).refreshDataByResume() + } else if (view_pager.currentItem == 2){ + (fragments[2] as TreeFragment).getTree() + } else if (view_pager.currentItem == 1){ + (fragments[1] as CourseFragment).refreshDataByResume() + } + if (isFirst&&!hasTreeFirstShow&&!SPUtils.instance().getString(Const.User.ANSWER).isNullOrEmpty()){ //如果是第一次安装并且还没显示树苗打卡引导并且答完题了 就去树苗引导 + tab_bar.currentTab = 2 + onTabSelect(2) + (fragments[2] as TreeFragment).showFirst() + hasTreeFirstShow = true + } + if (XQApplication.finishAnswer){ + XQApplication.finishAnswer = false + tab_bar.currentTab = 2 + onTabSelect(2) + } } - + override fun onPause() { + super.onPause() + stopTodayCheck() + } override fun onDestroy() { super.onDestroy() + bgPlayer?.stopPlayMusic(false) EventBus.getDefault().unregister(this) } + + override fun onUpdate(db: Double, time: Long) { + } + + override fun onStop(filePath: String?) { + } + + override fun onStartPlay() { + } + + override fun onFinishPlay() { + + } + + override fun onGetDuration(duration: Int) { + + } + + override fun onBackPressed() { + if (teacherVideoView?.onBackPressed() != true) + super.onBackPressed() + } } \ No newline at end of file -- Gitblit v1.7.1