Commit 38471d10 by 范玉宾

meditation player done

parent 8f44ca58
...@@ -58,14 +58,10 @@ dependencies { ...@@ -58,14 +58,10 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.9.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.0'
// solve build problem // solve build problem
// cannot access 'androidx.lifecycle.hasdefaultviewmodelproviderfactory' // cannot access 'androidx.lifecycle.hasdefaultviewmodelproviderfactory'
// Comment out when compiling // Comment out when compiling
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" // implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "com.alibaba:arouter-api:$arouter_api" implementation "com.alibaba:arouter-api:$arouter_api"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同 // 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
......
...@@ -2,20 +2,24 @@ package com.yidianling.muse.activity ...@@ -2,20 +2,24 @@ package com.yidianling.muse.activity
import android.media.MediaPlayer import android.media.MediaPlayer
import android.os.Bundle import android.os.Bundle
import android.widget.SeekBar
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.exoplayer2.ExoPlayerFactory import com.ydl.media.view.PlayerFloatHelper
import com.ydl.ydlcommon.base.BaseActivity import com.ydl.ydlcommon.base.BaseActivity
import com.ydl.ydlcommon.bean.StatusBarOptions import com.ydl.ydlcommon.bean.StatusBarOptions
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.setTransparentForImageView import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.setTransparentForImageView
import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.statusBarLightMode import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.statusBarLightMode
import com.ydl.ydlcommon.utils.remind.ToastHelper import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.yidianling.muse.R import com.yidianling.muse.R
import com.yidianling.muse.helper.MediaPlayerManager import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import com.yidianling.muse.widget.QuitMeditationDialog import com.yidianling.muse.widget.QuitMeditationDialog
import com.yidianling.muse.widget.ShareMeditationDialog import com.yidianling.muse.widget.ShareMeditationDialog
import kotlinx.android.synthetic.main.activity_play_meditation.* import kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.exo_player_control_view.* import kotlinx.android.synthetic.main.exo_player_control_view.*
import java.util.*
@Route(path = "/muse/play") @Route(path = "/muse/play")
...@@ -33,6 +37,13 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -33,6 +37,13 @@ class PlayMeditationActivity : BaseActivity() {
private var shareDialog: ShareMeditationDialog? = null private var shareDialog: ShareMeditationDialog? = null
private var quitDialog: QuitMeditationDialog? = null private var quitDialog: QuitMeditationDialog? = null
private var mTimer = Timer()
private var mMediaPlayer:MediaPlayer?=null
private var duration = 0
private var isSeekbarChanging = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setTransparentForImageView(this, null) setTransparentForImageView(this, null)
statusBarLightMode(this) statusBarLightMode(this)
...@@ -55,6 +66,20 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -55,6 +66,20 @@ class PlayMeditationActivity : BaseActivity() {
private fun initView() { private fun initView() {
mMediaPlayer = MediaPlayerManager.getInstance(this).mediaPlayer
MediaPlayerManager.getInstance(this).path = path
val currentPosition = mMediaPlayer?.currentPosition
duration = mMediaPlayer?.duration?:0
if (currentPosition!=null){
exo_position.text = MediaPlayerTimeUtil.calculateTime(currentPosition/1000)
}
if (duration!=null){
exo_duration.text = MediaPlayerTimeUtil.calculateTime(duration/1000)
}
Glide.with(this) Glide.with(this)
.load(bgUrl) .load(bgUrl)
.into(iv_bg) .into(iv_bg)
...@@ -113,11 +138,25 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -113,11 +138,25 @@ class PlayMeditationActivity : BaseActivity() {
if (isPlaying) { if (isPlaying) {
MediaPlayerManager.getInstance(this).pause() MediaPlayerManager.getInstance(this).pause()
} else { } else {
val duration = mMediaPlayer?.duration
if (MediaPlayerManager.getInstance(this).path.isNullOrBlank()) { if (MediaPlayerManager.getInstance(this).path.isNullOrBlank()) {
MediaPlayerManager.getInstance(this).path = path MediaPlayerManager.getInstance(this).path = path
} else { } else {
MediaPlayerManager.getInstance(this).play() MediaPlayerManager.getInstance(this).play()
} }
if (duration != null) {
seekbar_play_progress.max = duration
}
mTimer.schedule(object :TimerTask(){
override fun run() {
if (!isSeekbarChanging){
seekbar_play_progress.progress = mMediaPlayer?.currentPosition?:0
}
}
},0,50)
} }
isPlaying = !isPlaying isPlaying = !isPlaying
if (isPlaying) { if (isPlaying) {
...@@ -129,45 +168,111 @@ class PlayMeditationActivity : BaseActivity() { ...@@ -129,45 +168,111 @@ class PlayMeditationActivity : BaseActivity() {
} }
exo_prev.setOnClickListener { exo_prev.setOnClickListener {
ToastHelper.show("上一首!") MediaPlayerManager.getInstance(this).setNewPath(path)
isPlaying = if (mMediaPlayer?.isPlaying == true) {
exo_play.setImageResource(R.drawable.icon_pause_play)
if (duration != null) {
seekbar_play_progress.max = duration
}
mTimer.schedule(object :TimerTask(){
override fun run() {
seekbar_play_progress.progress = mMediaPlayer?.currentPosition?:0
}
},0,50)
true
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
false
}
} }
exo_next.setOnClickListener { exo_next.setOnClickListener {
ToastHelper.show("下一首!") MediaPlayerManager.getInstance(this).setNewPath(path)
isPlaying = if (mMediaPlayer?.isPlaying == true) {
exo_play.setImageResource(R.drawable.icon_pause_play)
if (duration != null) {
seekbar_play_progress.max = duration
}
mTimer.schedule(object :TimerTask(){
override fun run() {
if (!isSeekbarChanging){
seekbar_play_progress.progress = mMediaPlayer?.currentPosition?:0
}
}
},0,50)
true
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
false
}
} }
exo_rew.setOnClickListener { exo_rew.setOnClickListener {
if (mMediaPlayer!=null){
val currentPosition = mMediaPlayer!!.currentPosition
val seekPosition = 0.coerceAtLeast(currentPosition - 15000)
mMediaPlayer!!.seekTo(seekPosition)
}
} }
exo_ffwd.setOnClickListener { exo_ffwd.setOnClickListener {
if (mMediaPlayer!=null){
val currentPosition = mMediaPlayer!!.currentPosition
val seekPosition = duration.coerceAtMost(currentPosition + 15000)
mMediaPlayer!!.seekTo(seekPosition)
}
}
seekbar_play_progress.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (mMediaPlayer!=null){
val totalDuration = mMediaPlayer!!.duration / 1000
val position = mMediaPlayer!!.currentPosition
exo_position.text = MediaPlayerTimeUtil.calculateTime(position/1000)
exo_duration.text = MediaPlayerTimeUtil.calculateTime(totalDuration)
} }
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
isSeekbarChanging = true
}
MediaPlayerManager.getInstance(this) override fun onStopTrackingTouch(seekBar: SeekBar?) {
.setOnPreparedListener(object : MediaPlayerManager.OnMediaPlayerManagerListener { isSeekbarChanging = false
override fun onProgress(mediaPlayer: MediaPlayer?) { seekBar?.progress?.let {
MediaPlayerManager.getInstance(this@PlayMeditationActivity).seekTo(
it
)
if (mMediaPlayer!=null){
exo_position.text = MediaPlayerTimeUtil.calculateTime(
mMediaPlayer!!.currentPosition/1000
)
}
} }
}) }
// MediaPlayerManager.getInstance(this).setOnPreparedListener {
// it.start()
// }
// MediaPlayerHelper.getInstance(this).setPath( })
// "https://storage.googleapis.com/exoplayer-test-media-0/play.mp3"
// )
initPlayer() mMediaPlayer?.setOnCompletionListener {
isPlaying = if (it.isPlaying) {
exo_play.setImageResource(R.drawable.icon_pause_play)
true
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
false
}
}
} }
private fun initPlayer() { override fun onDestroy() {
val exoPlayer = ExoPlayerFactory.newSimpleInstance(this) super.onDestroy()
exoPlayer.playWhenReady = false mTimer.cancel()
mMediaPlayer?.stop()
mMediaPlayer?.release()
} }
} }
\ No newline at end of file
package com.yidianling.muse.helper
import android.content.Context
import android.media.MediaPlayer
import android.net.Uri
import kotlin.properties.Delegates
class MediaPlayerHelper private constructor(private var mContext: Context) {
private var listener: OnMediaPlayerHelperListener by Delegates.notNull()
companion object {
private var mContext: Context by Delegates.notNull()
private var mMediaPlayer: MediaPlayer by Delegates.notNull()
private var mPath: String by Delegates.notNull()
@Volatile
private var instance: MediaPlayerHelper? = null
fun getInstance(context: Context): MediaPlayerHelper {
return when {
instance != null -> instance!!
else -> synchronized(this) {
if (instance == null) {
mContext = context
mMediaPlayer = MediaPlayer()
instance = MediaPlayerHelper(context)
}
instance!!
}
}
}
}
fun setPath(path: String) {
mPath = path
if (mMediaPlayer.isPlaying) {
mMediaPlayer.reset()
}
mMediaPlayer.setDataSource(Companion.mContext, Uri.parse(path))
mMediaPlayer.prepareAsync()
mMediaPlayer.setOnPreparedListener {
listener?.onPrepared(it)
}
}
fun getPath(): String {
return mPath
}
fun play() {
if (mMediaPlayer.isPlaying) return
mMediaPlayer.start()
}
fun pause() {
if (mMediaPlayer.isPlaying) {
mMediaPlayer.pause()
}
}
fun setOnPreparedListener(listener: OnMediaPlayerHelperListener) {
this.listener = listener
}
interface OnMediaPlayerHelperListener{
fun onPrepared(mediaPlayer: MediaPlayer)
}
}
\ No newline at end of file
...@@ -33,14 +33,34 @@ public class MediaPlayerManager { ...@@ -33,14 +33,34 @@ public class MediaPlayerManager {
return instance; return instance;
} }
public void setPath(String path) throws IOException { public MediaPlayer getMediaPlayer(){
return mMediaPlayer;
}
public void setPath(String path) {
mPath = path; mPath = path;
if (mMediaPlayer.isPlaying()){ if (mMediaPlayer.isPlaying()){
mMediaPlayer.reset(); mMediaPlayer.reset();
} }
try {
mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
// mMediaPlayer.start();
}
public void setNewPath(String path){
mPath = path;
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path); mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare(); mMediaPlayer.prepare();
mMediaPlayer.start(); mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
} }
public String getPath(){ public String getPath(){
...@@ -69,7 +89,11 @@ public class MediaPlayerManager { ...@@ -69,7 +89,11 @@ public class MediaPlayerManager {
default void onProgress(MediaPlayer mediaPlayer){}; default void onProgress(MediaPlayer mediaPlayer){};
} }
public void stop(){
if (mMediaPlayer.isPlaying()){
mMediaPlayer.reset();
}
}
} }
package com.yidianling.muse.utils
class MediaPlayerTimeUtil {
companion object{
fun calculateTime(time:Int):String?{
var minute = 0
var second = 0
if (time>60){
minute = time / 60
second = time % 60
return if (minute in 0..9){
if (second in 0..9){
"0$minute:0$second"
}else{
"0$minute:$second"
}
}else{
if (second in 0..9){
"$minute:0$second"
}else{
"$minute:$second"
}
}
}else if (time<60){
second = time
return if (second in 0..9){
"00:0$second"
}else{
"00:$second"
}
}
return null
}
}
}
\ No newline at end of file
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
android:id="@+id/iv_bg" android:id="@+id/iv_bg"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:src="@drawable/default_cover"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"/>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
...@@ -126,7 +125,7 @@ ...@@ -126,7 +125,7 @@
android:layout_marginEnd="50dp" android:layout_marginEnd="50dp"
android:layout_marginBottom="48dp" android:layout_marginBottom="48dp"
android:src="@drawable/icon_play_meditation_collect" android:src="@drawable/icon_play_meditation_collect"
app:layout_constraintBottom_toTopOf="@id/exo_progress" app:layout_constraintBottom_toTopOf="@id/seekbar_play_progress"
app:layout_constraintEnd_toStartOf="@id/guide_line" /> app:layout_constraintEnd_toStartOf="@id/guide_line" />
<ImageView <ImageView
...@@ -136,7 +135,7 @@ ...@@ -136,7 +135,7 @@
android:layout_marginStart="50dp" android:layout_marginStart="50dp"
android:layout_marginBottom="48dp" android:layout_marginBottom="48dp"
android:src="@drawable/icon_play_meditation_time_off" android:src="@drawable/icon_play_meditation_time_off"
app:layout_constraintBottom_toTopOf="@id/exo_progress" app:layout_constraintBottom_toTopOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/guide_line" /> app:layout_constraintStart_toEndOf="@id/guide_line" />
<TextView <TextView
......
...@@ -55,14 +55,12 @@ ...@@ -55,14 +55,12 @@
app:layout_constraintStart_toEndOf="@id/exo_next" app:layout_constraintStart_toEndOf="@id/exo_next"
app:layout_constraintTop_toTopOf="@id/exo_play" /> app:layout_constraintTop_toTopOf="@id/exo_play" />
<com.google.android.exoplayer2.ui.DefaultTimeBar <androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/exo_progress" android:id="@+id/seekbar_play_progress"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="64dp" android:layout_marginHorizontal="64dp"
android:layout_marginBottom="50dp" android:layout_marginBottom="50dp"
app:played_color="#000000"
app:unplayed_color="#FFFFFFFF"
app:layout_constraintBottom_toTopOf="@id/exo_play" app:layout_constraintBottom_toTopOf="@id/exo_play"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
...@@ -74,9 +72,9 @@ ...@@ -74,9 +72,9 @@
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:textColor="#B3FFFFFF" android:textColor="#B3FFFFFF"
android:textSize="12sp" android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/exo_progress" app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintEnd_toStartOf="@id/exo_progress" app:layout_constraintEnd_toStartOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/exo_progress" app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="03:46" /> tools:text="03:46" />
<TextView <TextView
...@@ -86,8 +84,8 @@ ...@@ -86,8 +84,8 @@
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:textColor="#B3FFFFFF" android:textColor="#B3FFFFFF"
android:textSize="12sp" android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/exo_progress" app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/exo_progress" app:layout_constraintStart_toEndOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/exo_progress" app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="13:46" /> tools:text="13:46" />
</merge> </merge>
\ 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