Commit 38471d10 by 范玉宾

meditation player done

parent 8f44ca58
......@@ -58,14 +58,10 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
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
// cannot access 'androidx.lifecycle.hasdefaultviewmodelproviderfactory'
// 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"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
......
......@@ -2,20 +2,24 @@ package com.yidianling.muse.activity
import android.media.MediaPlayer
import android.os.Bundle
import android.widget.SeekBar
import com.alibaba.android.arouter.facade.annotation.Route
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.bean.StatusBarOptions
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.setTransparentForImageView
import com.ydl.ydlcommon.utils.StatusBarUtils.Companion.statusBarLightMode
import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.yidianling.muse.R
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import com.yidianling.muse.widget.QuitMeditationDialog
import com.yidianling.muse.widget.ShareMeditationDialog
import kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.exo_player_control_view.*
import java.util.*
@Route(path = "/muse/play")
......@@ -33,6 +37,13 @@ class PlayMeditationActivity : BaseActivity() {
private var shareDialog: ShareMeditationDialog? = 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?) {
setTransparentForImageView(this, null)
statusBarLightMode(this)
......@@ -55,6 +66,20 @@ class PlayMeditationActivity : BaseActivity() {
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)
.load(bgUrl)
.into(iv_bg)
......@@ -113,11 +138,25 @@ class PlayMeditationActivity : BaseActivity() {
if (isPlaying) {
MediaPlayerManager.getInstance(this).pause()
} else {
val duration = mMediaPlayer?.duration
if (MediaPlayerManager.getInstance(this).path.isNullOrBlank()) {
MediaPlayerManager.getInstance(this).path = path
} else {
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
if (isPlaying) {
......@@ -129,45 +168,111 @@ class PlayMeditationActivity : BaseActivity() {
}
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 {
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 {
if (mMediaPlayer!=null){
val currentPosition = mMediaPlayer!!.currentPosition
val seekPosition = 0.coerceAtLeast(currentPosition - 15000)
mMediaPlayer!!.seekTo(seekPosition)
}
}
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)
.setOnPreparedListener(object : MediaPlayerManager.OnMediaPlayerManagerListener {
override fun onProgress(mediaPlayer: MediaPlayer?) {
override fun onStopTrackingTouch(seekBar: SeekBar?) {
isSeekbarChanging = false
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() {
val exoPlayer = ExoPlayerFactory.newSimpleInstance(this)
exoPlayer.playWhenReady = false
override fun onDestroy() {
super.onDestroy()
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 {
return instance;
}
public void setPath(String path) throws IOException {
public MediaPlayer getMediaPlayer(){
return mMediaPlayer;
}
public void setPath(String path) {
mPath = path;
if (mMediaPlayer.isPlaying()){
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.prepare();
mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getPath(){
......@@ -69,7 +89,11 @@ public class MediaPlayerManager {
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 @@
android:id="@+id/iv_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:src="@drawable/default_cover"
android:scaleType="centerCrop"/>
<androidx.constraintlayout.widget.ConstraintLayout
......@@ -126,7 +125,7 @@
android:layout_marginEnd="50dp"
android:layout_marginBottom="48dp"
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" />
<ImageView
......@@ -136,7 +135,7 @@
android:layout_marginStart="50dp"
android:layout_marginBottom="48dp"
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" />
<TextView
......
......@@ -55,14 +55,12 @@
app:layout_constraintStart_toEndOf="@id/exo_next"
app:layout_constraintTop_toTopOf="@id/exo_play" />
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@+id/exo_progress"
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/seekbar_play_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="64dp"
android:layout_marginBottom="50dp"
app:played_color="#000000"
app:unplayed_color="#FFFFFFFF"
app:layout_constraintBottom_toTopOf="@id/exo_play"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
......@@ -74,9 +72,9 @@
android:layout_marginEnd="12dp"
android:textColor="#B3FFFFFF"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/exo_progress"
app:layout_constraintEnd_toStartOf="@id/exo_progress"
app:layout_constraintTop_toTopOf="@id/exo_progress"
app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintEnd_toStartOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="03:46" />
<TextView
......@@ -86,8 +84,8 @@
android:layout_marginEnd="12dp"
android:textColor="#B3FFFFFF"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/exo_progress"
app:layout_constraintStart_toEndOf="@id/exo_progress"
app:layout_constraintTop_toTopOf="@id/exo_progress"
app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="13:46" />
</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