Integrated user_video_view api for all modules.
Sync for clicks when logout synchronously. Sync for clicks when user closes app.
This commit is contained in:
@@ -2,7 +2,6 @@ package com.woka
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import com.jwplayer.pub.api.license.LicenseUtil
|
||||
import com.onesignal.OneSignal
|
||||
import com.woka.database.AppDatabase
|
||||
@@ -10,7 +9,6 @@ import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.userPreference.UserPreference
|
||||
import com.woka.utils.JW_PLAYER_LICENSE
|
||||
import com.woka.utils.ONESIGNAL_APP_ID
|
||||
import com.woka.utils.TAG
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.woka.databinding.ActivityAudioBooksBinding
|
||||
import com.woka.databinding.DialogModuleShowerBinding
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.utils.NoSignInDialog
|
||||
@@ -377,7 +377,7 @@ class AudioBooksActivity : WokaBaseActivity() {
|
||||
.build()
|
||||
)
|
||||
},
|
||||
mutableListOf(VideoViewRequestData(
|
||||
mutableListOf(VideoViewData(
|
||||
audioBookData.id,
|
||||
ContentType.AUDIO
|
||||
))
|
||||
|
||||
@@ -7,11 +7,8 @@ import com.woka.database.remote.models.RemoteClickEvent
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.networking.RetrofitHelper
|
||||
import com.woka.networking.RetrofitHelper.handleApiCall
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val SYNC_BATCH_COUNT = 10
|
||||
private const val SYNC_BATCH_COUNT = 15
|
||||
|
||||
object RemoteSync {
|
||||
|
||||
@@ -20,47 +17,45 @@ object RemoteSync {
|
||||
private val clicksDao = appDatabase?.clicksDao()
|
||||
private val apiService = RetrofitHelper.getRetrofit().create(RemoteApiService::class.java)
|
||||
|
||||
fun syncClickEvents(){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
Log.d(TAG, "syncClickEvents: CLICK EVENTS SYNC CALLED")
|
||||
suspend fun syncClickEvents(){
|
||||
Log.d(TAG, "syncClickEvents: CLICK EVENTS SYNC CALLED")
|
||||
|
||||
var roundCount = 0
|
||||
var roundCount = 0
|
||||
|
||||
while (true){
|
||||
val clicksBatch = clicksDao?.getClickEventBatch(SYNC_BATCH_COUNT)
|
||||
while (true){
|
||||
val clicksBatch = clicksDao?.getClickEventBatch(SYNC_BATCH_COUNT)
|
||||
|
||||
if (clicksDao == null || clicksBatch.isNullOrEmpty()){
|
||||
Log.d(TAG, "syncClickEvents: RECEIVED BATCH IS EMPTY")
|
||||
break
|
||||
}
|
||||
|
||||
Log.d(TAG, "syncClickEvents: BATCH COUNT FROM DATABASE ${clicksBatch.size}")
|
||||
when (val response = handleApiCall{ apiService.sendClickEvents(clicksBatch.map { RemoteClickEvent(it) })}){
|
||||
is ApiResult.Error -> {
|
||||
Log.e(TAG, "syncClickEvents: BATCH SYNC FAILED due to ${response.errorMessage}", response.error)
|
||||
break
|
||||
}
|
||||
is ApiResult.Loading -> {}
|
||||
is ApiResult.Success -> {
|
||||
Log.d(TAG, "syncClickEvents: BATCH SYNC IS SUCCESSFUL")
|
||||
|
||||
Log.d(TAG, "syncClickEvents: DELETING SYNCED DATA FROM LOCAL DATABASE")
|
||||
val deleteCount = clicksDao.deleteClickEvents(clicksBatch)
|
||||
Log.d(TAG, "syncClickEvents: $deleteCount ENTRIES ARE DELETED FROM LOCAL DATABASE")
|
||||
|
||||
if (deleteCount <= 0){
|
||||
Log.e(TAG, "syncClickEvents: NO ENTRIES WERE DELETED FROM LOCAL DATABASE")
|
||||
}
|
||||
|
||||
roundCount++
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "syncClickEvents: \n")
|
||||
if (clicksDao == null || clicksBatch.isNullOrEmpty()){
|
||||
Log.d(TAG, "syncClickEvents: RECEIVED BATCH IS EMPTY")
|
||||
break
|
||||
}
|
||||
|
||||
Log.d(TAG, "syncClickEvents: NUMBER OF ROUND : $roundCount")
|
||||
Log.d(TAG, "syncClickEvents: BATCH COUNT FROM DATABASE ${clicksBatch.size}")
|
||||
when (val response = handleApiCall{ apiService.sendClickEvents(clicksBatch.map { RemoteClickEvent(it) })}){
|
||||
is ApiResult.Error -> {
|
||||
Log.e(TAG, "syncClickEvents: BATCH SYNC FAILED due to ${response.errorMessage}", response.error)
|
||||
break
|
||||
}
|
||||
is ApiResult.Loading -> {}
|
||||
is ApiResult.Success -> {
|
||||
Log.d(TAG, "syncClickEvents: BATCH SYNC IS SUCCESSFUL")
|
||||
|
||||
Log.d(TAG, "syncClickEvents: DELETING SYNCED DATA FROM LOCAL DATABASE")
|
||||
val deleteCount = clicksDao.deleteClickEvents(clicksBatch)
|
||||
Log.d(TAG, "syncClickEvents: $deleteCount ENTRIES ARE DELETED FROM LOCAL DATABASE")
|
||||
|
||||
if (deleteCount <= 0){
|
||||
Log.e(TAG, "syncClickEvents: NO ENTRIES WERE DELETED FROM LOCAL DATABASE")
|
||||
}
|
||||
|
||||
roundCount++
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "syncClickEvents: \n")
|
||||
}
|
||||
|
||||
Log.d(TAG, "syncClickEvents: NUMBER OF ROUND : $roundCount")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,4 +14,4 @@ data class VideoViewEvent(
|
||||
@ColumnInfo(name = "post_type") val postType: Int,
|
||||
@ColumnInfo(name = "categoryId") val categoryId: Int,
|
||||
@ColumnInfo(name = "total_watch_duration") val watchDuration: Long
|
||||
)
|
||||
)
|
||||
@@ -20,7 +20,7 @@ import com.woka.home.views.FMActivity
|
||||
import com.woka.karaoke.views.KaraokeActivity
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.LiveStreamPlayerActivity
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.shop.views.ShopActivity
|
||||
@@ -155,7 +155,7 @@ class Home2Fragment : Fragment() {
|
||||
.build()
|
||||
)
|
||||
},
|
||||
mutableListOf(VideoViewRequestData(
|
||||
mutableListOf(VideoViewData(
|
||||
0,
|
||||
ContentType.TEASER
|
||||
))
|
||||
|
||||
@@ -51,7 +51,7 @@ import com.woka.karaoke.player.KaraokePlayerData
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.onboard.views.OnboardActivity
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.userdata.UserRepository
|
||||
@@ -795,7 +795,7 @@ class MyListFragment : Fragment() {
|
||||
)
|
||||
},
|
||||
mutableListOf(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
audioBookData.id,
|
||||
ContentType.AUDIO
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.woka.home.mylist.MyListRepository
|
||||
import com.woka.home.mylist.viewmodel.FavoriteViewModel
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.isNetworkConnected
|
||||
@@ -346,7 +346,7 @@ class FavAudioFragment : Fragment() {
|
||||
)
|
||||
},
|
||||
mutableListOf(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
audioBookData.id,
|
||||
ContentType.AUDIO
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Player.Listener
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.woka.database.helpers.RemoteSync
|
||||
import com.woka.home.views.BottomNavigation.Companion.HOME
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.userdata.UserRepository
|
||||
@@ -97,6 +98,7 @@ class HomeViewModel : ViewModel() {
|
||||
fun logout() {
|
||||
viewModelScope.launch {
|
||||
_logoutLiveData.postValue(ApiResult.Loading())
|
||||
RemoteSync.syncClickEvents()
|
||||
_logoutLiveData.postValue(UserRepository.logout())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.woka.R
|
||||
import com.woka.database.helpers.ClicksHelper
|
||||
import com.woka.database.models.ContentType
|
||||
import com.woka.databinding.ActivityFmactivityBinding
|
||||
import com.woka.userdata.UserRepository
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import com.woka.utils.TAG
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.hide
|
||||
@@ -38,6 +40,9 @@ class FMActivity : WokaBaseActivity() {
|
||||
|
||||
private val clickHelper = ClicksHelper
|
||||
|
||||
private var playbackStartTime: Long = 0
|
||||
private var totalPlaybackDuration: Long = 0
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -66,6 +71,32 @@ class FMActivity : WokaBaseActivity() {
|
||||
clickEvents()
|
||||
|
||||
setObservers()
|
||||
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
if (fmId > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
fmId,
|
||||
ContentType.FM.id,
|
||||
playingDurationInSecs
|
||||
)
|
||||
)
|
||||
|
||||
totalPlaybackDuration = 0
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
@@ -22,11 +22,13 @@ import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.bumptech.glide.Glide
|
||||
import com.woka.BuildConfig
|
||||
import com.woka.R
|
||||
import com.woka.WokaApp.Companion.userPrefs
|
||||
import com.woka.database.helpers.ClicksHelper
|
||||
import com.woka.database.helpers.RemoteSync
|
||||
import com.woka.database.models.ContentType
|
||||
import com.woka.databinding.ActivityHomeBinding
|
||||
import com.woka.home.fragments.Home1Fragment
|
||||
@@ -69,6 +71,7 @@ import com.woka.utils.lightStatusBar
|
||||
import com.woka.utils.setVisibility
|
||||
import com.woka.utils.show
|
||||
import com.woka.utils.toast
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.min
|
||||
|
||||
class HomeActivity : WokaBaseActivity(),
|
||||
@@ -137,8 +140,12 @@ class HomeActivity : WokaBaseActivity(),
|
||||
decisionDialog.message = getString(R.string.do_you_want_to_exit_from_the_woka_app)
|
||||
|
||||
decisionDialog.setPositiveButton(getString(R.string.yes)){
|
||||
@Suppress("DEPRECATION")
|
||||
super.onBackPressed()
|
||||
lifecycleScope.launch {
|
||||
RemoteSync.syncClickEvents()
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
decisionDialog.setNegativeButton(getString(R.string.no))
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.woka.modules.wokasongs.WokaSongsAdapter
|
||||
import com.woka.modules.wokasongs.WokaSongsRepository
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.hide
|
||||
@@ -140,7 +140,7 @@ class MoreHomeActivity : WokaBaseActivity() {
|
||||
)
|
||||
},
|
||||
mutableListOf(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
0,
|
||||
ContentType.TEASER
|
||||
)
|
||||
|
||||
@@ -35,6 +35,8 @@ import com.woka.database.helpers.ClicksHelper
|
||||
import com.woka.database.models.ContentType
|
||||
import com.woka.databinding.ActivityKaraokePlayerrBinding
|
||||
import com.woka.players.models.PlayBackState
|
||||
import com.woka.userdata.UserRepository
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import com.woka.utils.TAG
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.hide
|
||||
@@ -93,6 +95,11 @@ class KaraokePlayerActivity : WokaBaseActivity() {
|
||||
private lateinit var permissionLauncher: ActivityResultLauncher<String>
|
||||
private lateinit var storagePermissionLauncher: ActivityResultLauncher<String>
|
||||
|
||||
// user video view params
|
||||
private var playbackStartTime: Long = 0
|
||||
private var totalPlaybackDuration: Long = 0
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
@@ -150,6 +157,36 @@ class KaraokePlayerActivity : WokaBaseActivity() {
|
||||
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
karaokePlayerData?.id?.let {
|
||||
if (it > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
it,
|
||||
ContentType.KARAOKE_VIDEO.id,
|
||||
playingDurationInSecs
|
||||
)
|
||||
)
|
||||
|
||||
totalPlaybackDuration = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
@@ -300,7 +337,7 @@ class KaraokePlayerActivity : WokaBaseActivity() {
|
||||
|
||||
RecordingState.PLAYING_AUDIO -> {
|
||||
|
||||
recordBtn.text = getString(R.string.stop_recording)
|
||||
recordBtn.text = getString(R.string.start_recording)
|
||||
recordBtn.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_rec_mic,
|
||||
0,
|
||||
|
||||
@@ -48,7 +48,7 @@ object RetrofitHelper {
|
||||
chain.proceed(request.build())
|
||||
})
|
||||
|
||||
clientBuilder.callTimeout(10, TimeUnit.SECONDS)
|
||||
clientBuilder.callTimeout(20, TimeUnit.SECONDS)
|
||||
|
||||
retrofit = Retrofit.Builder()
|
||||
.baseUrl(BuildConfig.WOKA_STAGINNG_BASE_URL)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.woka.players
|
||||
|
||||
import com.woka.networking.ApiResponse
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.POST
|
||||
@@ -9,6 +9,6 @@ import retrofit2.http.POST
|
||||
interface PlayerApiService {
|
||||
|
||||
@POST("user_video_view")
|
||||
suspend fun userVideoView(@Body requestData: VideoViewRequestData): Response<ApiResponse<Any>>
|
||||
suspend fun userVideoView(@Body requestData: VideoViewData): Response<ApiResponse<Any>>
|
||||
|
||||
}
|
||||
@@ -7,5 +7,5 @@ import kotlinx.parcelize.Parcelize
|
||||
@Parcelize
|
||||
data class VideoPlayList(
|
||||
val playlist: ArrayList<PlaylistItem>,
|
||||
val videoViewRequestDataList: MutableList<VideoViewRequestData>
|
||||
val videoViewRequestDataList: MutableList<VideoViewData>
|
||||
): Parcelable
|
||||
@@ -5,9 +5,9 @@ import com.woka.database.models.ContentType
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class VideoViewRequestData(
|
||||
data class VideoViewData(
|
||||
val id: Int?,
|
||||
val contentType: ContentType,
|
||||
val categoryId: String? = null,
|
||||
var categoryId: String? = null,
|
||||
var watchedDuration: String? = null
|
||||
) : Parcelable
|
||||
@@ -22,12 +22,14 @@ import com.woka.database.models.ContentType
|
||||
import com.woka.databinding.ActivityLiveStreamPlayerBinding
|
||||
import com.woka.players.KeepScreenOnHandler
|
||||
import com.woka.players.models.PlayBackState
|
||||
import com.woka.userdata.UserRepository
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.show
|
||||
|
||||
class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
const val EXTRA_LIVE_STREAM_URL = "extra_live_stream_url"
|
||||
const val EXTRA_LIVE_STREAM_ID = "extra_live_stream_id"
|
||||
|
||||
@@ -75,11 +77,11 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
liveTvId = intent.getIntExtra(EXTRA_LIVE_STREAM_ID, -1)
|
||||
|
||||
networkCallback = object : NetworkCallback(){
|
||||
networkCallback = object : NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
super.onAvailable(network)
|
||||
runOnUiThread {
|
||||
if (playbackState == PlayBackState.STOPPED){
|
||||
if (playbackState == PlayBackState.STOPPED) {
|
||||
binding.playerView.show()
|
||||
binding.errorView.hide()
|
||||
configureAndPlay()
|
||||
@@ -98,14 +100,32 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
player.pause()
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
if (liveTvId > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
liveTvId,
|
||||
ContentType.LIVE_TV.id,
|
||||
playingDurationInSecs
|
||||
)
|
||||
)
|
||||
|
||||
totalPlaybackDuration = 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
player.pause()
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@@ -116,7 +136,7 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
)
|
||||
}
|
||||
|
||||
private fun setUpPlayer(){
|
||||
private fun setUpPlayer() {
|
||||
player = binding.playerView.getPlayer(this)
|
||||
|
||||
// to keep up the screen om when video is being played
|
||||
@@ -130,48 +150,35 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
playlist.add(playlistItem)
|
||||
|
||||
playerConfig = PlayerConfig.Builder()
|
||||
.playlist(playlist)
|
||||
.autostart(true)
|
||||
.build()
|
||||
.playlist(playlist)
|
||||
.autostart(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun addListeners(){
|
||||
private fun addListeners() {
|
||||
player.addListener(EventType.PLAY, VideoPlayerEvents.OnPlayListener {
|
||||
playbackState = PlayBackState.PLAY
|
||||
binding.playerView.show()
|
||||
binding.errorView.hide()
|
||||
|
||||
errorRetryCount = ERROR_RETRY_COUNT
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
|
||||
upsertClickEvent()
|
||||
})
|
||||
player.addListener(EventType.PAUSE, VideoPlayerEvents.OnPauseListener {
|
||||
playbackState = PlayBackState.PAUSED
|
||||
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
upsertClickEvent()
|
||||
})
|
||||
player.addListener(EventType.ERROR, VideoPlayerEvents.OnErrorListener {
|
||||
playbackState = PlayBackState.STOPPED
|
||||
if (errorRetryCount > 0){
|
||||
if (errorRetryCount > 0) {
|
||||
errorRetryCount--
|
||||
configureAndPlay()
|
||||
}else{
|
||||
} else {
|
||||
binding.playerView.hide()
|
||||
binding.errorView.show()
|
||||
}
|
||||
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
})
|
||||
|
||||
(getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager).registerNetworkCallback(
|
||||
@@ -187,7 +194,7 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
player.setup(playerConfig)
|
||||
}
|
||||
|
||||
private fun clickEvents(){
|
||||
private fun clickEvents() {
|
||||
binding.apply {
|
||||
retryBtn.setOnClickListener {
|
||||
binding.playerView.show()
|
||||
@@ -201,7 +208,7 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private fun upsertClickEvent(){
|
||||
private fun upsertClickEvent() {
|
||||
if (liveTvId == -1) return
|
||||
|
||||
clickHelper.upsertClickEvent(
|
||||
|
||||
@@ -24,10 +24,13 @@ import com.woka.databinding.ActivityPlayerBinding
|
||||
import com.woka.players.KeepScreenOnHandler
|
||||
import com.woka.players.models.PlayBackState
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.utils.TAG
|
||||
import com.woka.userdata.UserRepository
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.show
|
||||
|
||||
private const val TAG = "PlayerActivity_TAG"
|
||||
|
||||
class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
companion object{
|
||||
@@ -46,6 +49,9 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
private var playingIndex: Int = 0
|
||||
private var seekPosition: Double = 0.0
|
||||
|
||||
private var playbackStartTime: Long = 0
|
||||
private var totalPlaybackDuration: Long = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
@@ -96,6 +102,41 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
videoPlayList?.videoViewRequestDataList?.let {playlistData ->
|
||||
if (playingIndex >= 0 && playingIndex < playlistData.size){
|
||||
with(playlistData[playingIndex]){
|
||||
|
||||
// user video view
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
id?.let {id ->
|
||||
if (id > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
id,
|
||||
contentType.id,
|
||||
playingDurationInSecs,
|
||||
categoryId
|
||||
)
|
||||
)
|
||||
|
||||
totalPlaybackDuration = 0
|
||||
Log.d(TAG, "onStop: API DONE $playingDurationInSecs")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clickEvents(){
|
||||
binding.apply {
|
||||
retryBtn.setOnClickListener {
|
||||
@@ -155,6 +196,9 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "addListeners: PLAY")
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
})
|
||||
player.addListener(EventType.PAUSE, VideoPlayerEvents.OnPauseListener {
|
||||
playbackState = PlayBackState.PAUSED
|
||||
@@ -172,6 +216,14 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
Log.d(TAG, "addListeners: PAUSE ${Math.round(totalPlaybackDuration/1000.0)}")
|
||||
})
|
||||
player.addListener(EventType.ERROR, VideoPlayerEvents.OnErrorListener {
|
||||
if (player.position != 0.0){
|
||||
@@ -180,26 +232,58 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
playbackState = PlayBackState.STOPPED
|
||||
binding.playerView.hide()
|
||||
binding.errorView.show()
|
||||
})
|
||||
|
||||
player.addListener(EventType.PLAYLIST_ITEM, VideoPlayerEvents.OnPlaylistItemListener {
|
||||
playingIndex = it.index
|
||||
|
||||
videoPlayList?.videoViewRequestDataList?.let {playlistData ->
|
||||
if (playingIndex >= 0 && playingIndex < playlistData.size){
|
||||
with(playlistData[playingIndex]){
|
||||
ClicksHelper.upsertClickEvent(
|
||||
contentType,
|
||||
id,
|
||||
categoryId
|
||||
)
|
||||
}
|
||||
}
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
})
|
||||
|
||||
player.addListener(EventType.SEEK, VideoPlayerEvents.OnSeekListener {
|
||||
Log.d(TAG, "addListeners: ")
|
||||
player.addListener(EventType.PLAYLIST_ITEM, VideoPlayerEvents.OnPlaylistItemListener {
|
||||
if (playingIndex != it.index){
|
||||
videoPlayList?.videoViewRequestDataList?.let {playlistData ->
|
||||
if (playingIndex >= 0 && playingIndex < playlistData.size){
|
||||
with(playlistData[playingIndex]){
|
||||
|
||||
// user video view
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
id?.let {id ->
|
||||
if (id > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
id,
|
||||
contentType.id,
|
||||
playingDurationInSecs,
|
||||
categoryId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// resetting data for new video
|
||||
totalPlaybackDuration = 0
|
||||
Log.d(TAG, "onStop: API DONE $playingDurationInSecs")
|
||||
|
||||
// clicks event
|
||||
ClicksHelper.upsertClickEvent(
|
||||
contentType,
|
||||
id,
|
||||
categoryId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
playingIndex = it.index
|
||||
})
|
||||
|
||||
(getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager).registerNetworkCallback(
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.woka.home.mylist.models.MyListResponse
|
||||
import com.woka.home.notifications.models.NotificationData
|
||||
import com.woka.networking.ApiResponse
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import okhttp3.FormBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
@@ -29,4 +30,7 @@ interface UserApiService {
|
||||
|
||||
@POST("v2/favourite_listing")
|
||||
suspend fun getMyFavList(@Body formBody: FormBody): Response<ApiResponse<MyListResponse>>
|
||||
|
||||
@POST("user_video_view")
|
||||
suspend fun userVideoView(@Body videoViewRequestData: VideoViewRequestData): Response<ApiResponse<Any>>
|
||||
}
|
||||
@@ -2,10 +2,14 @@ package com.woka.userdata
|
||||
|
||||
import com.woka.home.mylist.models.MyListResponse
|
||||
import com.woka.home.notifications.models.NotificationData
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.networking.RetrofitHelper
|
||||
import com.woka.networking.RetrofitHelper.handleApiCall
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.FormBody
|
||||
|
||||
object UserRepository {
|
||||
@@ -61,4 +65,12 @@ object UserRepository {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun userVideoView(videoViewRequestData: VideoViewRequestData){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
handleApiCall {
|
||||
userApiService.userVideoView(videoViewRequestData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.woka.userdata.userDataModels
|
||||
|
||||
data class VideoViewRequestData(
|
||||
val post_id: Int,
|
||||
val post_type: Int,
|
||||
val total_watched_duration: Long,
|
||||
val category_id: String? = null,
|
||||
val device_type: Int = 1
|
||||
)
|
||||
@@ -9,7 +9,7 @@ import com.woka.database.models.ContentType
|
||||
import com.woka.modules.categorymodels.CategoriesResponse
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.utils.PagingData
|
||||
import com.woka.webseries.WebSeriesRepository
|
||||
import com.woka.webseries.models.ContinueEpisodeResponse
|
||||
@@ -269,9 +269,10 @@ class WebSeriesViewModel : ViewModel() {
|
||||
)
|
||||
|
||||
currentPlayListHin.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
episode.id,
|
||||
ContentType.EPISODE
|
||||
ContentType.EPISODE,
|
||||
"18"
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -287,9 +288,10 @@ class WebSeriesViewModel : ViewModel() {
|
||||
)
|
||||
|
||||
currentPlayListEng.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
episode.id,
|
||||
ContentType.EPISODE
|
||||
ContentType.EPISODE,
|
||||
"1"
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -376,9 +378,10 @@ class WebSeriesViewModel : ViewModel() {
|
||||
)
|
||||
|
||||
currentPlayListHin.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
teaser.id,
|
||||
ContentType.TEASER
|
||||
ContentType.EPISODE,
|
||||
"18"
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -394,9 +397,10 @@ class WebSeriesViewModel : ViewModel() {
|
||||
)
|
||||
|
||||
currentPlayListEng.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
teaser.id,
|
||||
ContentType.TEASER
|
||||
ContentType.EPISODE,
|
||||
"1"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.woka.databinding.DialogContinueEpisodeBinding
|
||||
import com.woka.databinding.FragmentWebSeriesBinding
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_INDEX
|
||||
import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_LIST
|
||||
@@ -144,7 +144,7 @@ class WebSeriesFragment : Fragment() {
|
||||
)
|
||||
},
|
||||
mutableListOf(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
0,
|
||||
ContentType.TEASER
|
||||
)
|
||||
@@ -256,7 +256,7 @@ class WebSeriesFragment : Fragment() {
|
||||
binding.categorySpinner.setSelection(viewModel.selectedCategoryPos)
|
||||
|
||||
loadShowData()
|
||||
if (userPrefs?.userType != UserType.GUEST && !viewModel.continueWatchLiveData.isInitialized) {
|
||||
if (userPrefs?.userType != UserType.GUEST) {
|
||||
viewModel.loadContinueWatching()
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ class WebSeriesFragment : Fragment() {
|
||||
if (continueWatchList.isNotEmpty()) {
|
||||
binding.rvContinueWatch.show()
|
||||
binding.continueWatchTxt.show()
|
||||
continueWatchAdapter.submitList(continueWatchList.reversed())
|
||||
continueWatchAdapter.submitList(continueWatchList)
|
||||
} else {
|
||||
binding.rvContinueWatch.hide()
|
||||
binding.continueWatchTxt.hide()
|
||||
@@ -450,7 +450,7 @@ class WebSeriesFragment : Fragment() {
|
||||
)
|
||||
|
||||
videoPlayList.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
episodeData.id,
|
||||
ContentType.EPISODE,
|
||||
"18"
|
||||
@@ -468,7 +468,7 @@ class WebSeriesFragment : Fragment() {
|
||||
)
|
||||
|
||||
videoPlayList.videoViewRequestDataList.add(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
episodeData.id,
|
||||
ContentType.EPISODE,
|
||||
"1"
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.woka.databinding.DialogEpisodeBinding
|
||||
import com.woka.databinding.FragmentWebShowBinding
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.models.VideoViewRequestData
|
||||
import com.woka.players.models.VideoViewData
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.utils.NoSignInDialog
|
||||
@@ -285,9 +285,10 @@ class WebShowFragment : Fragment(), TabLayout.OnTabSelectedListener {
|
||||
}
|
||||
|
||||
val videoPlayList = VideoPlayList(ArrayList(), mutableListOf(
|
||||
VideoViewRequestData(
|
||||
VideoViewData(
|
||||
seasonData.id,
|
||||
ContentType.SEASON
|
||||
ContentType.EPISODE,
|
||||
categoryId
|
||||
)
|
||||
))
|
||||
videoPlayList.playlist.add(playlistItem.build())
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.woka.R
|
||||
import com.woka.database.helpers.ClicksHelper
|
||||
import com.woka.database.models.ContentType
|
||||
import com.woka.databinding.ActivityGamePlayerBinding
|
||||
import com.woka.userdata.UserRepository
|
||||
import com.woka.userdata.userDataModels.VideoViewRequestData
|
||||
import com.woka.utils.DecisionDialog
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
|
||||
@@ -30,6 +32,9 @@ class GamePlayerActivity : WokaBaseActivity() {
|
||||
|
||||
private var clicksCount = 0
|
||||
|
||||
private var playbackStartTime: Long = 0
|
||||
private var totalPlaybackDuration: Long = 0
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -64,14 +69,36 @@ class GamePlayerActivity : WokaBaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
if (playbackStartTime > 0) {
|
||||
val elapsed = System.currentTimeMillis() - playbackStartTime
|
||||
totalPlaybackDuration += elapsed
|
||||
playbackStartTime = 0
|
||||
}
|
||||
|
||||
val playingDurationInSecs = Math.round(totalPlaybackDuration/1000.0)
|
||||
|
||||
gamePlayerData?.id?.let {
|
||||
if (it > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
it,
|
||||
ContentType.GAME.id,
|
||||
playingDurationInSecs
|
||||
)
|
||||
)
|
||||
|
||||
totalPlaybackDuration = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
playbackStartTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -89,6 +116,20 @@ class GamePlayerActivity : WokaBaseActivity() {
|
||||
binding.webView.destroy()
|
||||
|
||||
ClicksHelper.upsertClickEvent(ContentType.GAME, gamePlayerData?.id, null, clicksCount)
|
||||
|
||||
val playingDurationInSecs = totalPlaybackDuration / 1000
|
||||
|
||||
gamePlayerData?.id?.let {
|
||||
if (it > 0 && playingDurationInSecs > 0) {
|
||||
UserRepository.userVideoView(
|
||||
VideoViewRequestData(
|
||||
it,
|
||||
ContentType.GAME.id,
|
||||
playingDurationInSecs
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
android:layout_height="@dimen/_20ssp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_home_bn"
|
||||
android:scaleType="fitXY"
|
||||
app:tint="@android:color/darker_gray" />
|
||||
|
||||
<TextView
|
||||
@@ -133,6 +134,7 @@
|
||||
android:layout_height="@dimen/_20ssp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_heart_filled"
|
||||
android:scaleType="fitXY"
|
||||
app:tint="@android:color/darker_gray"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user