diff --git a/app/build.gradle b/app/build.gradle index 19c2a95..af7db7e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) + id("kotlin-parcelize") } android { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 205593b..e8b75de 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,7 +17,7 @@ tools:targetApi="31"> ? = null - private var playIndex: Int = 0 + private var videoPlayList: VideoPlayList? = null + private var playingIndex: Int = 0 + + private var apiService = RetrofitHelper.getRetrofit().create(PlayerApiService::class.java) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -41,16 +56,22 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler { WindowCompat.getInsetsController(window, window.decorView) windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) - playList = intent.getParcelableArrayListExtra(EXTRA_PLAY_LIST) - playIndex = intent.getIntExtra(EXTRA_PLAY_INDEX, 0) + videoPlayList = intent.getParcelableExtra(EXTRA_PLAY_LIST) + playingIndex = intent.getIntExtra(EXTRA_PLAY_INDEX, 0) + + player = binding.playerView.getPlayer(this) setUpPlayer() } + override fun onDestroy() { + makeVideoViewApiCall(player.playlistIndex, round(player.position).toLong()) + super.onDestroy() + } + private fun setUpPlayer() { - if (playList == null) return - player = binding.playerView.getPlayer(this) + if (videoPlayList == null || videoPlayList?.playlist.isNullOrEmpty()) return player.setFullscreenHandler(this) @@ -60,11 +81,29 @@ class PlayerActivity : AppCompatActivity(), FullscreenHandler { KeepScreenOnHandler(player, window) val config = PlayerConfig.Builder() - .playlist(playList) + .playlist(videoPlayList?.playlist) .build() + + player.setup(config) - player.playlistItem(playIndex) + player.playlistItem(playingIndex) + } + + private fun makeVideoViewApiCall(playingPosition: Int, watchedDurationSeconds: Long){ + videoPlayList?.videoViewRequestDataList?.let { + if (playingPosition >= 0 && playingPosition < it.size){ + it[playingPosition].let {videoViewData -> + + if (watchedDurationSeconds > 0){ + videoViewData.total_watched_duration = "$watchedDurationSeconds" + CoroutineScope(Dispatchers.IO).launch { + apiService.userVideoView(videoViewData) + } + } + } + } + } } override fun onFullscreenRequested() {} diff --git a/app/src/main/java/com/woka/players/PlayerApiService.kt b/app/src/main/java/com/woka/players/PlayerApiService.kt new file mode 100644 index 0000000..da74cb5 --- /dev/null +++ b/app/src/main/java/com/woka/players/PlayerApiService.kt @@ -0,0 +1,14 @@ +package com.woka.players + +import com.woka.networking.ApiResponse +import com.woka.players.models.VideoViewRequestData +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.POST + +interface PlayerApiService { + + @POST("user_video_view") + suspend fun userVideoView(@Body requestData: VideoViewRequestData): Response> + +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/players/models/VideoPlayList.kt b/app/src/main/java/com/woka/players/models/VideoPlayList.kt new file mode 100644 index 0000000..e98e3bc --- /dev/null +++ b/app/src/main/java/com/woka/players/models/VideoPlayList.kt @@ -0,0 +1,11 @@ +package com.woka.players.models + +import android.os.Parcelable +import com.jwplayer.pub.api.media.playlists.PlaylistItem +import kotlinx.parcelize.Parcelize + +@Parcelize +data class VideoPlayList( + val playlist: ArrayList, + val videoViewRequestDataList: ArrayList? = null +): Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/woka/players/models/VideoViewRequestData.kt b/app/src/main/java/com/woka/players/models/VideoViewRequestData.kt new file mode 100644 index 0000000..acd55f8 --- /dev/null +++ b/app/src/main/java/com/woka/players/models/VideoViewRequestData.kt @@ -0,0 +1,12 @@ +package com.woka.players.models + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class VideoViewRequestData( + val post_id: String, + val post_type: String, + var total_watched_duration: String? = null, + val category_id: String? = null +) : Parcelable diff --git a/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt b/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt index 639a11d..ca35f1d 100644 --- a/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt +++ b/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt @@ -10,12 +10,12 @@ import com.woka.home.mylist.models.PostType import com.woka.modules.ModuleApiService import com.woka.networking.ApiResult import com.woka.networking.RetrofitHelper +import com.woka.players.models.VideoPlayList +import com.woka.players.models.VideoViewRequestData import com.woka.webseries.models.ContinueEpisodeResponse import com.woka.webseries.models.ShowData import com.woka.webseries.models.WebSeriesResponse -import com.woka.webseries.models.episodedata.EpisodeData import com.woka.webseries.models.episodedata.EpisodeResponseData -import com.woka.webseries.models.seasondata.SeasonData import com.woka.webseries.models.seasondata.SeasonDataResponse import com.woka.webseries.models.teaserdata.TeaserResponseData import kotlinx.coroutines.CoroutineScope @@ -84,7 +84,7 @@ object WebSeriesRepository { // episode data for every season. where {key -> "showId_seasonId"} private var episodeDataMap = HashMap() // episodes playlist, where {key -> "showId_seasonId_categoryId"} - var episodesPlaylistMap = HashMap>() + val episodesPlaylistMap = HashMap() // teaser listing data private val _teaserDataLiveData = MutableLiveData>() @@ -94,7 +94,7 @@ object WebSeriesRepository { // teaser data for every season. where {key -> "showId_seasonId"} private var teaserDataMap = HashMap() // teasers playlist, where {key -> "showId_seasonId_categoryId"} - var teasersPlaylistMap = HashMap>() + var teasersPlaylistMap = HashMap() fun loadTeaserData(showId: Int, seasonId: Int){ if (teaserDataMap.containsKey("${showId}_${seasonId}")){ @@ -126,15 +126,15 @@ object WebSeriesRepository { // creating a playable playlist teaserDataMap["${showId}_${seasonId}"]?.result?.filterNotNull()?.let { - val hindiPlayList = ArrayList() - val englishPlayList = ArrayList() + val videoPlayListEng = VideoPlayList(ArrayList(), ArrayList()) + val videoPlayListHin = VideoPlayList(ArrayList(), ArrayList()) for (teaser in it){ teaser.content_more_details?.let {moreDetailsList -> if (moreDetailsList.isNotEmpty()){ if (moreDetailsList.size > 1){ moreDetailsList[1]?.let {moreDetail -> - hindiPlayList.add( + videoPlayListHin.playlist.add( PlaylistItem.Builder() .file(moreDetail.content_hd_url) .title(moreDetail.title) @@ -145,7 +145,7 @@ object WebSeriesRepository { } moreDetailsList[0]?.let {moreDetail -> - englishPlayList.add( + videoPlayListEng.playlist.add( PlaylistItem.Builder() .file(moreDetail.content_hd_url) .title(moreDetail.title) @@ -157,8 +157,8 @@ object WebSeriesRepository { } } - teasersPlaylistMap["${showId}_${seasonId}_18"] = hindiPlayList - teasersPlaylistMap["${showId}_${seasonId}_1"] = englishPlayList + teasersPlaylistMap["${showId}_${seasonId}_18"] = videoPlayListHin + teasersPlaylistMap["${showId}_${seasonId}_1"] = videoPlayListEng } } } @@ -195,39 +195,58 @@ object WebSeriesRepository { // creating a playable playlist episodeDataMap["${showId}_${seasonId}"]?.result?.filterNotNull()?.let { - val hindiPlayList = ArrayList() - val englishPlayList = ArrayList() + + val videoPlayListItemHin = VideoPlayList(ArrayList(), ArrayList()) + val videoPlayListItemEng = VideoPlayList(ArrayList(), ArrayList()) for (episode in it){ episode.content_more_details?.let {moreDetailsList -> if (moreDetailsList.isNotEmpty()){ if (moreDetailsList.size > 1){ moreDetailsList[1]?.let {moreDetail -> - hindiPlayList.add( + videoPlayListItemHin.playlist.add( PlaylistItem.Builder() .file(moreDetail.content_hd_url) .title(moreDetail.title) .image(episode.thumbnail_path) .build() ) + + videoPlayListItemHin.videoViewRequestDataList?.add( + VideoViewRequestData( + post_id = "${episode.id}", + post_type = "3", + total_watched_duration = null, + category_id = "18" + ) + ) } } moreDetailsList[0]?.let {moreDetail -> - englishPlayList.add( + videoPlayListItemEng.playlist.add( PlaylistItem.Builder() .file(moreDetail.content_hd_url) .title(moreDetail.title) .image(episode.thumbnail_path) .build() ) + + videoPlayListItemEng.videoViewRequestDataList?.add( + VideoViewRequestData( + post_id = "${episode.id}", + post_type = "3", + total_watched_duration = null, + category_id = "1" + ) + ) } } } } - episodesPlaylistMap["${showId}_${seasonId}_18"] = hindiPlayList - episodesPlaylistMap["${showId}_${seasonId}_1"] = englishPlayList + episodesPlaylistMap["${showId}_${seasonId}_18"] = videoPlayListItemHin + episodesPlaylistMap["${showId}_${seasonId}_1"] = videoPlayListItemEng } } } diff --git a/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt b/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt index f9b2001..890ed8d 100644 --- a/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt +++ b/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt @@ -24,6 +24,8 @@ import com.woka.networking.ApiResult import com.woka.players.PlayerActivity import com.woka.players.PlayerActivity.Companion.EXTRA_PLAY_INDEX import com.woka.players.PlayerActivity.Companion.EXTRA_PLAY_LIST +import com.woka.players.models.VideoPlayList +import com.woka.players.models.VideoViewRequestData import com.woka.utils.ProgressView import com.woka.utils.WokaBaseActivity import com.woka.utils.hide @@ -105,10 +107,10 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { } } - if (showData == null){ + if (showData == null) { MyListRepository.myFavData.result?.show_data?.let { - for (show in it){ - if (showId == show.id){ + for (show in it) { + if (showId == show.id) { showData = ShowData(show) break } @@ -158,8 +160,7 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { } - - private fun initEpisodeDialog(){ + private fun initEpisodeDialog() { episodeDialogBinding = DialogEpisodeBinding.inflate(layoutInflater) episodeDialog = Dialog(this) @@ -252,32 +253,40 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { if (seasonsTab.selectedTabPosition >= 0) { WebSeriesRepository.seasonDataMap["${showId}_${categoryId}"]?.result?.let { seasonList -> if (seasonsTab.selectedTabPosition < seasonList.size) { - seasonList[seasonsTab.selectedTabPosition]?.season_more_details?.let {moreDetailsList -> - if (moreDetailsList.isNotEmpty()){ - val playlistItem = PlaylistItem.Builder() + seasonList[seasonsTab.selectedTabPosition]?.let { seasonData -> - if (categoryId == "18" && moreDetailsList.size > 1){ - moreDetailsList[1]?.let {seasonData -> - playlistItem.title(seasonData.title) - playlistItem.image(seasonData.trailer_hd_url) - playlistItem.file(seasonData.trailer_hd_url) - } - }else{ - moreDetailsList[0]?.let {seasonData -> - playlistItem.title(seasonData.title) - playlistItem.image(seasonData.trailer_hd_url) - playlistItem.file(seasonData.trailer_hd_url) - } - } + seasonData.season_more_details?.let { moreDetailsList -> + if (moreDetailsList.isNotEmpty()) { + val videoPlayList = VideoPlayList(ArrayList()) - startActivity( - Intent(this@SeasonActivity, PlayerActivity::class.java) - .apply { - putParcelableArrayListExtra(EXTRA_PLAY_LIST, ArrayList().apply { - add(playlistItem.build()) - }) + val playlistItem = PlaylistItem.Builder() + + if (categoryId == "18" && moreDetailsList.size > 1) { + moreDetailsList[1]?.let { seasonMoreData -> + playlistItem.title(seasonMoreData.title) + playlistItem.image(seasonMoreData.trailer_hd_url) + playlistItem.file(seasonMoreData.trailer_hd_url) } - ) + } else { + moreDetailsList[0]?.let { seasonMoreData -> + playlistItem.title(seasonMoreData.title) + playlistItem.image(seasonMoreData.trailer_hd_url) + playlistItem.file(seasonMoreData.trailer_hd_url) + } + } + + videoPlayList.playlist.add(playlistItem.build()) + + startActivity( + Intent(this@SeasonActivity, PlayerActivity::class.java) + .apply { + putExtra( + EXTRA_PLAY_LIST, + videoPlayList + ) + } + ) + } } } } @@ -438,16 +447,16 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { private fun onEpisodeClicked(position: Int, episodeData: EpisodeData) { episodeDialogBinding.apply { - episodeData.content_more_details?.let {moreDetailsList -> + episodeData.content_more_details?.let { moreDetailsList -> episodeData.thumbnail_path?.let { image.loadImage(it) } - if (moreDetailsList.isNotEmpty()){ + if (moreDetailsList.isNotEmpty()) { - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ - moreDetailsList[1]?.let {data -> + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + moreDetailsList[1]?.let { data -> title.text = data.title description.text = Html.fromHtml( data.description?.replace( @@ -455,12 +464,13 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { " " ), Html.FROM_HTML_MODE_LEGACY ) - val mediaType = "${getString(R.string.episode)} ${episodeData.episode_number}" + val mediaType = + "${getString(R.string.episode)} ${episodeData.episode_number}" mediaTypeNumber.text = mediaType duration.text = episodeData.episode_duration } - }else{ - moreDetailsList[0]?.let {data -> + } else { + moreDetailsList[0]?.let { data -> title.text = data.title description.text = Html.fromHtml( data.description?.replace( @@ -468,12 +478,13 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { " " ), Html.FROM_HTML_MODE_LEGACY ) - val mediaType = "${getString(R.string.episode)} ${episodeData.episode_number}" + val mediaType = + "${getString(R.string.episode)} ${episodeData.episode_number}" mediaTypeNumber.text = mediaType duration.text = episodeData.episode_duration } } - }else{ + } else { title.text = episodeData.episode_title description.text = Html.fromHtml( episodeData.episode_description?.replace( @@ -501,7 +512,7 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { private fun onEpisodePlayClicked(position: Int) { startActivity(Intent(this, PlayerActivity::class.java).apply { - putParcelableArrayListExtra( + putExtra( EXTRA_PLAY_LIST, WebSeriesRepository.episodesPlaylistMap["${showId}_${selectedSeasonId}_$categoryId"] ) @@ -511,16 +522,16 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { private fun onTeaserClicked(position: Int, teaserData: TeaserData) { episodeDialogBinding.apply { - teaserData.content_more_details?.let {moreDetailsList -> + teaserData.content_more_details?.let { moreDetailsList -> teaserData.thumbnail_path?.let { image.loadImage(it) } - if (moreDetailsList.isNotEmpty()){ + if (moreDetailsList.isNotEmpty()) { - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ - moreDetailsList[1]?.let {data -> + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + moreDetailsList[1]?.let { data -> title.text = data.title description.text = Html.fromHtml( data.description?.replace( @@ -528,12 +539,13 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { " " ), Html.FROM_HTML_MODE_LEGACY ) - val mediaType = "${getString(R.string.teasers)} ${teaserData.teaser_number}" + val mediaType = + "${getString(R.string.teasers)} ${teaserData.teaser_number}" mediaTypeNumber.text = mediaType duration.text = teaserData.teaser_duration } - }else{ - moreDetailsList[0]?.let {data -> + } else { + moreDetailsList[0]?.let { data -> title.text = data.title description.text = Html.fromHtml( data.description?.replace( @@ -541,12 +553,13 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { " " ), Html.FROM_HTML_MODE_LEGACY ) - val mediaType = "${getString(R.string.teasers)} ${teaserData.teaser_number}" + val mediaType = + "${getString(R.string.teasers)} ${teaserData.teaser_number}" mediaTypeNumber.text = mediaType duration.text = teaserData.teaser_duration } } - }else{ + } else { title.text = teaserData.teaser_title description.text = Html.fromHtml( teaserData.teaser_description?.replace( @@ -574,7 +587,7 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { private fun onTeaserPlayClicked(position: Int) { startActivity(Intent(this, PlayerActivity::class.java).apply { - putParcelableArrayListExtra( + putExtra( EXTRA_PLAY_LIST, WebSeriesRepository.teasersPlaylistMap["${showId}_${selectedSeasonId}_$categoryId"] ) diff --git a/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt b/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt index 5f143d5..c033409 100644 --- a/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt +++ b/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt @@ -33,6 +33,8 @@ import com.woka.networking.ApiResult import com.woka.players.PlayerActivity import com.woka.players.PlayerActivity.Companion.EXTRA_PLAY_INDEX import com.woka.players.PlayerActivity.Companion.EXTRA_PLAY_LIST +import com.woka.players.models.VideoPlayList +import com.woka.players.models.VideoViewRequestData import com.woka.utils.WokaBaseActivity import com.woka.utils.hide import com.woka.utils.show @@ -340,35 +342,50 @@ class WebSeriesActivity : WokaBaseActivity(), Observer - val playlist = ArrayList() - playlist.add( - if (moreDetailsList.isNotEmpty()){ - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ + episodeData.content_more_details.let {moreDetailsList -> + val videoPlayList = VideoPlayList(ArrayList(), ArrayList()) + + if (moreDetailsList.isNotEmpty()){ + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ + videoPlayList.playlist.add( PlaylistItem.Builder() .file(moreDetailsList[1].content_hd_url) .title(moreDetailsList[1].title) .image(moreDetailsList[1].content_hd_url) .build() - }else{ + ) + + videoPlayList.videoViewRequestDataList?.add( + VideoViewRequestData( + "${episodeData.id}", + "3", + null, + category_id = "18" + ) + ) + }else{ + videoPlayList.playlist.add( PlaylistItem.Builder() .file(moreDetailsList[0].content_hd_url) .title(moreDetailsList[0].title) .image(moreDetailsList[0].content_hd_url) .build() - } - }else{ - PlaylistItem.Builder() - .file(episodeData.episode_url) - .title(episodeData.episode_title) - .image(episodeData.episode_url) - .build() + ) + + videoPlayList.videoViewRequestDataList?.add( + VideoViewRequestData( + "${episodeData.id}", + "3", + null, + "1" + ) + ) } - ) + } startActivity(Intent(this@WebSeriesActivity, PlayerActivity::class.java) .apply { - putParcelableArrayListExtra(EXTRA_PLAY_LIST, playlist) + putExtra(EXTRA_PLAY_LIST, videoPlayList) putExtra(EXTRA_PLAY_INDEX, 0) }) }