MoreActivity -

Completed implementing progressive timing for each song played.

Songs playing issue related to progress view solved,

Completed full implementations of woka songs completed
This commit is contained in:
2024-06-11 21:27:26 +05:30
parent 599f817e73
commit 976238d1f3
4 changed files with 164 additions and 23 deletions

View File

@@ -1,6 +1,9 @@
package com.woka.modules.wokasongs
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
@@ -9,34 +12,92 @@ import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.Player.EVENT_IS_LOADING_CHANGED
import com.woka.R
import com.woka.databinding.WokaSongViewHolderBinding
import com.woka.modules.wokasongs.models.SongData
import com.woka.utils.TAG
import com.woka.utils.formatTime
import com.woka.utils.hide
import com.woka.utils.show
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.math.log
class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.SongViewHolder>() {
companion object{
private const val CURRENT_TIME_CHANGED = 123
private const val PLAY_BACK_CHANGED = 124
}
inner class SongViewHolder(val binding: WokaSongViewHolderBinding): ViewHolder(binding.root)
private var player: ExoPlayer
private var player = ExoPlayer.Builder(context).build()
private var currentPlayingPos = -1
private var songList = mutableListOf<SongData>()
private val lock = Any()
private val handler: Handler = Handler(Looper.getMainLooper())
private val updateProgressAction: Runnable = object : Runnable {
override fun run() {
if (currentPlayingPos >= 0 && player.isPlaying){
notifyItemChanged(currentPlayingPos, CURRENT_TIME_CHANGED)
}
handler.postDelayed(this, 1000)
}
}
init {
player = ExoPlayer.Builder(context).build()
player.addListener(object : Player.Listener{
override fun onEvents(player: Player, events: Player.Events) {
super.onEvents(player, events)
if (currentPlayingPos >= 0)
notifyItemChanged(currentPlayingPos)
if (currentPlayingPos >= 0){
if (events.containsAny(ExoPlayer.EVENT_IS_LOADING_CHANGED,
ExoPlayer.EVENT_IS_PLAYING_CHANGED)){
notifyItemChanged(currentPlayingPos, PLAY_BACK_CHANGED)
}
}
}
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
if (playbackState == ExoPlayer.STATE_ENDED){
player.removeListener(this)
player.pause()
player.addListener(this)
val lastPosition = currentPlayingPos
currentPlayingPos = -1
notifyItemChanged(lastPosition, PLAY_BACK_CHANGED)
}
}
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
super.onMediaItemTransition(mediaItem, reason)
if (reason == ExoPlayer.MEDIA_ITEM_TRANSITION_REASON_AUTO){
player.removeListener(this)
player.pause()
player.addListener(this)
val lastPosition = currentPlayingPos
currentPlayingPos = -1
notifyItemChanged(lastPosition, PLAY_BACK_CHANGED)
}
}
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
if (currentPlayingPos >= 0)
notifyItemChanged(currentPlayingPos)
if (currentPlayingPos >= 0) {
notifyItemChanged(currentPlayingPos, PLAY_BACK_CHANGED)
}
}
})
}
@@ -44,6 +105,8 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
fun releasePlayer(){
player.stop()
player.release()
handler.removeCallbacks(updateProgressAction)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
@@ -55,12 +118,59 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
override fun getItemCount(): Int = songList.size
override fun onBindViewHolder(
holder: SongViewHolder,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.isNotEmpty()){
synchronized(lock){
holder.binding.apply {
when (payloads[0]){
CURRENT_TIME_CHANGED -> {
if (currentPlayingPos == position){
currentTime.text = player.currentPosition.formatTime()
}else{
currentTime.text = root.context.getString(R.string._00_00)
}
}
PLAY_BACK_CHANGED -> {
if (currentPlayingPos == holder.absoluteAdapterPosition){
if (player.isPlaying){
progressBar.post {
progressBar.show()
playBtn.setImageResource(R.drawable.ic_pause)
playBtn.show()
progressBar.hide()
}
}else if (player.isLoading){
playBtn.hide()
progressBar.show()
}else{
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
progressBar.hide()
}
}else{
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
progressBar.hide()
}
}
else -> super.onBindViewHolder(holder, position, payloads)
}
}
}
}else super.onBindViewHolder(holder, position, payloads)
}
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
if (position >= songList.size) return
val songData = songList[position]
holder.binding.apply {
title.text = songData.title
totalTime.text = try {
if (songData.song_duration?.split(":")?.get(0)?.toInt() == 0)
songData.song_duration.substring(3)
@@ -70,6 +180,12 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
songData.song_duration
}
if (currentPlayingPos == position){
currentTime.text = player.currentPosition.formatTime()
}else{
currentTime.text = root.context.getString(R.string._00_00)
}
root.setOnClickListener {
if (currentPlayingPos == holder.absoluteAdapterPosition){
if (player.isLoading){
@@ -81,11 +197,11 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
player.play()
}
}else{
player.pause()
if (currentPlayingPos >= 0) notifyItemChanged(currentPlayingPos)
val lastPlayingPos = currentPlayingPos
currentPlayingPos = holder.absoluteAdapterPosition
if (lastPlayingPos >= 0) {
notifyItemChanged(lastPlayingPos, PLAY_BACK_CHANGED)
}
player.seekTo(holder.absoluteAdapterPosition, 0)
player.play()
}
@@ -96,18 +212,20 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
progressBar.show()
playBtn.hide()
}else if (player.isPlaying){
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_pause)
progressBar.post {
playBtn.setImageResource(R.drawable.ic_pause)
playBtn.show()
progressBar.hide()
}
}else{
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
progressBar.hide()
}
}else{
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
progressBar.hide()
}
}
}
@@ -123,6 +241,9 @@ class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.
player.addMediaItems(mediaItems)
player.prepare()
handler.removeCallbacks(updateProgressAction)
handler.post(updateProgressAction)
notifyDataSetChanged()
}
}

