diff --git a/README.md b/README.md index 889efcb..3fe7fd2 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ ## 更新日志 +### v1.2.5 + +* 美化频道信息显示 +* 优化节目单获取 + ### v1.2.4 * 改变换台滑动方向,上一个频道下滑,下一个频道上滑 diff --git a/app/src/main/java/com/lizongying/mytv/InfoFragment.kt b/app/src/main/java/com/lizongying/mytv/InfoFragment.kt index 6de7aca..a5279f2 100644 --- a/app/src/main/java/com/lizongying/mytv/InfoFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/InfoFragment.kt @@ -33,8 +33,17 @@ class InfoFragment : Fragment() { handler.postDelayed(removeRunnable, delay) } - fun show() { + fun show(tvViewModel: TVViewModel) { 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) view?.visibility = View.VISIBLE handler.postDelayed(removeRunnable, delay) @@ -52,17 +61,6 @@ class InfoFragment : Fragment() { 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() { super.onDestroyView() _binding = null diff --git a/app/src/main/java/com/lizongying/mytv/MainActivity.kt b/app/src/main/java/com/lizongying/mytv/MainActivity.kt index a7ea683..0fab0b0 100644 --- a/app/src/main/java/com/lizongying/mytv/MainActivity.kt +++ b/app/src/main/java/com/lizongying/mytv/MainActivity.kt @@ -46,8 +46,8 @@ class MainActivity : FragmentActivity() { if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .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, mainFragment) .hide(infoFragment) .commit() mainFragment.view?.requestFocus() @@ -56,8 +56,7 @@ class MainActivity : FragmentActivity() { } fun showInfoFragment(tvViewModel: TVViewModel) { - infoFragment.setInfo(tvViewModel) - infoFragment.show() + infoFragment.show(tvViewModel) } fun play(tvViewModel: TVViewModel) { diff --git a/app/src/main/java/com/lizongying/mytv/MainFragment.kt b/app/src/main/java/com/lizongying/mytv/MainFragment.kt index 7ec172a..ff85409 100644 --- a/app/src/main/java/com/lizongying/mytv/MainFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/MainFragment.kt @@ -3,6 +3,8 @@ package com.lizongying.mytv import android.content.Context import android.content.SharedPreferences import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.util.Log import androidx.leanback.app.BrowseSupportFragment import androidx.leanback.widget.ArrayObjectAdapter @@ -16,6 +18,7 @@ import androidx.leanback.widget.Presenter import androidx.leanback.widget.Row import androidx.leanback.widget.RowPresenter import androidx.lifecycle.lifecycleScope +import com.lizongying.mytv.Utils.getDateTimestamp import com.lizongying.mytv.models.TVListViewModel import com.lizongying.mytv.models.TVViewModel import kotlinx.coroutines.Dispatchers @@ -35,6 +38,9 @@ class MainFragment : BrowseSupportFragment() { private var lastVideoUrl: String = "" + private val handler = Handler(Looper.getMainLooper()) + private lateinit var mUpdateProgramRunnable: UpdateProgramRunnable + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) headersState = HEADERS_DISABLED @@ -47,6 +53,9 @@ class MainFragment : BrowseSupportFragment() { request = activity?.let { Request(it) } loadRows() + mUpdateProgramRunnable = UpdateProgramRunnable() + handler.post(mUpdateProgramRunnable) + setupEventListeners() view?.post { @@ -92,17 +101,41 @@ class MainFragment : BrowseSupportFragment() { } } } - tvViewModel.program.observe(viewLifecycleOwner) { _ -> - if (tvViewModel.program.value!!.isEmpty()) { - if (tvViewModel.programId.value != null) { - Log.i(TAG, "get program ${tvViewModel.title.value}") - request?.fetchProgram(tvViewModel) - } + } + } + + 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()) { + tvViewModel.programUpdateTime = timestamp + request?.fetchProgram(tvViewModel) + } else { + if (timestamp - tvViewModel.program.value!!.last().et < 600) { + tvViewModel.programUpdateTime = timestamp + 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 { val title = tvViewModel.title.value val videoUrl = tvViewModel.videoIndex.value?.let { tvViewModel.videoUrl.value?.get(it) } diff --git a/app/src/main/java/com/lizongying/mytv/Request.kt b/app/src/main/java/com/lizongying/mytv/Request.kt index 390adb2..7c6ea9b 100644 --- a/app/src/main/java/com/lizongying/mytv/Request.kt +++ b/app/src/main/java/com/lizongying/mytv/Request.kt @@ -5,6 +5,7 @@ import android.os.Handler import android.os.Looper import android.util.Base64 import android.util.Log +import com.lizongying.mytv.Utils.getDateFormat import com.lizongying.mytv.api.ApiClient import com.lizongying.mytv.api.BtraceClient 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.Callback import retrofit2.Response -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec @@ -34,6 +32,7 @@ class Request(var context: Context) { private var yspBtraceService: YSPBtraceService? = null private var yspProtoService: YSPProtoService? = null + // TODO onDestroy private val handler = Handler(Looper.getMainLooper()) private lateinit var myRunnable: MyRunnable @@ -175,13 +174,13 @@ class Request(var context: Context) { livepid = pid, sUrl = "https://www.yangshipin.cn/#/tv/home?pid=$pid", playno = ysp?.getRand()!!, - ftime = getCurrentDate2(), + ftime = getDateFormat("yyyy-MM-dd HH:mm:ss"), seq = tvModel.seq.toString(), ) ?.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { -// Log.i(TAG, "$title kvcollect success") + Log.d(TAG, "$title kvcollect success") } else { Log.e(TAG, "$title kvcollect status error") tvModel.firstSource() @@ -238,20 +237,9 @@ class Request(var context: Context) { }) } - private fun getCurrentDate(): String { - val currentDate = Date() - val formatter = SimpleDateFormat("yyyyMMdd", Locale.CHINA) - 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()) + fun fetchProgram(tvViewModel: TVViewModel) { + val title = tvViewModel.title.value + yspProtoService?.getProgram(tvViewModel.programId.value!!, getDateFormat("yyyyMMdd")) ?.enqueue(object : Callback { override fun onResponse( call: Call, @@ -260,13 +248,14 @@ class Request(var context: Context) { if (response.isSuccessful) { val program = response.body() if (program != null) { - tvModel.addProgram(program.dataListList) + tvViewModel.addProgram(program.dataListList) + Log.i(TAG, "$title program ${program.dataListList.size}") } } } override fun onFailure(call: Call, t: Throwable) { - Log.e(TAG, "Program request failed", t) + Log.e(TAG, "$title program request failed $t") } }) } diff --git a/app/src/main/java/com/lizongying/mytv/Utils.kt b/app/src/main/java/com/lizongying/mytv/Utils.kt new file mode 100644 index 0000000..1282925 --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/Utils.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt b/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt index f81e9b3..76111f4 100644 --- a/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt +++ b/app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt @@ -11,6 +11,7 @@ import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.exoplayer.hls.HlsMediaSource 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 java.util.Date @@ -231,6 +232,8 @@ class TVViewModel(private var tv: TV) : ViewModel() { private var rowPosition: Int = 0 private var itemPosition: Int = 0 + var programUpdateTime: Int = 0 + private val _programId = MutableLiveData() val programId: LiveData get() = _programId @@ -376,10 +379,10 @@ class TVViewModel(private var tv: TV) : ViewModel() { return mapping[tv.title] } - fun getProgram(): MutableList? { - _program.value = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList() - return _program.value?.subList(0, 2) - } +// fun getProgram(): MutableList? { +// _program.value = (_program.value?.filter { it.et > (Date().time / 1000) })?.toMutableList() +// return _program.value?.subList(0, 2) +// } fun getProgramOne(): Program? { 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) { - 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) { return } @@ -402,7 +408,7 @@ class TVViewModel(private var tv: TV) : ViewModel() { _program.value = p1 } else { _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 ))?.toMutableList() } @@ -415,7 +421,6 @@ class TVViewModel(private var tv: TV) : ViewModel() { mHeaders = headers } - fun setMinimumLoadableRetryCount(minimumLoadableRetryCount: Int) { mMinimumLoadableRetryCount = minimumLoadableRetryCount }