Compare commits

..
3 Commits
Author SHA1 Message Date
Li ZongYing 61f62121f2 menu auto close 2024-01-10 18:01:25 +08:00
Li ZongYing d0c7627e35 fix 13 2024-01-08 22:40:56 +08:00
Li ZongYing c10d8b688f add retry 2024-01-08 20:07:53 +08:00
8 changed files with 127 additions and 74 deletions
+10
View File
@@ -14,6 +14,16 @@
## 更新日志
### v1.3.3
* 部分错误会提示用户
* 菜单3秒钟后自动关闭
### v1.3.2
* 增加重试,减少因网络问题导致的播放失败
* 优化横幅banner
### v1.2.6
* 支持安卓4.2
+1 -2
View File
@@ -12,12 +12,11 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.MyTV">
<activity
android:keepScreenOn="true"
android:name=".MainActivity"
android:banner="@drawable/logo"
android:banner="@drawable/banner"
android:exported="true"
android:icon="@drawable/logo"
android:logo="@drawable/logo"
@@ -35,6 +35,9 @@ class MainActivity : FragmentActivity() {
private lateinit var gestureDetector: GestureDetector
private val handler = Handler()
private val delay: Long = 3000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@@ -86,6 +89,7 @@ class MainActivity : FragmentActivity() {
if (mainFragment.isHidden) {
transaction.show(mainFragment)
keepRunnable()
} else {
transaction.hide(mainFragment)
}
@@ -93,6 +97,15 @@ class MainActivity : FragmentActivity() {
transaction.commit()
}
fun keepRunnable() {
handler.removeCallbacks(hideRunnable)
handler.postDelayed(hideRunnable, delay)
}
private val hideRunnable = Runnable {
supportFragmentManager.beginTransaction().hide(mainFragment).commit()
}
private fun mainFragmentIsHidden(): Boolean {
return mainFragment.isHidden
}
@@ -6,6 +6,7 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter
import androidx.leanback.widget.HeaderItem
@@ -63,6 +64,13 @@ class MainFragment : BrowseSupportFragment() {
handler.post(mUpdateProgramRunnable)
tvListViewModel.getTVListViewModel().value?.forEach { tvViewModel ->
tvViewModel.errInfo.observe(viewLifecycleOwner) { _ ->
if (tvViewModel.errInfo.value != null
&& tvViewModel.id.value == itemPosition
) {
Toast.makeText(context, tvViewModel.errInfo.value, Toast.LENGTH_SHORT).show()
}
}
tvViewModel.ready.observe(viewLifecycleOwner) { _ ->
// not first time && channel not change
@@ -78,8 +86,8 @@ class MainFragment : BrowseSupportFragment() {
if (tvViewModel.change.value != null) {
val title = tvViewModel.title.value
Log.i(TAG, "switch $title")
if (tvViewModel.pid.value != null) {
Log.i(TAG, "request $title")
if (tvViewModel.pid.value != "") {
Log.i(TAG, "request $title ${tvViewModel.pid.value}")
lifecycleScope.launch(Dispatchers.IO) {
tvViewModel.let { request.fetchData(it) }
}
@@ -305,6 +313,7 @@ class MainFragment : BrowseSupportFragment() {
) {
if (item is TVViewModel) {
tvListViewModel.setItemPositionCurrent(item.id.value!!)
(activity as MainActivity).keepRunnable()
}
}
}
@@ -26,7 +26,6 @@ import retrofit2.Response
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import kotlin.reflect.KFunction0
class Request {
@@ -87,33 +86,10 @@ class Request {
"海南卫视" to "海南卫视",
)
private var token: String? = null
fun initYSP(context: Context) {
ysp = YSP(context)
}
fun fetchToken(fragmentReady: KFunction0<Unit>) {
yspTokenService.getInfo()
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful) {
val info = response.body()
token = info?.data?.token
Log.i(TAG, "info success $token")
} else {
Log.e(TAG, "info status error")
}
fragmentReady()
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
fragmentReady()
}
})
}
fun fetchVideo(tvModel: TVViewModel, cookie: String) {
if (::myRunnable.isInitialized) {
handler.removeCallbacks(myRunnable)
@@ -150,71 +126,82 @@ class Request {
Log.i(TAG, "$title url $url")
tvModel.addVideoUrl(url)
tvModel.allReady()
tvModel.retryTimes = 0
myRunnable = MyRunnable(tvModel)
handler.post(myRunnable)
} else {
Log.e(TAG, "$title key error")
tvModel.firstSource()
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
}
}
} else {
Log.e(TAG, "$title url error $request")
tvModel.firstSource()
if (liveInfo?.data?.errinfo != null && liveInfo.data.errinfo != "success!") {
Log.e(TAG, "$title url error ${liveInfo.data.errinfo}")
tvModel.setErrInfo(liveInfo.data.errinfo)
} else {
Log.e(TAG, "$title url error $request $liveInfo")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
}
}
}
} else {
Log.e(TAG, "$title status error")
tvModel.firstSource()
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
}
}
}
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
Log.e(TAG, "$title request error")
tvModel.firstSource()
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
}
}
})
}
fun fetchVideo(tvModel: TVViewModel) {
yspTokenService.getInfo()
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful) {
val info = response.body()
val token = info?.data?.token
Log.i(TAG, "info success $token")
val cookie =
"guid=1; vplatform=109; yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchVideo(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel)
}
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel)
}
}
})
}
fun fetchData(tvModel: TVViewModel) {
var cookie = "guid=1; vplatform=109"
val channels = arrayOf(
"CCTV3 综艺",
"CCTV6 电影",
"CCTV8 电视剧",
"风云剧场",
"第一剧场",
"怀旧剧场",
"世界地理",
"风云音乐",
"兵器科技",
"风云足球",
"高尔夫网球",
"女性时尚",
"央视文化精品",
"央视台球",
"电视指南",
"卫生健康",
)
if (tvModel.title.value in channels) {
yspTokenService.getInfo()
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful) {
val info = response.body()
token = info?.data?.token
Log.i(TAG, "info success $token")
cookie =
"guid=1; vplatform=109; yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchVideo(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
}
})
if (tvModel.needToken) {
fetchVideo(tvModel)
} else {
val cookie = "guid=1; vplatform=109"
fetchVideo(tvModel, cookie)
}
}
@@ -251,7 +238,6 @@ class Request {
// Log.d(TAG, "$title kvcollect success")
} else {
Log.e(TAG, "$title kvcollect status error")
tvModel.firstSource()
}
}
@@ -15,6 +15,7 @@ data class LiveInfo(
data class LiveInfoData(
val chanll: String,
val playurl: String,
val errinfo: String,
)
data class LiveInfoRequest(
@@ -19,8 +19,14 @@ class TVViewModel(private var tv: TV) : ViewModel() {
private var rowPosition: Int = 0
private var itemPosition: Int = 0
var retryTimes: Int = 0
var retryMaxTimes: Int = 3
var programUpdateTime: Long = 0
private val _errInfo = MutableLiveData<String>()
val errInfo: LiveData<String>
get() = _errInfo
private val _programId = MutableLiveData<String>()
val programId: LiveData<String>
get() = _programId
@@ -69,6 +75,27 @@ class TVViewModel(private var tv: TV) : ViewModel() {
var seq = 0
var needToken = false
private val channelsNeedToken = arrayOf(
"CCTV3 综艺",
"CCTV6 电影",
"CCTV8 电视剧",
"风云剧场",
"第一剧场",
"怀旧剧场",
"世界地理",
"风云音乐",
"兵器科技",
"风云足球",
"高尔夫网球",
"女性时尚",
"央视文化精品",
"央视台球",
"电视指南",
"卫生健康",
)
fun addVideoUrl(url: String) {
if (_videoUrl.value?.isNotEmpty() == true) {
if (_videoUrl.value!!.last().contains("cctv.cn")) {
@@ -119,6 +146,10 @@ class TVViewModel(private var tv: TV) : ViewModel() {
_pid.value = tv.pid
_sid.value = tv.sid
_program.value = mutableListOf()
if (tv.title in channelsNeedToken) {
needToken = true
}
}
fun getRowPosition(): Int {
@@ -137,6 +168,10 @@ class TVViewModel(private var tv: TV) : ViewModel() {
itemPosition = position
}
fun setErrInfo(info: String) {
_errInfo.value = info
}
fun update(t: TV) {
tv = t
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB