This commit is contained in:
2024-06-28 22:44:03 +05:30
parent 9d38928884
commit c50cf3d29e
9 changed files with 216 additions and 90 deletions

View File

@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id("kotlin-parcelize")
}
android {

View File

@@ -17,7 +17,7 @@
tools:targetApi="31">
<activity
android:name=".players.PlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="sensorLandscape"

View File

@@ -1,30 +1,45 @@
package com.woka.players
import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.google.common.base.Stopwatch
import com.jwplayer.pub.api.JWPlayer
import com.jwplayer.pub.api.configuration.PlayerConfig
import com.jwplayer.pub.api.events.EventType
import com.jwplayer.pub.api.events.listeners.VideoPlayerEvents
import com.jwplayer.pub.api.fullscreen.FullscreenHandler
import com.jwplayer.pub.api.media.playlists.PlaylistItem
import com.woka.databinding.ActivityPlayerBinding
import com.woka.networking.RetrofitHelper
import com.woka.players.models.VideoPlayList
import com.woka.utils.TAG
import com.woka.utils.formatTime
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.math.round
class PlayerActivity : AppCompatActivity(), FullscreenHandler {
companion object{
const val EXTRA_PLAY_LIST = "episode_key"
const val EXTRA_PLAY_INDEX = "episode_index"
const val EXTRA_PLAY_LIST = "player_play_list"
const val EXTRA_PLAY_INDEX = "playing_index"
}
private lateinit var binding: ActivityPlayerBinding
private lateinit var player: JWPlayer
private var playList: List<PlaylistItem>? = 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() {}

View File

@@ -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<ApiResponse<Any>>
}

View File

@@ -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<PlaylistItem>,
val videoViewRequestDataList: ArrayList<VideoViewRequestData>? = null
): Parcelable

View File

@@ -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

View File

@@ -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<String, EpisodeResponseData>()
// episodes playlist, where {key -> "showId_seasonId_categoryId"}
var episodesPlaylistMap = HashMap<String, ArrayList<PlaylistItem>>()
val episodesPlaylistMap = HashMap<String, VideoPlayList>()
// teaser listing data
private val _teaserDataLiveData = MutableLiveData<ApiResult<TeaserResponseData>>()
@@ -94,7 +94,7 @@ object WebSeriesRepository {
// teaser data for every season. where {key -> "showId_seasonId"}
private var teaserDataMap = HashMap<String, TeaserResponseData>()
// teasers playlist, where {key -> "showId_seasonId_categoryId"}
var teasersPlaylistMap = HashMap<String, ArrayList<PlaylistItem>>()
var teasersPlaylistMap = HashMap<String, VideoPlayList>()
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<PlaylistItem>()
val englishPlayList = ArrayList<PlaylistItem>()
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<PlaylistItem>()
val englishPlayList = ArrayList<PlaylistItem>()
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
}
}
}

View File

@@ -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<Parcelable?>().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"]
)

View File

@@ -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<ApiResult<HashMap<String,
}
watchCard.setOnClickListener {
episodeData.content_more_details.let {moreDetailsList->
val playlist = ArrayList<PlaylistItem>()
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)
})
}