-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
310 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...ntscompose/src/main/java/com/jeluchu/jchucomponentscompose/core/platform/BaseViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.jeluchu.jchucomponentscompose.core.platform | ||
|
||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import com.jeluchu.jchucomponentscompose.core.exception.Failure | ||
|
||
abstract class BaseViewModel : ViewModel() { | ||
|
||
var failure: MutableLiveData<Failure> = MutableLiveData() | ||
var showSpinner: MutableLiveData<Boolean> = MutableLiveData() | ||
|
||
protected fun handleShowSpinner(show: Boolean) { | ||
this.showSpinner.value = show | ||
} | ||
|
||
protected fun handleFailure(failure: Failure) { | ||
this.failure.value = failure | ||
} | ||
|
||
} |
8 changes: 8 additions & 0 deletions
8
...tscompose/src/main/java/com/jeluchu/jchucomponentscompose/core/platform/ContextHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.jeluchu.jchucomponentscompose.core.platform | ||
|
||
import android.content.Context | ||
|
||
class ContextHandler | ||
(private val context: Context) { | ||
val appContext: Context get() = context.applicationContext | ||
} |
9 changes: 9 additions & 0 deletions
9
...tscompose/src/main/java/com/jeluchu/jchucomponentscompose/core/platform/NetworkHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.jeluchu.jchucomponentscompose.core.platform | ||
|
||
import android.content.Context | ||
import com.jeluchu.jchucomponentscompose.core.extensions.context.checkNetworkState | ||
|
||
class NetworkHandler | ||
(private val context: Context) { | ||
val isConnected get() = context.checkNetworkState() | ||
} |
180 changes: 180 additions & 0 deletions
180
...se/src/main/java/com/jeluchu/jchucomponentscompose/utils/mediaplayer/MediaPlayerHolder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
package com.jeluchu.jchucomponentscompose.utils.mediaplayer | ||
|
||
import android.content.Context | ||
import android.media.MediaPlayer | ||
import android.net.Uri | ||
import com.jeluchu.inook.core.utils.mediaplayer.PlaybackInfoListener | ||
import com.jeluchu.jchucomponentscompose.core.extensions.ints.milliSecondsToTimer | ||
import com.jeluchu.jchucomponentscompose.core.extensions.strings.empty | ||
import java.util.concurrent.Executors | ||
import java.util.concurrent.ScheduledExecutorService | ||
import java.util.concurrent.TimeUnit | ||
|
||
class MediaPlayerHolder(context: Context) : PlayerAdapter { | ||
private val mContext: Context = context.applicationContext | ||
private var mMediaPlayer: MediaPlayer? = null | ||
private var mResourceId = String.empty() | ||
private var mPlaybackInfoListener: PlaybackInfoListener? = null | ||
private var mExecutor: ScheduledExecutorService? = null | ||
private var mSeekbarPositionUpdateTask: Runnable? = null | ||
|
||
/** | ||
* Once the [MediaPlayer] is released, it can't be used again, and another one has to be | ||
* created. In the onStop() method of the [MainActivity] the [MediaPlayer] is | ||
* released. Then in the onStart() of the [MainActivity] a new [MediaPlayer] | ||
* object has to be created. That's why this method is private, and called by load(int) and | ||
* not the constructor. | ||
*/ | ||
private fun initializeMediaPlayer() { | ||
if (mMediaPlayer == null) { | ||
mMediaPlayer = MediaPlayer() | ||
mMediaPlayer!!.setOnCompletionListener { | ||
stopUpdatingCallbackWithPosition(true) | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onStateChanged(PlaybackInfoListener.State.COMPLETED) | ||
mPlaybackInfoListener!!.onPlaybackCompleted() | ||
} | ||
} | ||
} | ||
} | ||
|
||
override val isPlaying: Boolean | ||
get() = if (mMediaPlayer != null) mMediaPlayer!!.isPlaying else false | ||
|
||
override val currentProgress: Float | ||
get() = if (mMediaPlayer != null) { | ||
val currentSeconds: Long = (mMediaPlayer!!.currentPosition / 1000).toLong() | ||
val totalSeconds: Long = (mMediaPlayer!!.duration / 1000).toLong() | ||
(currentSeconds.toDouble() / totalSeconds * 100).toFloat() | ||
} else 0F | ||
|
||
override val currentTime: String | ||
get() = if (mMediaPlayer != null) mMediaPlayer!!.currentPosition.milliSecondsToTimer() | ||
else String.empty() | ||
|
||
override val totalTime: String | ||
get() = if (mMediaPlayer != null) mMediaPlayer!!.duration.milliSecondsToTimer() | ||
else String.empty() | ||
|
||
override fun togglePlaying(isPlaying: Boolean) { | ||
if (mMediaPlayer != null) { | ||
when (isPlaying) { | ||
true -> mMediaPlayer!!.pause() | ||
false -> mMediaPlayer!!.start() | ||
} | ||
} | ||
} | ||
|
||
fun setPlaybackInfoListener(listener: PlaybackInfoListener?) { | ||
mPlaybackInfoListener = listener | ||
} | ||
|
||
override fun loadMedia(mp3Link: String) { | ||
mResourceId = mp3Link | ||
initializeMediaPlayer() | ||
try { | ||
mMediaPlayer!!.setDataSource(mContext, Uri.parse(mResourceId)) | ||
} catch (e: Exception) { | ||
e.message | ||
} | ||
try { | ||
mMediaPlayer!!.prepare() | ||
} catch (e: Exception) { | ||
e.message | ||
} | ||
initializeProgressCallback() | ||
} | ||
|
||
override fun release() { | ||
if (mMediaPlayer != null) { | ||
mMediaPlayer!!.release() | ||
mMediaPlayer = null | ||
} | ||
} | ||
|
||
|
||
override fun play() { | ||
if (mMediaPlayer != null && !mMediaPlayer!!.isPlaying) { | ||
mMediaPlayer!!.start() | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onStateChanged(PlaybackInfoListener.State.PLAYING) | ||
} | ||
startUpdatingCallbackWithPosition() | ||
} | ||
} | ||
|
||
override fun reset() { | ||
if (mMediaPlayer != null) { | ||
mMediaPlayer!!.reset() | ||
loadMedia(mResourceId) | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onStateChanged(PlaybackInfoListener.State.RESET) | ||
} | ||
stopUpdatingCallbackWithPosition(true) | ||
} | ||
} | ||
|
||
override fun pause() { | ||
if (mMediaPlayer != null && mMediaPlayer!!.isPlaying) { | ||
mMediaPlayer!!.pause() | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onStateChanged(PlaybackInfoListener.State.PAUSED) | ||
} | ||
} | ||
} | ||
|
||
override fun seekTo(position: Int) { | ||
if (mMediaPlayer != null) { | ||
mMediaPlayer!!.seekTo(position) | ||
} | ||
} | ||
|
||
private fun startUpdatingCallbackWithPosition() { | ||
if (mExecutor == null) { | ||
mExecutor = Executors.newSingleThreadScheduledExecutor() | ||
} | ||
if (mSeekbarPositionUpdateTask == null) { | ||
mSeekbarPositionUpdateTask = Runnable { updateProgressCallbackTask() } | ||
} | ||
mExecutor!!.scheduleAtFixedRate( | ||
mSeekbarPositionUpdateTask, | ||
0, | ||
PLAYBACK_POSITION_REFRESH_INTERVAL_MS.toLong(), | ||
TimeUnit.MILLISECONDS | ||
) | ||
} | ||
|
||
// Reports media playback position to mPlaybackProgressCallback. | ||
private fun stopUpdatingCallbackWithPosition(resetUIPlaybackPosition: Boolean) { | ||
if (mExecutor != null) { | ||
mExecutor!!.shutdownNow() | ||
mExecutor = null | ||
mSeekbarPositionUpdateTask = null | ||
if (resetUIPlaybackPosition && mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onPositionChanged(0) | ||
} | ||
} | ||
} | ||
|
||
private fun updateProgressCallbackTask() { | ||
if (mMediaPlayer != null && mMediaPlayer!!.isPlaying) { | ||
val currentPosition = mMediaPlayer!!.currentPosition | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onPositionChanged(currentPosition) | ||
} | ||
} | ||
} | ||
|
||
override fun initializeProgressCallback() { | ||
val duration = mMediaPlayer!!.duration | ||
if (mPlaybackInfoListener != null) { | ||
mPlaybackInfoListener!!.onDurationChanged(duration) | ||
mPlaybackInfoListener!!.onPositionChanged(0) | ||
} | ||
} | ||
|
||
companion object { | ||
const val PLAYBACK_POSITION_REFRESH_INTERVAL_MS = 1000 | ||
} | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
...src/main/java/com/jeluchu/jchucomponentscompose/utils/mediaplayer/PlaybackInfoListener.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.jeluchu.inook.core.utils.mediaplayer | ||
|
||
abstract class PlaybackInfoListener { | ||
|
||
internal annotation class State { | ||
companion object { | ||
var INVALID = -1 | ||
var PLAYING = 0 | ||
var PAUSED = 1 | ||
var RESET = 2 | ||
var COMPLETED = 3 | ||
} | ||
} | ||
|
||
open fun onLogUpdated(formattedMessage: String?) {} | ||
open fun onDurationChanged(duration: Int) {} | ||
open fun onPositionChanged(position: Int) {} | ||
open fun onStateChanged(@State state: Int) {} | ||
open fun onPlaybackCompleted() {} | ||
|
||
companion object { | ||
@JvmStatic | ||
fun convertStateToString(@State state: Int): String { | ||
return when (state) { | ||
State.COMPLETED -> "COMPLETED" | ||
State.INVALID -> "INVALID" | ||
State.PAUSED -> "PAUSED" | ||
State.PLAYING -> "PLAYING" | ||
State.RESET -> "RESET" | ||
else -> "N/A" | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.