View File

@@ -5,6 +5,7 @@ import android.animation.ObjectAnimator
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.util.Log
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
@@ -15,6 +16,9 @@ import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import com.woka.WokaApp.Companion.userPrefs
import java.util.Locale
import kotlin.math.ceil
import kotlin.math.round
import kotlin.math.roundToLong
fun Window.lightStatusBar(lightStatus: Boolean = false){
WindowCompat.getInsetsController(this, decorView).isAppearanceLightStatusBars = lightStatus
@@ -69,4 +73,17 @@ fun Context.toast(text: String?, length: Int = Toast.LENGTH_SHORT){
fun Fragment.toast(text: String?, length: Int = Toast.LENGTH_SHORT){
activity?.toast(text, length)
}
fun Long.formatTime(): String {
val totalSeconds = ceil(this / 1000.0).toLong()
val hours = totalSeconds / 3600
val minutes = (totalSeconds % 3600) / 60
val seconds = totalSeconds % 60
return if (hours > 0) {
String.format("%02d:%02d:%02d", hours, minutes, seconds)
} else {
String.format("%02d:%02d", minutes, seconds)
}
}

View File

@@ -29,16 +29,16 @@
<RelativeLayout
android:id="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
>
<ImageView
android:id="@+id/play_btn"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/image"
android:src="@drawable/ic_play"
android:scaleType="fitXY"
@@ -47,8 +47,8 @@
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminate="true"
android:indeterminateTint="@color/white"
@@ -64,6 +64,7 @@
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_toStartOf="@+id/ll"
android:layout_toEndOf="@id/view"
@@ -89,7 +90,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="00:00"
android:text="@string/_00_00"
android:textColor="@color/white"
android:fontFamily="@font/exo_2"
@@ -99,7 +100,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="/"
android:text="@string/slash"
android:textColor="@color/white"
android:fontFamily="@font/exo_2"

View File

@@ -163,4 +163,6 @@
<string name="woka_songs">WOKA Songs</string>
<string name="app_name_caps" translatable="false">WOKA</string>
<string name="do_you_want_to_exit_from_the_woka_app">Do you want to exit from the WOKA app?</string>
<string name="_00_00">00:00</string>
<string name="slash">/</string>
</resources>