app/src/main/java/com/sinata/xqmuse/MainActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/sinata/xqmuse/ThinkAudioService.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/sinata/xqmuse/network/Apis.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/sinata/xqmuse/ui/home/VoiceDetailActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/sinata/xqmuse/ui/home/adapter/CardBannerAdapter.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/activity_guide.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/fragment_home.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/item_banner.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/item_banner_card.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
app/src/main/java/com/sinata/xqmuse/MainActivity.kt
@@ -8,6 +8,7 @@ import android.provider.Settings import android.util.Log import android.view.View import android.view.WindowManager import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentPagerAdapter import cn.sinata.xldutils.gone @@ -57,7 +58,7 @@ private var thinkHandler:Handler? = null //冥想时间相关 private var inGuide = false //true 引导中... private val isFirst by lazy { intent.getBooleanExtra("isFirst",false) } //首次安装,需要到导师引导页 private val isFirst by lazy { intent.getBooleanExtra("isFirst", false) } //首次安装,需要到导师引导页 private val MSG_PROGRESS = 0//疗愈进度+1 private val MSG_TODAY = 1//今日疗愈更新计时 @@ -72,14 +73,14 @@ override fun initClick() { player_close.setOnClickListener { TipDialog.show(supportFragmentManager,"是否关闭当前音频?",object :TipDialog.OnClickCallback{ TipDialog.show(supportFragmentManager, "是否关闭当前音频?", object : TipDialog.OnClickCallback { override fun onOk() { EventBus.getDefault().post(EmptyEvent(Const.EventCode.FINISH_THINK)) } override fun onCancel() { } },"确认","取消") }, "确认", "取消") } cl_player.setOnClickListener { @@ -121,24 +122,24 @@ override fun handleMessage(msg: Message) { super.handleMessage(msg) when(msg.what){ MSG_PROGRESS->{ currentPosition = thinkBgPlayer?.currentPosition ?:0 MSG_PROGRESS -> { currentPosition = thinkBgPlayer?.currentPosition ?: 0 EventBus.getDefault().post(EmptyEvent(Const.EventCode.GOT_THINK_POSITION)) sendEmptyMessageDelayed(MSG_PROGRESS,1000) sendEmptyMessageDelayed(MSG_PROGRESS, 1000) } MSG_COUNTDOWN->{ if (System.currentTimeMillis()>= finishTime) MSG_COUNTDOWN -> { if (System.currentTimeMillis() >= finishTime) EventBus.getDefault().post(EmptyEvent(Const.EventCode.FINISH_THINK)) else sendEmptyMessageDelayed(MSG_COUNTDOWN,1000) sendEmptyMessageDelayed(MSG_COUNTDOWN, 1000) } MSG_TODAY->{ MSG_TODAY -> { if (System.currentTimeMillis() - lastTodayTime > 60000) { //距离上次刷新过去了1分钟 Log.e(Const.Tag,"已经过1分钟,需要重新获取今日疗愈数据") Log.e(Const.Tag, "已经过1分钟,需要重新获取今日疗愈数据") lastTodayTime = System.currentTimeMillis() (fragments[0] as HomeFragment).getToday() } sendEmptyMessageDelayed(MSG_TODAY,5000) sendEmptyMessageDelayed(MSG_TODAY, 5000) } } } @@ -151,29 +152,29 @@ if (guidePlayer == null) guidePlayer = AudioUtils() if (guideAudio.isNullOrEmpty()) HttpManager.getPlan().request(this){_,data-> HttpManager.getPlan().request(this){ _, data-> guideAudio = data if (inGuide){ guidePlayer?.setVolume(0.6f) guidePlayer?.loopPlayMusic(this,data) guidePlayer?.loopPlayMusic(this, data) } } else{ guidePlayer?.setVolume(0.6f) guidePlayer?.loopPlayMusic(this,guideAudio) guidePlayer?.loopPlayMusic(this, guideAudio) } } private fun startBgm() { HttpManager.getHomeBackgroundMusicByUserId().request(this){_,data-> 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) 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?:"") (fragments[0] as HomeFragment).changeBg(data?.imageUrl ?: "", data?.backUrl ?: "") } } @@ -188,8 +189,8 @@ thinkBgPlayer = AudioUtils() thinkBgPlayer!!.setOnAudioStatusUpdateListener(this) } val volume = SPUtils.instance().getInt(Const.User.VOLUME_THINK,50) thinkBgPlayer?.setVolume(volume.toFloat()/100) val volume = SPUtils.instance().getInt(Const.User.VOLUME_THINK, 50) thinkBgPlayer?.setVolume(volume.toFloat() / 100) thinkBgPlayer?.startPlayMusic(this, voice?.meditationMusicList?.get(index)) currentDuration = voice?.meditationSecondList?.get(index)?:0 EventBus.getDefault().post(EmptyEvent(Const.EventCode.GOT_THINK_DURATION)) @@ -233,10 +234,10 @@ return val time = ((System.currentTimeMillis() - startTime) / 1000).toInt() startTime = 0L HttpManager.saveViewingHistory(voice?.id?:"", time).request(this,false,{ _, _-> Log.e(Const.Tag,"冥想记录成功:$time 秒") }){_,_-> Log.e(Const.Tag,"冥想记录失败:$time 秒") HttpManager.saveViewingHistory(voice?.id ?: "", time).request(this, false, { _, _ -> Log.e(Const.Tag, "冥想记录成功:$time 秒") }){ _, _-> Log.e(Const.Tag, "冥想记录失败:$time 秒") } } @@ -248,7 +249,7 @@ } private fun initTab() { val titles = arrayListOf("疗愈","课程","","疗愈馆","我的") val titles = arrayListOf("疗愈", "课程", "", "疗愈馆", "我的") val iconChecked = arrayListOf( R.mipmap.home_selected, R.mipmap.play_selected, @@ -269,7 +270,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] } @@ -327,7 +328,7 @@ } @Subscribe fun onEvent(e:EmptyEvent){ fun onEvent(e: EmptyEvent){ if (e.code == Const.EventCode.CHANGE_USER){ tab_bar.currentTab = 0 onTabSelect(0) @@ -359,8 +360,8 @@ }else if(e.code == Const.EventCode.PAUSE_OR_RESUME_THINK){ player_play.callOnClick() }else if(e.code == Const.EventCode.CHANGE_THINK_VOLUME){ val v = SPUtils.instance().getInt(Const.User.VOLUME_THINK,50) thinkBgPlayer?.setVolume(v.toFloat()/100) val v = SPUtils.instance().getInt(Const.User.VOLUME_THINK, 50) thinkBgPlayer?.setVolume(v.toFloat() / 100) }else if(e.code == Const.EventCode.START_GUIDE_AUDIO){ inGuide = true startGuide() @@ -382,7 +383,7 @@ } @Subscribe fun onIntEvent(e:IntEvent){ fun onIntEvent(e: IntEvent){ if (e.code == Const.EventCode.THINK_SEEK_PROGRESS){ thinkBgPlayer?.seekTo(e.i) player_play.callOnClick() @@ -394,12 +395,15 @@ 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,"私人定制已保存") 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() }){_,_-> }){ _, _-> } } } app/src/main/java/com/sinata/xqmuse/ThinkAudioService.kt
New file @@ -0,0 +1,89 @@ package com.sinata.xqmuse import android.app.NotificationChannel import android.app.NotificationManager import android.app.Service import android.content.Intent import android.media.AudioManager import android.media.MediaPlayer import android.os.Build import android.os.IBinder import android.os.PowerManager import androidx.core.app.NotificationCompat class ThinkAudioService:Service() { private var mediaPlayer: MediaPlayer? = null private var wakeLock: PowerManager.WakeLock? = null override fun onCreate() { super.onCreate() // 初始化 MediaPlayer // mediaPlayer = MediaPlayer.create(this, R.raw.audio_sample) mediaPlayer!!.isLooping = true // 初始化 WakeLock val powerManager = getSystemService(POWER_SERVICE) as PowerManager wakeLock = powerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "AudioService::WakeLock" ) } private val focusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { mediaPlayer!!.pause() // 焦点丢失时暂停播放 } } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "audio_channel", "音频播放", NotificationManager.IMPORTANCE_LOW ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } } override fun onBind(intent: Intent?): IBinder? { return null } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 创建通知渠道(Android 8.0+ 必须) createNotificationChannel() // 启动前台服务 val notification = NotificationCompat.Builder(this, "audio_channel") .setContentTitle("音频播放中") .setSmallIcon(R.mipmap.ic_launcher) .build() startForeground(1, notification) // 请求音频焦点 val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager val result = audioManager.requestAudioFocus( focusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { mediaPlayer?.start() wakeLock?.acquire(30 * 60 * 1000L) // 申请 WakeLock } return START_STICKY } override fun onDestroy() { if (mediaPlayer != null) { mediaPlayer!!.release() mediaPlayer = null } if (wakeLock != null && wakeLock!!.isHeld) { wakeLock!!.release() } super.onDestroy() } } app/src/main/java/com/sinata/xqmuse/network/Apis.kt
@@ -5,7 +5,7 @@ // private const val TEST_URL = "http://192.168.110.64:9000/" //内网 private const val TEST_URL = "https://xq.xqzhihui.com/api/" //外网 private const val LINE_URL = "https://jkcyl.cn/app/" //正式服 private const val LINE_URL = "" //正式服 val BASE_URL = if (isTest) TEST_URL else LINE_URL /**公共接口*/ app/src/main/java/com/sinata/xqmuse/ui/home/VoiceDetailActivity.kt
@@ -150,6 +150,7 @@ } } EventBus.getDefault().register(this) iv_play.keepScreenOn = true } private fun startTimer(){ app/src/main/java/com/sinata/xqmuse/ui/home/adapter/CardBannerAdapter.kt
@@ -34,7 +34,7 @@ val bannerViewHolder = holder as BannerViewHolder bannerViewHolder.iv_bg.setImageURI(data?.coverUrl?.split(",")?.get(1)) bannerViewHolder.tv_title.text = data?.meditationTitle bannerViewHolder.tv_subtitle.text = data?.coverDescription?.ellipsize(6) bannerViewHolder.tv_subtitle.text = data?.coverDescription?.ellipsize(4) bannerViewHolder.tv_count.text = ((data?.realLearnedNum?:0)+(data?.virtualLearnedNum?:0)).toString() when(data?.chargeType){ //1=免费 2=会员免费 3=单独收费 2->{ app/src/main/res/layout/activity_guide.xml
@@ -8,7 +8,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:screenScaleType="type_center_crop" app:playerBackgroundColor="@color/colorPrimary" app:playerBackgroundColor="@color/white" android:id="@+id/player"/> <TextView app/src/main/res/layout/fragment_home.xml
@@ -126,7 +126,7 @@ android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="@id/iv_today" android:paddingVertical="8dp" android:textSize="11sp" android:textSize="14sp" android:textColor="@color/white" android:gravity="end" android:id="@+id/tv_today_count" @@ -141,7 +141,7 @@ app:layout_constraintBaseline_toBaselineOf="@id/tv_today_count" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="18dp" android:textSize="11sp" android:textSize="14sp" android:textColor="@color/white" /> app/src/main/res/layout/item_banner.xml
@@ -45,6 +45,6 @@ android:layout_marginBottom="16dp" app:layout_constraintStart_toStartOf="@id/tv_name" android:textColor="@color/white" android:textSize="10sp" android:textSize="14sp" android:textStyle="bold"/> </androidx.constraintlayout.widget.ConstraintLayout> app/src/main/res/layout/item_banner_card.xml
@@ -34,7 +34,7 @@ android:text="缓解压力" android:singleLine="true" android:ellipsize="end" android:textSize="14sp" android:textSize="16sp" android:textColor="@color/white" android:id="@+id/tv_title"/> <TextView @@ -46,7 +46,7 @@ app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="11dp" android:text="缓解压力" android:textSize="9sp" android:textSize="11sp" android:textColor="@color/white" android:id="@+id/tv_subtitle"/> <ImageView @@ -63,7 +63,7 @@ android:layout_height="wrap_content" android:id="@+id/tv_count" android:textColor="@color/white" android:textSize="9sp" android:textSize="11sp" app:layout_constraintStart_toEndOf="@id/iv" app:layout_constraintBaseline_toBaselineOf="@id/tv_subtitle" android:layout_marginStart="2dp"