From f3b61d972b35a7ead1a07b71cab20058cf8a2618 Mon Sep 17 00:00:00 2001 From: kshivang Date: Tue, 8 Oct 2019 23:45:38 +0530 Subject: [PATCH] autoplay observable api added, documentation updated --- README.md | 30 ++++++---- .../rever/goonjexample/AudioPlayerActivity.kt | 25 ++++---- goonj/src/main/java/ai/rever/goonj/Goonj.kt | 60 +++++++++++-------- .../ai/rever/goonj/interfaces/AudioPlayer.kt | 2 +- .../ai/rever/goonj/interfaces/GoonjPlayer.kt | 6 +- .../rever/goonj/manager/GoonjPlayerManager.kt | 9 +-- .../ai/rever/goonj/player/LocalAudioPlayer.kt | 16 ++--- .../rever/goonj/player/RemoteAudioPlayer.kt | 14 +---- 8 files changed, 78 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index a28bdaa..bb46654 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,6 @@ Add the dependency ``` dependencies { implementation 'com.github.rever-ai:goonj:v0.3' - implementation 'com.google.android.exoplayer:exoplayer-core:2.10.3' - implementation 'com.google.android.exoplayer:exoplayer-ui:2.10.3' - implementation 'com.google.android.exoplayer:extension-mediasession:2.10.0' } ``` @@ -55,18 +52,25 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer | -------| ----------- | |__startNewSession()__|Starts a new Audio Session. Clears existing playlist.| |__addTrack(track : Track, index: Int? = null)__| Add an audio to playlist.| -|__resume()__ | Resume the player| -|__pause()__| Pauses the player| +|__resume()__| Resume the player.| +|__pause()__| Pauses the player.| |__seekTo(positionMs: Long)__|Seek by a certain length. +ve values seek forward, -ve seek backward.| -|__setAutoplay(autoplay : Boolean)__ | Lets you enable Autoplay with auto-fetch tracks. | -|__session(context: Context) : List__|Returns current playlist| -|__removeTrack(index : Int)__|Removes track from current Index in the playlist| -|__moveTrack(currentIndex : Int, finalIndex : Int)__|Moves a prticular track from one place in the playlist to another.| +|__removeTrack(index : Int)__|Removes track from current Index in the playlist.| +|__moveTrack(currentIndex : Int, finalIndex : Int)__|Moves a particular track from one place in the playlist to another.| |__skipToNext()__|Skip to next track.| -|__skipToPrevious()__|Skip to previous track| +|__skipToPrevious()__|Skip to previous track.| +|__finishTrack()__|Manual finish track.| +|__customiseNotification(useNavigationAction: Boolean, usePlayPauseAction: Boolean, fastForwardIncrementMs: Long, rewindIncrementMs: Long, smallIcon: Int)__|Customise notification which appear while playing.| +|__removeNotification()__|Remove notification.| +|__trackList__|Get current playlist| +|__playerState__|Get player state (GoonjPlayerState)| +|__currentTrack__|Get current track (Track)| +|__trackPosition__|Get current track position (Long)| +|__autoplay__|Enable autoplay with auto-fetch tracks, could be used get current state of autoplay.| |__playerStateObservable__|Observable of (GoonjPlayerState) that tells if the Player state. Helps in updating Play/Pause Icon/Button in UI.| -|__currentPlayingTrack__|Returns a Observable of (Track) that contains details of the Current Track that is playing.| +|__currentTrackObservable__|Observable of (Track) that contains details of the Current Track that is playing.| +|__autoplayObservable__|Observable of (Track) that contains details of the Current Track that is playing.| + ### Cast -To support __ChromeCast__, add ``` CastButtonFactory.setUpMediaRouteButton(this, yourMediaRouterButtonInXML) ``` to your Activity/Fragment and add ```yourMediaRouterButtonInXML``` in your XML Layout. -** Note **: Cast doesn't supports Autoplay. +Feature under development diff --git a/app/src/main/java/ai/rever/goonjexample/AudioPlayerActivity.kt b/app/src/main/java/ai/rever/goonjexample/AudioPlayerActivity.kt index 08a883c..be8b40e 100644 --- a/app/src/main/java/ai/rever/goonjexample/AudioPlayerActivity.kt +++ b/app/src/main/java/ai/rever/goonjexample/AudioPlayerActivity.kt @@ -28,7 +28,7 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer { setContentView(R.layout.activity_audio_player) - setupUI() + setListener() customizeNotification() setupPlayer() @@ -41,11 +41,11 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer { override fun onResume() { super.onResume() - playerStateObservable?.subscribe { + playerStateObservable.subscribe { audioPlayerPlayPauseToggleBtn.isChecked = it != GoonjPlayerState.PLAYING }?.addTo(compositeDisposable) - currentTrackObservable?.subscribe(::onPlayingTrackChange) + currentTrackObservable.subscribe(::onPlayingTrackChange) ?.addTo(compositeDisposable) } @@ -78,14 +78,14 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer { knownTrack = currentItem } - private fun setupUI() { + private fun setListener() { audioPlayerPlayPauseToggleBtn?.apply { setOnClickListener { if (isChecked) { pause() } else { - play() + resume() } } } @@ -121,7 +121,7 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer { addTrack(SAMPLES[1]) addTrack(SAMPLES[2]) addTrack(SAMPLES[3]) - play() + resume() } override fun onBackPressed() { @@ -130,30 +130,29 @@ class AudioPlayerActivity : AppCompatActivity(), GoonjPlayer { pause() } - override fun dispatchKeyEvent(event: KeyEvent): Boolean { + override fun dispatchKeyEvent(event: KeyEvent?): Boolean { val audioManager = applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager - when (val keyCode = event.keyCode) { + return when (event?.keyCode) { KEYCODE_VOLUME_UP -> { audioManager.adjustStreamVolume( AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI ) - return true + true } KEYCODE_VOLUME_DOWN -> { audioManager.adjustStreamVolume( AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI ) - return true + true } KEYCODE_BACK ->{ onBackPressed() - return true + true } - else -> - return super.onKeyDown(keyCode, event) + else -> super.dispatchKeyEvent(event) } } diff --git a/goonj/src/main/java/ai/rever/goonj/Goonj.kt b/goonj/src/main/java/ai/rever/goonj/Goonj.kt index 457c7e0..d55fea9 100644 --- a/goonj/src/main/java/ai/rever/goonj/Goonj.kt +++ b/goonj/src/main/java/ai/rever/goonj/Goonj.kt @@ -127,11 +127,7 @@ object Goonj { goonjPlayerServiceInterface = null } - fun resume() = run { GoonjPlayerManager.resume() } - - fun pause() = run { GoonjPlayerManager.pause() } - - fun seekTo(position : Long) = run { GoonjPlayerManager.seekTo(position) } + fun startNewSession() = run { GoonjPlayerManager.startNewSession() } fun addTrack(track : Track, index: Int? = null) = run { index?.let { @@ -139,19 +135,11 @@ object Goonj { } ?: GoonjPlayerManager.addTrack(track) } - fun startNewSession() = run { GoonjPlayerManager.startNewSession() } - + fun resume() = run { GoonjPlayerManager.resume() } - fun customiseNotification(useNavigationAction: Boolean, - usePlayPauseAction: Boolean, - fastForwardIncrementMs: Long , - rewindIncrementMs: Long, smallIcon: Int) = run { - GoonjNotificationManager.customiseNotification( - useNavigationAction, usePlayPauseAction, - fastForwardIncrementMs, rewindIncrementMs, smallIcon - ) - } + fun pause() = run { GoonjPlayerManager.pause() } + fun seekTo(position : Long) = run { GoonjPlayerManager.seekTo(position) } fun removeTrack(index : Int) = run { GoonjPlayerManager.removeTrack(index) } @@ -163,30 +151,52 @@ object Goonj { fun skipToPrevious() = run { GoonjPlayerManager.skipToPrevious() } + fun finishTrack() = run { GoonjPlayerManager.finishTrack() } + + fun customiseNotification(useNavigationAction: Boolean, + usePlayPauseAction: Boolean, + fastForwardIncrementMs: Long , + rewindIncrementMs: Long, + smallIcon: Int) = run { + GoonjNotificationManager.customiseNotification(useNavigationAction, + usePlayPauseAction, fastForwardIncrementMs, rewindIncrementMs, smallIcon) + } + fun removeNotification() = run { GoonjPlayerManager.removeNotification() } - fun finishTrack() = run { GoonjPlayerManager.finishTrack() } + val trackList get() = GoonjPlayerManager.trackList + + val playerState: GoonjPlayerState? get() = GoonjPlayerManager.playerStateBehaviorSubject.value + + val currentTrack: Track? get() = GoonjPlayerManager.currentTrackSubject.value + val trackPosition: Long get() = GoonjPlayerManager.trackPosition var autoplay: Boolean - get() = GoonjPlayerManager.autoplay + get() = GoonjPlayerManager.autoplayTrackSubject.value?: false set(value) { run { - GoonjPlayerManager.autoplay = value + GoonjPlayerManager.autoplayTrackSubject.onNext(value) } } - val playerState: GoonjPlayerState? get() = GoonjPlayerManager.playerStateBehaviorSubject.value + val playerStateObservable: Observable get() = GoonjPlayerManager.playerStateBehaviorSubject.observeOn(AndroidSchedulers.mainThread()) - val currentTrack: Track? get() = GoonjPlayerManager.currentTrackSubject.value + val currentTrackObservable: Observable get() = GoonjPlayerManager.currentTrackSubject.observeOn(AndroidSchedulers.mainThread()) - val playerStateObservable: Observable? get() = GoonjPlayerManager.playerStateBehaviorSubject.observeOn(AndroidSchedulers.mainThread()) + val autoplayObservable: Observable? get() = GoonjPlayerManager.autoplayTrackSubject.observeOn(AndroidSchedulers.mainThread()) - val currentTrackObservable: Observable? get() = GoonjPlayerManager.currentTrackSubject.observeOn(AndroidSchedulers.mainThread()) - val trackList get() = GoonjPlayerManager.trackList - val trackPosition get() = GoonjPlayerManager.trackPosition + /** + * Track progress 0 to 1 + */ + val trackProgress: Double get() { + currentTrack?.apply { + return trackState.position.toDouble() / trackState.duration.toDouble() + } + return 0.toDouble() + } // internal method internal fun startForeground(notificationId: Int, notification: Notification?) = run { diff --git a/goonj/src/main/java/ai/rever/goonj/interfaces/AudioPlayer.kt b/goonj/src/main/java/ai/rever/goonj/interfaces/AudioPlayer.kt index 8e28b5d..4c50cdc 100644 --- a/goonj/src/main/java/ai/rever/goonj/interfaces/AudioPlayer.kt +++ b/goonj/src/main/java/ai/rever/goonj/interfaces/AudioPlayer.kt @@ -17,7 +17,7 @@ interface AudioPlayer { fun suspend() fun unsuspend() - var autoplay: Boolean +// var autoplay: Boolean fun seekTo(index: Int, positionMs: Long) {} diff --git a/goonj/src/main/java/ai/rever/goonj/interfaces/GoonjPlayer.kt b/goonj/src/main/java/ai/rever/goonj/interfaces/GoonjPlayer.kt index 27ce663..71b7a15 100644 --- a/goonj/src/main/java/ai/rever/goonj/interfaces/GoonjPlayer.kt +++ b/goonj/src/main/java/ai/rever/goonj/interfaces/GoonjPlayer.kt @@ -14,7 +14,7 @@ interface GoonjPlayer { Goonj.startNewSession() } - fun play() { + fun resume() { Goonj.resume() } @@ -71,14 +71,16 @@ interface GoonjPlayer { val playerState: GoonjPlayerState? get() = Goonj.playerState - val currentTrack: Track? get() = Goonj.currentTrack val playerStateObservable get() = Goonj.playerStateObservable val currentTrackObservable get() = Goonj.currentTrackObservable + val currentTrack: Track? get() = Goonj.currentTrack + val trackList get() = Goonj.trackList val trackPosition get() = Goonj.trackPosition + val trackProgress get() = Goonj.trackProgress } \ No newline at end of file diff --git a/goonj/src/main/java/ai/rever/goonj/manager/GoonjPlayerManager.kt b/goonj/src/main/java/ai/rever/goonj/manager/GoonjPlayerManager.kt index 58d19d0..b1e5e4c 100644 --- a/goonj/src/main/java/ai/rever/goonj/manager/GoonjPlayerManager.kt +++ b/goonj/src/main/java/ai/rever/goonj/manager/GoonjPlayerManager.kt @@ -27,8 +27,11 @@ internal object GoonjPlayerManager { } internal val playerStateBehaviorSubject: BehaviorSubject = BehaviorSubject.create() + internal val currentTrackSubject: BehaviorSubject = BehaviorSubject.create() + internal val autoplayTrackSubject: BehaviorSubject = BehaviorSubject.createDefault(false) + private val player: AudioPlayer? get() { // isRemote = mediaRoute?.supportsControlCategory( // MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)?: false @@ -68,12 +71,6 @@ internal object GoonjPlayerManager { player?.startNewSession() } - internal var autoplay: Boolean - get() = player?.autoplay ?: false - set(value) { - player?.autoplay = value - } - internal fun removeTrack(index : Int){ mTrackList.removeAt(index) player?.remove(index) diff --git a/goonj/src/main/java/ai/rever/goonj/player/LocalAudioPlayer.kt b/goonj/src/main/java/ai/rever/goonj/player/LocalAudioPlayer.kt index 596ab1e..af90d67 100644 --- a/goonj/src/main/java/ai/rever/goonj/player/LocalAudioPlayer.kt +++ b/goonj/src/main/java/ai/rever/goonj/player/LocalAudioPlayer.kt @@ -74,8 +74,6 @@ class LocalAudioPlayer: AudioPlayer { private val concatenatingMediaSource by lazy { ConcatenatingMediaSource() } - private var _autoplay = false - private val trackList get() = GoonjPlayerManager.trackList private fun onStart() { @@ -161,8 +159,10 @@ class LocalAudioPlayer: AudioPlayer { if (currentTrack.id != lastKnownTrack?.id) { GoonjPlayerManager.onTrackComplete(lastKnownTrack ?: return) - if (!autoplay) { - pause() + GoonjPlayerManager.autoplayTrackSubject.value?.let { + if (!it) { + pause() + } } } } @@ -194,7 +194,6 @@ class LocalAudioPlayer: AudioPlayer { } override fun seekTo(positionMs: Long) { - Log.e("==========>", "$positionMs") player?.seekTo(positionMs) } @@ -269,13 +268,6 @@ class LocalAudioPlayer: AudioPlayer { override fun getTrackPosition() = player?.currentPosition ?: 0 - override var autoplay: Boolean - get() = _autoplay - set(value) { - _autoplay = value - } - - override fun onRemoveNotification() { playerNotificationManager.setPlayer(null) } diff --git a/goonj/src/main/java/ai/rever/goonj/player/RemoteAudioPlayer.kt b/goonj/src/main/java/ai/rever/goonj/player/RemoteAudioPlayer.kt index bfc3728..5fa35b5 100644 --- a/goonj/src/main/java/ai/rever/goonj/player/RemoteAudioPlayer.kt +++ b/goonj/src/main/java/ai/rever/goonj/player/RemoteAudioPlayer.kt @@ -22,12 +22,10 @@ import java.lang.ref.WeakReference class RemoteAudioPlayer: AudioPlayer { private var player: RemotePlaybackClient? = null - - private var _autoplay = false - - private var isHandlerRunning = false + // TODO : Re-create RemoteAudioPlayer with playlist support, for autoplay + override fun connect(route: MediaRouter.RouteInfo) { // TODO check for resume services @@ -172,14 +170,6 @@ class RemoteAudioPlayer: AudioPlayer { } - override var autoplay - get() = _autoplay - set(value) { - _autoplay = value - - // TODO : Re-create RemoteAudioPlayer with playlist support - } - private fun seekInternal(item: Track) { if (player?.hasSession() != true) { // ignore if no trackList