Resolved migration problem with app-inspection of room database.
implement upsert transaction for ClickEvent Verified database with debugging. Implemented for live tv and fm. live_streaming api integration and caching with singleton. Implemented online url at all places of fm and live stream.
This commit is contained in:
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import com.jwplayer.pub.api.license.LicenseUtil
|
||||
import com.woka.database.AppDatabase
|
||||
import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.userPreference.UserPreference
|
||||
|
||||
class WokaApp: Application() {
|
||||
@@ -20,5 +21,7 @@ class WokaApp: Application() {
|
||||
LicenseUtil().setLicenseKey(this, "LkYoNusv+gSIVJIrXa5Bf59iBNlUMxeg82PM/l8JWk+cD4BE")
|
||||
|
||||
appDatabase = AppDatabase.getInstance(applicationContext)
|
||||
|
||||
StreamingUrlRepository.loadLiveStreamingUrls()
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,9 @@ abstract class AppDatabase : RoomDatabase(){
|
||||
Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
AppDatabase::class.java, DATABASE_NAME
|
||||
).build()
|
||||
)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
|
||||
abstract fun clicksDao(): ClicksDao
|
||||
|
||||
@@ -1,12 +1,43 @@
|
||||
package com.woka.database.dao
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import com.woka.database.models.clicks.ClickEvent
|
||||
import com.woka.database.models.clicks.ContentType
|
||||
import com.woka.utils.TAG
|
||||
|
||||
/*
|
||||
clickId will always in the following format
|
||||
${post_type}_${post_id}_${category_id}
|
||||
*/
|
||||
|
||||
@Dao
|
||||
interface ClicksDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun addClickEvent(vararg clickEvent: ClickEvent)
|
||||
|
||||
@Query("UPDATE click_events SET clicks_count = clicks_count + 1 WHERE id = :clickId")
|
||||
suspend fun updateAndGetRowCount(clickId: String): Int
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(vararg clickEvent: ClickEvent)
|
||||
|
||||
@Transaction
|
||||
suspend fun upsertClickEvent(contentType: ContentType, postId: Int = 0, categoryId: Int = 0){
|
||||
val clickId = "${contentType.id}_${postId}_${categoryId}"
|
||||
|
||||
val count = updateAndGetRowCount(clickId)
|
||||
if (count == 0){
|
||||
insert(
|
||||
ClickEvent(
|
||||
clickId,
|
||||
postId,
|
||||
contentType.id,
|
||||
categoryId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
18
app/src/main/java/com/woka/database/helpers/ClicksHelper.kt
Normal file
18
app/src/main/java/com/woka/database/helpers/ClicksHelper.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.woka.database.helpers
|
||||
|
||||
import com.woka.WokaApp.Companion.appDatabase
|
||||
import com.woka.database.dao.ClicksDao
|
||||
import com.woka.database.models.clicks.ContentType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
object ClicksHelper {
|
||||
private val clicksDao: ClicksDao? = appDatabase?.clicksDao()
|
||||
|
||||
fun upsertClickEvent(contentType: ContentType, postId: Int = 0, categoryId: Int = 0){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
clicksDao?.upsertClickEvent(contentType, postId, categoryId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ private const val DB_TABLE_NAME = "click_events"
|
||||
|
||||
@Entity(tableName = DB_TABLE_NAME)
|
||||
data class ClickEvent(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "id") val clickId: Int = 0,
|
||||
@ColumnInfo(name = "post_id") val postId: String,
|
||||
@ColumnInfo(name = "post_type") val postType: String,
|
||||
@ColumnInfo(name = "categoryId") val categoryId: String?,
|
||||
@ColumnInfo(name = "clicks_count") val clickCount: Int,
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "id") val clickId: String,
|
||||
@ColumnInfo(name = "post_id") val postId: Int,
|
||||
@ColumnInfo(name = "post_type") val postType: Int,
|
||||
@ColumnInfo(name = "categoryId") val categoryId: Int,
|
||||
@ColumnInfo(name = "clicks_count") val clickCount: Int = 1,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.woka.database.models.clicks
|
||||
|
||||
enum class ContentType(val id: Int) {
|
||||
SERIES(1),
|
||||
SEASON(2),
|
||||
EPISODE(3),
|
||||
VIDEO(4),
|
||||
PAINT(5),
|
||||
GAME(6),
|
||||
AUDIO(7),
|
||||
KARAOKE_VIDEO(8),
|
||||
SHOP_PRODUCT(9),
|
||||
PARENTAL_VIDEO(10),
|
||||
ARTICLE(11),
|
||||
LIVE_TV(12),
|
||||
FM(13),
|
||||
TEASER(14),
|
||||
OTHERS(15),
|
||||
HOME(16)
|
||||
}
|
||||
@@ -16,15 +16,10 @@ import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.Player.Listener
|
||||
import com.bumptech.glide.Glide
|
||||
import com.woka.R
|
||||
import com.woka.WokaApp
|
||||
import com.woka.WokaApp.Companion.appDatabase
|
||||
import com.woka.WokaApp.Companion.userPrefs
|
||||
import com.woka.audiobooks.views.AudioBooksActivity
|
||||
import com.woka.database.models.clicks.ClickEvent
|
||||
import com.woka.databinding.FragmentHome1Binding
|
||||
import com.woka.home.models.TimePeriod
|
||||
import com.woka.home.viewmodels.HomeViewModel
|
||||
@@ -34,19 +29,18 @@ import com.woka.karaoke.views.KaraokeActivity
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.views.LiveStreamPlayerActivity
|
||||
import com.woka.shop.views.ShopActivity
|
||||
import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.utils.ProgressView
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.scaleAnimate
|
||||
import com.woka.utils.show
|
||||
import com.woka.webseries.views.WebSeriesActivity
|
||||
import com.woka.wokagames.views.GamesActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class Home1Fragment : Fragment(), Listener {
|
||||
class Home1Fragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentHome1Binding
|
||||
private lateinit var viewModel: HomeViewModel
|
||||
@@ -60,14 +54,15 @@ class Home1Fragment : Fragment(), Listener {
|
||||
private var star1Animator: ValueAnimator? = null
|
||||
private var star2Animator: ValueAnimator? = null
|
||||
|
||||
private lateinit var progressView: ProgressView
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentHome1Binding.inflate(inflater, container, false)
|
||||
activity?.let {
|
||||
viewModel = ViewModelProvider(it)[HomeViewModel::class.java]
|
||||
}
|
||||
viewModel = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
|
||||
progressView = ProgressView(requireContext())
|
||||
|
||||
initViews()
|
||||
|
||||
@@ -116,11 +111,9 @@ class Home1Fragment : Fragment(), Listener {
|
||||
binding.playerView.hide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initPlayerView() {
|
||||
binding.playerView.player = viewModel.player
|
||||
binding.playerView.useController = false
|
||||
viewModel.player?.addListener(this)
|
||||
}
|
||||
|
||||
private fun setObservers() {
|
||||
@@ -154,15 +147,64 @@ class Home1Fragment : Fragment(), Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activity?.registerReceiver(minuteReceiver, IntentFilter(ACTION_TIME_TICK))
|
||||
|
||||
viewModel.playerReadyCallback = {
|
||||
initPlayerView()
|
||||
}
|
||||
|
||||
StreamingUrlRepository.liveStreamLiveData.observe(viewLifecycleOwner){
|
||||
when (it){
|
||||
is ApiResult.Error -> {
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
StreamingUrlRepository.loadLiveStreamingUrls()
|
||||
}
|
||||
}
|
||||
is ApiResult.Loading -> {
|
||||
progressView.show()
|
||||
}
|
||||
is ApiResult.Success -> {
|
||||
it.data?.live_data?.let {urls ->
|
||||
if (urls.isNotEmpty()){
|
||||
urls.first()?.let {liveData ->
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
activity?.let {activity ->
|
||||
startActivity(Intent(activity, LiveStreamPlayerActivity::class.java).apply {
|
||||
putExtra(
|
||||
LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_ID,
|
||||
liveData.id
|
||||
)
|
||||
putExtra(LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_URL,
|
||||
liveData.live_url?.hd_url_en)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.data?.live_fm_data?.let {fmData ->
|
||||
binding.fmButton.setOnClickListener {
|
||||
activity?.let {activity ->
|
||||
startActivity(Intent(activity, FMActivity::class.java).apply {
|
||||
putExtra(FMActivity.EXTRA_FM_URL, fmData.live_fm_url)
|
||||
putExtra(FMActivity.EXTRA_FM_ID, fmData.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clickEvents() {
|
||||
binding.apply {
|
||||
blackImage.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, LiveStreamPlayerActivity::class.java))
|
||||
}
|
||||
liveTv.performClick()
|
||||
}
|
||||
|
||||
more.setOnClickListener {
|
||||
@@ -174,33 +216,9 @@ class Home1Fragment : Fragment(), Listener {
|
||||
}
|
||||
}
|
||||
|
||||
fmButton.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, FMActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
liveTv.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, LiveStreamPlayerActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
webSeries.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, WebSeriesActivity::class.java))
|
||||
lifecycleScope.launch {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
appDatabase?.clicksDao()?.addClickEvent(
|
||||
ClickEvent(
|
||||
postId = "2",
|
||||
postType = "3",
|
||||
categoryId = "1",
|
||||
clickCount = 1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +251,6 @@ class Home1Fragment : Fragment(), Listener {
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
activity?.unregisterReceiver(minuteReceiver)
|
||||
viewModel.player?.removeListener(this)
|
||||
}
|
||||
|
||||
private fun updateUserData(data: UserDataResponse?) {
|
||||
|
||||
@@ -20,8 +20,10 @@ import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.views.LiveStreamPlayerActivity
|
||||
import com.woka.players.views.PlayerActivity
|
||||
import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.utils.ProgressView
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.show
|
||||
import com.woka.webseries.views.WebSeriesActivity
|
||||
@@ -33,15 +35,16 @@ class Home2Fragment : Fragment() {
|
||||
|
||||
private lateinit var viewModel: HomeViewModel
|
||||
|
||||
private lateinit var progressView: ProgressView
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentHome2Binding.inflate(inflater, container, false)
|
||||
|
||||
activity?.let {
|
||||
viewModel = ViewModelProvider(it)[HomeViewModel::class.java]
|
||||
}
|
||||
viewModel = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
|
||||
progressView = ProgressView(requireContext())
|
||||
|
||||
iniViews()
|
||||
|
||||
@@ -88,21 +91,7 @@ class Home2Fragment : Fragment() {
|
||||
private fun clickEvents(){
|
||||
binding.apply {
|
||||
playerCard.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, LiveStreamPlayerActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
liveTv.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, LiveStreamPlayerActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
wokaFm.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, FMActivity::class.java))
|
||||
}
|
||||
liveTv.performClick()
|
||||
}
|
||||
|
||||
webSeries.setOnClickListener {
|
||||
@@ -181,6 +170,52 @@ class Home2Fragment : Fragment() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.playerReadyCallback = {
|
||||
initPlayerView()
|
||||
}
|
||||
|
||||
StreamingUrlRepository.liveStreamLiveData.observe(viewLifecycleOwner){
|
||||
when (it){
|
||||
is ApiResult.Error -> {
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
StreamingUrlRepository.loadLiveStreamingUrls()
|
||||
}
|
||||
}
|
||||
is ApiResult.Loading -> {
|
||||
progressView.show()
|
||||
}
|
||||
is ApiResult.Success -> {
|
||||
it.data?.live_data?.let {urls ->
|
||||
if (urls.isNotEmpty()){
|
||||
urls.first()?.let {liveData ->
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
activity?.let {activity ->
|
||||
startActivity(Intent(activity, LiveStreamPlayerActivity::class.java).apply {
|
||||
putExtra(LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_ID, liveData.id)
|
||||
putExtra(LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_URL, liveData.live_url?.hd_url_en)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.data?.live_fm_data?.let {fmData ->
|
||||
binding.wokaFm.setOnClickListener {
|
||||
activity?.let {activity ->
|
||||
startActivity(Intent(activity, FMActivity::class.java).apply {
|
||||
putExtra(FMActivity.EXTRA_FM_URL, fmData.live_fm_url)
|
||||
putExtra(FMActivity.EXTRA_FM_ID, fmData.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUserData(data: UserDataResponse?) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Player.Listener
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.woka.home.views.BottomNavigation.Companion.HOME
|
||||
import com.woka.networking.ApiResult
|
||||
@@ -30,14 +31,34 @@ class HomeViewModel : ViewModel() {
|
||||
val deActivateLiveData: LiveData<ApiResult<Any>?>
|
||||
get() = _deActivateLiveData
|
||||
|
||||
var playerReadyCallback: (() -> Unit)? = null
|
||||
|
||||
var player: Player? = null
|
||||
|
||||
fun initPlayer(context: Context) {
|
||||
fun initPlayer(context: Context, liveUrl: String) {
|
||||
player = ExoPlayer.Builder(context).build()
|
||||
|
||||
player?.volume = 0f
|
||||
|
||||
player?.setMediaItem(MediaItem.fromUri("https://d3volyx7jx7oal.cloudfront.net/master.m3u8"))
|
||||
player?.addListener(object : Listener{
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
super.onPlaybackStateChanged(playbackState)
|
||||
when (playbackState){
|
||||
|
||||
Player.STATE_BUFFERING -> {}
|
||||
|
||||
Player.STATE_ENDED -> {}
|
||||
|
||||
Player.STATE_IDLE -> {}
|
||||
|
||||
Player.STATE_READY -> {
|
||||
playerReadyCallback?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
player?.setMediaItem(MediaItem.fromUri(liveUrl))
|
||||
player?.playWhenReady = true
|
||||
player?.prepare()
|
||||
}
|
||||
|
||||
@@ -14,8 +14,11 @@ import com.woka.audiobooks.views.AudioBooksActivity
|
||||
import com.woka.databinding.ActivityExploreWokaBinding
|
||||
import com.woka.karaoke.views.KaraokeActivity
|
||||
import com.woka.modules.blogs.view.BlogsActivity
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.views.LiveStreamPlayerActivity
|
||||
import com.woka.shop.views.ShopActivity
|
||||
import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.utils.ProgressView
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.lightStatusBar
|
||||
import com.woka.webseries.views.WebSeriesActivity
|
||||
@@ -25,6 +28,8 @@ class ExploreWokaActivity : WokaBaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivityExploreWokaBinding
|
||||
|
||||
private lateinit var progressView: ProgressView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
with(window){
|
||||
@@ -42,11 +47,15 @@ class ExploreWokaActivity : WokaBaseActivity() {
|
||||
insets
|
||||
}
|
||||
|
||||
progressView = ProgressView(this)
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S){
|
||||
binding.root.setBackgroundColor(ContextCompat.getColor(this, R.color.black_50))
|
||||
}
|
||||
|
||||
clickEvents()
|
||||
|
||||
setObservers()
|
||||
}
|
||||
|
||||
private fun clickEvents() {
|
||||
@@ -59,14 +68,6 @@ class ExploreWokaActivity : WokaBaseActivity() {
|
||||
finish()
|
||||
}
|
||||
|
||||
liveTv.setOnClickListener {
|
||||
startActivity(Intent(this@ExploreWokaActivity, LiveStreamPlayerActivity::class.java))
|
||||
}
|
||||
|
||||
wokaFm.setOnClickListener {
|
||||
startActivity(Intent(this@ExploreWokaActivity, FMActivity::class.java))
|
||||
}
|
||||
|
||||
webSeries.setOnClickListener {
|
||||
startActivity(Intent(this@ExploreWokaActivity, WebSeriesActivity::class.java))
|
||||
}
|
||||
@@ -93,4 +94,44 @@ class ExploreWokaActivity : WokaBaseActivity() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun setObservers(){
|
||||
StreamingUrlRepository.liveStreamLiveData.observe(this){
|
||||
when (it){
|
||||
is ApiResult.Error -> {
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
StreamingUrlRepository.loadLiveStreamingUrls()
|
||||
}
|
||||
}
|
||||
is ApiResult.Loading -> {
|
||||
progressView.show()
|
||||
}
|
||||
is ApiResult.Success -> {
|
||||
it.data?.live_data?.let {urls ->
|
||||
if (urls.isNotEmpty()){
|
||||
urls.first()?.let {liveData ->
|
||||
progressView.hide()
|
||||
binding.liveTv.setOnClickListener {
|
||||
startActivity(Intent(this, LiveStreamPlayerActivity::class.java).apply {
|
||||
putExtra(LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_ID, liveData.id)
|
||||
putExtra(LiveStreamPlayerActivity.EXTRA_LIVE_STREAM_URL, liveData.live_url?.hd_url_en)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.data?.live_fm_data?.let {fmData ->
|
||||
binding.wokaFm.setOnClickListener {
|
||||
startActivity(Intent(this, FMActivity::class.java).apply {
|
||||
putExtra(FMActivity.EXTRA_FM_URL, fmData.live_fm_url)
|
||||
putExtra(FMActivity.EXTRA_FM_ID, fmData.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,29 +8,36 @@ import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.woka.R
|
||||
import com.woka.database.helpers.ClicksHelper
|
||||
import com.woka.database.models.clicks.ContentType
|
||||
import com.woka.databinding.ActivityFmactivityBinding
|
||||
import com.woka.utils.TAG
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.show
|
||||
import com.woka.utils.toast
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.round
|
||||
|
||||
class FMActivity : WokaBaseActivity() {
|
||||
|
||||
companion object {
|
||||
private const val FM_URL = "https://stream.rcast.net/71643"
|
||||
const val EXTRA_FM_URL = "extra_fm_url"
|
||||
const val EXTRA_FM_ID = "extra_fm_id"
|
||||
private const val VOLUME_STEP = 0.2f
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityFmactivityBinding
|
||||
private lateinit var player: ExoPlayer
|
||||
|
||||
private var fmUrl: String = ""
|
||||
private var fmId: Int = -1
|
||||
|
||||
private val clickHelper = ClicksHelper
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -45,6 +52,15 @@ class FMActivity : WokaBaseActivity() {
|
||||
|
||||
window.navigationBarColor = Color.BLACK
|
||||
|
||||
intent.getStringExtra(EXTRA_FM_URL)?.let {
|
||||
fmUrl = it
|
||||
}
|
||||
|
||||
fmId = intent.getIntExtra(EXTRA_FM_ID, -1)
|
||||
upsertClickEvent()
|
||||
|
||||
Log.d(TAG, "onCreate: $fmUrl $fmId")
|
||||
|
||||
player = ExoPlayer.Builder(this).build()
|
||||
|
||||
initPlayer()
|
||||
@@ -58,13 +74,16 @@ class FMActivity : WokaBaseActivity() {
|
||||
super.onDestroy()
|
||||
player.stop()
|
||||
player.release()
|
||||
|
||||
upsertClickEvent()
|
||||
}
|
||||
|
||||
private fun initPlayer() {
|
||||
binding.retryBtn.hide()
|
||||
binding.playBtn.hide()
|
||||
binding.progressBar.show()
|
||||
|
||||
player.setMediaItem(MediaItem.fromUri(FM_URL))
|
||||
player.setMediaItem(MediaItem.fromUri(fmUrl))
|
||||
player.playWhenReady = true
|
||||
player.volume = 0.6f
|
||||
player.prepare()
|
||||
@@ -81,6 +100,8 @@ class FMActivity : WokaBaseActivity() {
|
||||
playBtn.setOnClickListener {
|
||||
if (player.isPlaying) player.pause()
|
||||
else player.play()
|
||||
|
||||
upsertClickEvent()
|
||||
}
|
||||
|
||||
volumeDown.setOnClickListener {
|
||||
@@ -91,6 +112,8 @@ class FMActivity : WokaBaseActivity() {
|
||||
player.volume = max(0.0f, player.volume - VOLUME_STEP)
|
||||
|
||||
updateVolumeButtons()
|
||||
|
||||
upsertClickEvent()
|
||||
}
|
||||
|
||||
volumeUp.setOnClickListener {
|
||||
@@ -101,14 +124,32 @@ class FMActivity : WokaBaseActivity() {
|
||||
player.volume = min(1.0f, player.volume + VOLUME_STEP)
|
||||
|
||||
updateVolumeButtons()
|
||||
|
||||
upsertClickEvent()
|
||||
}
|
||||
|
||||
retryBtn.setOnClickListener {
|
||||
initPlayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun upsertClickEvent(){
|
||||
if (fmId == -1) return
|
||||
|
||||
clickHelper.upsertClickEvent(
|
||||
ContentType.FM,
|
||||
fmId,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
private fun setObservers() {
|
||||
player.addListener(object : Player.Listener {
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
super.onIsPlayingChanged(isPlaying)
|
||||
binding.retryBtn.hide()
|
||||
binding.progressBar.hide()
|
||||
binding.playBtn.show()
|
||||
|
||||
binding.playBtn.setImageResource(
|
||||
@@ -119,6 +160,13 @@ class FMActivity : WokaBaseActivity() {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
super.onPlayerError(error)
|
||||
binding.playBtn.hide()
|
||||
binding.retryBtn.show()
|
||||
binding.progressBar.hide()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import com.woka.onboard.views.OnboardActivity.Companion.ADD_CHILD_INTENT
|
||||
import com.woka.onboard.views.OnboardActivity.Companion.LOG_IN_INTENT
|
||||
import com.woka.onboard.views.OnboardActivity.Companion.ONBOARD_ACTIVITY_INTENT
|
||||
import com.woka.shop.views.MyOrdersActivity
|
||||
import com.woka.streamingurls.StreamingUrlRepository
|
||||
import com.woka.userPreference.UserType
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.utils.DecisionDialog
|
||||
@@ -108,8 +109,6 @@ class HomeActivity : WokaBaseActivity(),
|
||||
if (userPrefs?.userLiveData?.isInitialized == false){
|
||||
userPrefs?.loadUserData()
|
||||
}
|
||||
|
||||
viewModel.initPlayer(applicationContext)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -203,6 +202,26 @@ class HomeActivity : WokaBaseActivity(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StreamingUrlRepository.liveStreamLiveData.observe(this){
|
||||
when (it){
|
||||
is ApiResult.Error -> {
|
||||
progressView.hide()
|
||||
toast(it.errorMessage)
|
||||
}
|
||||
is ApiResult.Loading -> {progressView.show()}
|
||||
is ApiResult.Success -> {
|
||||
progressView.hide()
|
||||
it.data?.live_data?.let {urls ->
|
||||
if (urls.isNotEmpty()){
|
||||
urls.first()?.live_url?.hd_url_en?.let {liveUrl ->
|
||||
viewModel.initPlayer(applicationContext, liveUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
@@ -495,7 +514,11 @@ class HomeActivity : WokaBaseActivity(),
|
||||
, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
|
||||
}
|
||||
MY_LIST -> {
|
||||
unregisterReceiver(minuteReceiver)
|
||||
try {
|
||||
unregisterReceiver(minuteReceiver)
|
||||
}catch (e: Exception){
|
||||
// do nothing
|
||||
}
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fc_home, MyListFragment.getInstance())
|
||||
|
||||
@@ -17,6 +17,8 @@ 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.database.helpers.ClicksHelper
|
||||
import com.woka.database.models.clicks.ContentType
|
||||
import com.woka.databinding.ActivityLiveStreamPlayerBinding
|
||||
import com.woka.players.KeepScreenOnHandler
|
||||
import com.woka.players.models.PlayBackState
|
||||
@@ -25,6 +27,11 @@ import com.woka.utils.show
|
||||
|
||||
class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
companion object{
|
||||
const val EXTRA_LIVE_STREAM_URL = "extra_live_stream_url"
|
||||
const val EXTRA_LIVE_STREAM_ID = "extra_live_stream_id"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityLiveStreamPlayerBinding
|
||||
|
||||
private lateinit var player: JWPlayer
|
||||
@@ -35,6 +42,11 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
|
||||
private var playbackState: PlayBackState? = null
|
||||
|
||||
private val clickHelper = ClicksHelper
|
||||
|
||||
private var liveStreamUrl: String = ""
|
||||
private var liveTvId: Int = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
@@ -50,6 +62,12 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
WindowCompat.getInsetsController(window, window.decorView)
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
|
||||
intent.getStringExtra(EXTRA_LIVE_STREAM_URL)?.let {
|
||||
liveStreamUrl = it
|
||||
}
|
||||
|
||||
liveTvId = intent.getIntExtra(EXTRA_LIVE_STREAM_ID, -1)
|
||||
|
||||
networkCallback = object : NetworkCallback(){
|
||||
override fun onAvailable(network: Network) {
|
||||
super.onAvailable(network)
|
||||
@@ -88,7 +106,7 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
KeepScreenOnHandler(player, window)
|
||||
|
||||
val playlistItem = PlaylistItem.Builder()
|
||||
.file("https://d3volyx7jx7oal.cloudfront.net/master.m3u8")
|
||||
.file(liveStreamUrl)
|
||||
.mediaId("YR5pnlIM")
|
||||
.build()
|
||||
val playlist: MutableList<PlaylistItem> = ArrayList()
|
||||
@@ -105,9 +123,13 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
playbackState = PlayBackState.PLAY
|
||||
binding.playerView.show()
|
||||
binding.errorView.hide()
|
||||
|
||||
upsertClickEvent()
|
||||
})
|
||||
player.addListener(EventType.PAUSE, VideoPlayerEvents.OnPauseListener {
|
||||
playbackState = PlayBackState.PAUSED
|
||||
|
||||
upsertClickEvent()
|
||||
})
|
||||
player.addListener(EventType.ERROR, VideoPlayerEvents.OnErrorListener {
|
||||
playbackState = PlayBackState.STOPPED
|
||||
@@ -142,6 +164,16 @@ class LiveStreamPlayerActivity : AppCompatActivity(), FullscreenHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private fun upsertClickEvent(){
|
||||
if (liveTvId == -1) return
|
||||
|
||||
clickHelper.upsertClickEvent(
|
||||
ContentType.LIVE_TV,
|
||||
liveTvId,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFullscreenRequested() {}
|
||||
|
||||
override fun onFullscreenExitRequested() {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.woka.streamingurls
|
||||
|
||||
import com.woka.networking.ApiResponse
|
||||
import com.woka.streamingurls.models.LiveStreamingResponse
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
|
||||
interface StreamingApiService {
|
||||
|
||||
@GET("live_streaming")
|
||||
suspend fun liveStreaming(): Response<ApiResponse<LiveStreamingResponse>>
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.woka.streamingurls
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.networking.RetrofitHelper
|
||||
import com.woka.networking.RetrofitHelper.handleApiCall
|
||||
import com.woka.streamingurls.models.LiveStreamingResponse
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
object StreamingUrlRepository {
|
||||
|
||||
private val apiService = RetrofitHelper.getRetrofit().create(StreamingApiService::class.java)
|
||||
|
||||
private val _liveStreamLiveData = MutableLiveData<ApiResult<LiveStreamingResponse>>()
|
||||
val liveStreamLiveData: LiveData<ApiResult<LiveStreamingResponse>>
|
||||
get() = _liveStreamLiveData
|
||||
|
||||
fun loadLiveStreamingUrls(){
|
||||
if (_liveStreamLiveData.isInitialized && _liveStreamLiveData.value is ApiResult.Success){
|
||||
return
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
_liveStreamLiveData.postValue(
|
||||
handleApiCall {
|
||||
apiService.liveStreaming()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.woka.streamingurls.models
|
||||
|
||||
data class LiveData(
|
||||
val id: Int?,
|
||||
val live_url: LiveUrl?,
|
||||
val name: Name?
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.woka.streamingurls.models
|
||||
|
||||
data class LiveFmData(
|
||||
val id: Int?,
|
||||
val live_fm_url: String?,
|
||||
val title: String?
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.woka.streamingurls.models
|
||||
|
||||
data class LiveStreamingResponse(
|
||||
val live_data: List<LiveData?>?,
|
||||
val live_fm_data: LiveFmData?
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.woka.streamingurls.models
|
||||
|
||||
data class LiveUrl(
|
||||
val hd_url_en: String?,
|
||||
val hd_url_hin: String?,
|
||||
val sd_url_en: String?,
|
||||
val sd_url_hin: String?
|
||||
)
|
||||
6
app/src/main/java/com/woka/streamingurls/models/Name.kt
Normal file
6
app/src/main/java/com/woka/streamingurls/models/Name.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.woka.streamingurls.models
|
||||
|
||||
data class Name(
|
||||
val title_en: String?,
|
||||
val title_hin: String?
|
||||
)
|
||||
12
app/src/main/res/drawable/ic_play_retry.xml
Normal file
12
app/src/main/res/drawable/ic_play_retry.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M5.233,0.494C6.88,-0.113 8.681,-0.162 10.358,0.355C11.402,0.677 12.362,1.208 13.184,1.907L13.453,2.146L14.293,1.306C14.896,0.703 15.907,1.085 15.994,1.899L16,2.013L16,6L12.013,6C11.161,6 10.715,5.015 11.229,4.377L11.306,4.293L12.037,3.561C11.389,2.972 10.616,2.528 9.768,2.267C8.511,1.879 7.16,1.915 5.925,2.37C4.69,2.825 3.639,3.674 2.934,4.786C2.228,5.897 1.908,7.21 2.023,8.521C2.137,9.832 2.679,11.07 3.566,12.042C4.453,13.015 5.635,13.669 6.931,13.904C8.226,14.139 9.562,13.941 10.734,13.341C11.906,12.741 12.848,11.773 13.415,10.585C13.653,10.086 14.25,9.875 14.748,10.113C15.246,10.351 15.458,10.948 15.22,11.446C14.464,13.03 13.208,14.321 11.645,15.121C10.083,15.921 8.301,16.185 6.574,15.872C4.847,15.559 3.271,14.687 2.088,13.39C0.906,12.093 0.183,10.443 0.03,8.695C-0.122,6.946 0.305,5.196 1.245,3.714C2.185,2.232 3.587,1.101 5.233,0.494ZM6,5.461C6,5.095 6.375,4.862 6.695,5L6.768,5.039L10.771,7.578C11.053,7.756 11.078,8.146 10.848,8.363L10.771,8.422L6.768,10.962C6.459,11.158 6.062,10.965 6.006,10.621L6,10.539L6,5.461Z" />
|
||||
|
||||
</vector>
|
||||
@@ -123,6 +123,17 @@
|
||||
android:scaleType="fitXY"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/retry_btn"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_play_retry"
|
||||
android:layout_margin="12dp"
|
||||
android:scaleType="fitXY"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
android:visibility="gone"
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/home_img_bn"
|
||||
android:layout_width="22sp"
|
||||
android:layout_height="22sp"
|
||||
android:layout_width="@dimen/_20ssp"
|
||||
android:layout_height="@dimen/_20ssp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_home_bn"
|
||||
app:tint="@android:color/darker_gray" />
|
||||
@@ -53,7 +53,7 @@
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textAlignment="center"
|
||||
android:maxLines="1"
|
||||
android:textSize="12sp"
|
||||
android:textSize="@dimen/_11ssp"
|
||||
android:ellipsize="end"
|
||||
|
||||
android:layout_marginTop="5dp"
|
||||
@@ -82,8 +82,8 @@
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="22sp"
|
||||
android:layout_width="@dimen/_34ssp"
|
||||
android:layout_height="@dimen/_20ssp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/img_woka_w"
|
||||
android:scaleType="fitXY"
|
||||
@@ -97,7 +97,7 @@
|
||||
android:text="@string/explore_woka"
|
||||
android:textColor="@color/color_primary"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textSize="12sp"
|
||||
android:textSize="@dimen/_11ssp"
|
||||
android:textAlignment="center"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
@@ -129,8 +129,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/my_list_img_bn"
|
||||
android:layout_width="22sp"
|
||||
android:layout_height="22sp"
|
||||
android:layout_width="@dimen/_20ssp"
|
||||
android:layout_height="@dimen/_20ssp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_heart_filled"
|
||||
app:tint="@android:color/darker_gray"
|
||||
@@ -144,7 +144,7 @@
|
||||
android:text="@string/my_list"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textSize="12sp"
|
||||
android:textSize="@dimen/_11ssp"
|
||||
android:textAlignment="center"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
|
||||
Reference in New Issue
Block a user