change channel info style

This commit is contained in:
Li ZongYing 2023-12-28 20:30:12 +08:00
parent 72e893b73a
commit 3eb6757543
7 changed files with 93 additions and 49 deletions

View File

@ -13,6 +13,11 @@
## 更新日志 ## 更新日志
### v1.2.5
* 美化频道信息显示
* 优化节目单获取
### v1.2.4 ### v1.2.4
* 改变换台滑动方向,上一个频道下滑,下一个频道上滑 * 改变换台滑动方向,上一个频道下滑,下一个频道上滑

View File

@ -33,8 +33,17 @@ class InfoFragment : Fragment() {
handler.postDelayed(removeRunnable, delay) handler.postDelayed(removeRunnable, delay)
} }
fun show() { fun show(tvViewModel: TVViewModel) {
Log.i("", "show") Log.i("", "show")
binding.textView.text = tvViewModel.title.value
Glide.with(this)
.load(tvViewModel.logo.value)
.into(binding.infoLogo)
val program = tvViewModel.getProgramOne()
if (program != null) {
binding.infoDesc.text = program.name
}
handler.removeCallbacks(removeRunnable) handler.removeCallbacks(removeRunnable)
view?.visibility = View.VISIBLE view?.visibility = View.VISIBLE
handler.postDelayed(removeRunnable, delay) handler.postDelayed(removeRunnable, delay)
@ -52,17 +61,6 @@ class InfoFragment : Fragment() {
view?.visibility = View.GONE view?.visibility = View.GONE
} }
fun setInfo(tvViewModel: TVViewModel) {
binding.textView.text = tvViewModel.title.value
Glide.with(this)
.load(tvViewModel.logo.value)
.into(binding.infoLogo)
val program = tvViewModel.getProgramOne()
if (program != null) {
binding.infoDesc.text = program.name
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View File

@ -46,8 +46,8 @@ class MainActivity : FragmentActivity() {
if (savedInstanceState == null) { if (savedInstanceState == null) {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.main_browse_fragment, playerFragment) .add(R.id.main_browse_fragment, playerFragment)
.add(R.id.main_browse_fragment, mainFragment)
.add(R.id.main_browse_fragment, infoFragment) .add(R.id.main_browse_fragment, infoFragment)
.add(R.id.main_browse_fragment, mainFragment)
.hide(infoFragment) .hide(infoFragment)
.commit() .commit()
mainFragment.view?.requestFocus() mainFragment.view?.requestFocus()
@ -56,8 +56,7 @@ class MainActivity : FragmentActivity() {
} }
fun showInfoFragment(tvViewModel: TVViewModel) { fun showInfoFragment(tvViewModel: TVViewModel) {
infoFragment.setInfo(tvViewModel) infoFragment.show(tvViewModel)
infoFragment.show()
} }
fun play(tvViewModel: TVViewModel) { fun play(tvViewModel: TVViewModel) {

View File

@ -3,6 +3,8 @@ package com.lizongying.mytv
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log import android.util.Log
import androidx.leanback.app.BrowseSupportFragment import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter import androidx.leanback.widget.ArrayObjectAdapter
@ -16,6 +18,7 @@ import androidx.leanback.widget.Presenter
import androidx.leanback.widget.Row import androidx.leanback.widget.Row
import androidx.leanback.widget.RowPresenter import androidx.leanback.widget.RowPresenter
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.lizongying.mytv.Utils.getDateTimestamp
import com.lizongying.mytv.models.TVListViewModel import com.lizongying.mytv.models.TVListViewModel
import com.lizongying.mytv.models.TVViewModel import com.lizongying.mytv.models.TVViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -35,6 +38,9 @@ class MainFragment : BrowseSupportFragment() {
private var lastVideoUrl: String = "" private var lastVideoUrl: String = ""
private val handler = Handler(Looper.getMainLooper())
private lateinit var mUpdateProgramRunnable: UpdateProgramRunnable
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
headersState = HEADERS_DISABLED headersState = HEADERS_DISABLED
@ -47,6 +53,9 @@ class MainFragment : BrowseSupportFragment() {
request = activity?.let { Request(it) } request = activity?.let { Request(it) }
loadRows() loadRows()
mUpdateProgramRunnable = UpdateProgramRunnable()
handler.post(mUpdateProgramRunnable)
setupEventListeners() setupEventListeners()
view?.post { view?.post {
@ -92,15 +101,39 @@ class MainFragment : BrowseSupportFragment() {
} }
} }
} }
tvViewModel.program.observe(viewLifecycleOwner) { _ -> }
}
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacks(mUpdateProgramRunnable)
}
fun updateProgram(tvViewModel: TVViewModel) {
val timestamp = getDateTimestamp()
if (timestamp - tvViewModel.programUpdateTime > 60) {
if (tvViewModel.program.value!!.isEmpty()) { if (tvViewModel.program.value!!.isEmpty()) {
if (tvViewModel.programId.value != null) { tvViewModel.programUpdateTime = timestamp
Log.i(TAG, "get program ${tvViewModel.title.value}") request?.fetchProgram(tvViewModel)
} else {
if (timestamp - tvViewModel.program.value!!.last().et < 600) {
tvViewModel.programUpdateTime = timestamp
request?.fetchProgram(tvViewModel) request?.fetchProgram(tvViewModel)
} }
} }
} }
} }
inner class UpdateProgramRunnable : Runnable {
override fun run() {
tvListViewModel.getTVListViewModel().value?.filter { it.programId.value != null }
?.forEach { tvViewModel ->
updateProgram(
tvViewModel
)
}
handler.postDelayed(this, 60000)
}
} }
fun check(tvViewModel: TVViewModel): Boolean { fun check(tvViewModel: TVViewModel): Boolean {

View File

@ -5,6 +5,7 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import com.lizongying.mytv.Utils.getDateFormat
import com.lizongying.mytv.api.ApiClient import com.lizongying.mytv.api.ApiClient
import com.lizongying.mytv.api.BtraceClient import com.lizongying.mytv.api.BtraceClient
import com.lizongying.mytv.api.LiveInfo import com.lizongying.mytv.api.LiveInfo
@ -20,9 +21,6 @@ import com.lizongying.mytv.proto.Ysp.cn.yangshipin.omstv.common.proto.epgProgram
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import javax.crypto.Cipher import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
@ -34,6 +32,7 @@ class Request(var context: Context) {
private var yspBtraceService: YSPBtraceService? = null private var yspBtraceService: YSPBtraceService? = null
private var yspProtoService: YSPProtoService? = null private var yspProtoService: YSPProtoService? = null
// TODO onDestroy
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
private lateinit var myRunnable: MyRunnable private lateinit var myRunnable: MyRunnable
@ -175,13 +174,13 @@ class Request(var context: Context) {
livepid = pid, livepid = pid,
sUrl = "https://www.yangshipin.cn/#/tv/home?pid=$pid", sUrl = "https://www.yangshipin.cn/#/tv/home?pid=$pid",
playno = ysp?.getRand()!!, playno = ysp?.getRand()!!,
ftime = getCurrentDate2(), ftime = getDateFormat("yyyy-MM-dd HH:mm:ss"),
seq = tvModel.seq.toString(), seq = tvModel.seq.toString(),
) )
?.enqueue(object : Callback<Void> { ?.enqueue(object : Callback<Void> {
override fun onResponse(call: Call<Void>, response: Response<Void>) { override fun onResponse(call: Call<Void>, response: Response<Void>) {
if (response.isSuccessful) { if (response.isSuccessful) {
// Log.i(TAG, "$title kvcollect success") Log.d(TAG, "$title kvcollect success")
} else { } else {
Log.e(TAG, "$title kvcollect status error") Log.e(TAG, "$title kvcollect status error")
tvModel.firstSource() tvModel.firstSource()
@ -238,20 +237,9 @@ class Request(var context: Context) {
}) })
} }
private fun getCurrentDate(): String { fun fetchProgram(tvViewModel: TVViewModel) {
val currentDate = Date() val title = tvViewModel.title.value
val formatter = SimpleDateFormat("yyyyMMdd", Locale.CHINA) yspProtoService?.getProgram(tvViewModel.programId.value!!, getDateFormat("yyyyMMdd"))
return formatter.format(currentDate)
}
private fun getCurrentDate2(): String {
val currentDate = Date()
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA)
return formatter.format(currentDate)
}
fun fetchProgram(tvModel: TVViewModel) {
yspProtoService?.getProgram(tvModel.programId.value!!, getCurrentDate())
?.enqueue(object : Callback<epgProgramModel.Response> { ?.enqueue(object : Callback<epgProgramModel.Response> {
override fun onResponse( override fun onResponse(
call: Call<epgProgramModel.Response>, call: Call<epgProgramModel.Response>,
@ -260,13 +248,14 @@ class Request(var context: Context) {
if (response.isSuccessful) { if (response.isSuccessful) {
val program = response.body() val program = response.body()
if (program != null) { if (program != null) {
tvModel.addProgram(program.dataListList) tvViewModel.addProgram(program.dataListList)
Log.i(TAG, "$title program ${program.dataListList.size}")
} }
} }
} }
override fun onFailure(call: Call<epgProgramModel.Response>, t: Throwable) { override fun onFailure(call: Call<epgProgramModel.Response>, t: Throwable) {
Log.e(TAG, "Program request failed", t) Log.e(TAG, "$title program request failed $t")
} }
}) })
} }

View File

@ -0,0 +1,15 @@
package com.lizongying.mytv
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
object Utils {
fun getDateFormat(format: String): String {
return SimpleDateFormat(format, Locale.CHINA).format(Date())
}
fun getDateTimestamp(): Int {
return (Date().time / 1000).toInt()
}
}

View File

@ -11,6 +11,7 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.exoplayer.hls.HlsMediaSource import androidx.media3.exoplayer.hls.HlsMediaSource
import com.lizongying.mytv.TV import com.lizongying.mytv.TV
import com.lizongying.mytv.Utils.getDateTimestamp
import com.lizongying.mytv.proto.Ysp.cn.yangshipin.omstv.common.proto.programModel.Program import com.lizongying.mytv.proto.Ysp.cn.yangshipin.omstv.common.proto.programModel.Program
import java.util.Date import java.util.Date
@ -231,6 +232,8 @@ class TVViewModel(private var tv: TV) : ViewModel() {
private var rowPosition: Int = 0 private var rowPosition: Int = 0
private var itemPosition: Int = 0 private var itemPosition: Int = 0
var programUpdateTime: Int = 0
private val _programId = MutableLiveData<String>() private val _programId = MutableLiveData<String>()
val programId: LiveData<String> val programId: LiveData<String>
get() = _programId get() = _programId
@ -376,10 +379,10 @@ class TVViewModel(private var tv: TV) : ViewModel() {
return mapping[tv.title] return mapping[tv.title]
} }
fun getProgram(): MutableList<Program>? { // fun getProgram(): MutableList<Program>? {
_program.value = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList() // _program.value = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList()
return _program.value?.subList(0, 2) // return _program.value?.subList(0, 2)
} // }
fun getProgramOne(): Program? { fun getProgramOne(): Program? {
val programNew = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList() val programNew = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList()
@ -393,7 +396,10 @@ class TVViewModel(private var tv: TV) : ViewModel() {
} }
fun addProgram(p: MutableList<Program>) { fun addProgram(p: MutableList<Program>) {
val p1 = (p.filter { it.et > (Date().time / 1000) }).toMutableList() val timestamp = getDateTimestamp()
// after now & not empty & different
val p1 = (p.filter { it.et > timestamp }).toMutableList()
if (p1.isEmpty() || _program.value == p1) { if (p1.isEmpty() || _program.value == p1) {
return return
} }
@ -402,7 +408,7 @@ class TVViewModel(private var tv: TV) : ViewModel() {
_program.value = p1 _program.value = p1
} else { } else {
_program.value = _program.value =
((_program.value?.filter { it.et > (Date().time / 1000) && it.st < p1.first().st })?.plus( ((_program.value?.filter { it.et > timestamp && it.st < p1.first().st })?.plus(
p1 p1
))?.toMutableList() ))?.toMutableList()
} }
@ -415,7 +421,6 @@ class TVViewModel(private var tv: TV) : ViewModel() {
mHeaders = headers mHeaders = headers
} }
fun setMinimumLoadableRetryCount(minimumLoadableRetryCount: Int) { fun setMinimumLoadableRetryCount(minimumLoadableRetryCount: Int) {
mMinimumLoadableRetryCount = minimumLoadableRetryCount mMinimumLoadableRetryCount = minimumLoadableRetryCount
} }