mirror of
https://github.com/lizongying/my-tv.git
synced 2026-10-26 22:26:29 +08:00
add ysp
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.util.Log
|
||||
@@ -8,12 +9,30 @@ import android.view.ViewGroup
|
||||
import androidx.leanback.widget.ImageCardView
|
||||
import androidx.leanback.widget.Presenter
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.bumptech.glide.Glide
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CardPresenter(private val lifecycleScope: LifecycleCoroutineScope) : Presenter() {
|
||||
class CardPresenter(
|
||||
private val lifecycleScope: LifecycleCoroutineScope,
|
||||
// private val owner: LifecycleOwner
|
||||
) : Presenter() {
|
||||
|
||||
private var tvViewModel: TVViewModel? = null
|
||||
fun bindData(viewModel: TVViewModel, fragment: Context?, viewHolder: ViewHolder) {
|
||||
}
|
||||
|
||||
fun setViewModel(model: TVViewModel) {
|
||||
tvViewModel = model
|
||||
}
|
||||
|
||||
fun unbind() {
|
||||
// viewModel?.backgroundImage?.removeObservers(fragment)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
|
||||
val cardView = object :
|
||||
@@ -36,6 +55,7 @@ class CardPresenter(private val lifecycleScope: LifecycleCoroutineScope) : Prese
|
||||
cardView.titleText = tv.title
|
||||
cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT)
|
||||
cardView.tag = tv.videoUrl
|
||||
Log.i(TAG, "bind ${tv.videoUrl}")
|
||||
|
||||
// lifecycleScope.launch(Dispatchers.IO) {
|
||||
// val videoThumbnail = tv.videoUrl?.let { getVideoThumbnail(it) }
|
||||
@@ -44,11 +64,20 @@ class CardPresenter(private val lifecycleScope: LifecycleCoroutineScope) : Prese
|
||||
// cardView.mainImageView.setImageBitmap(videoThumbnail)
|
||||
// }
|
||||
// }
|
||||
|
||||
// tvViewModel?.update(tv)
|
||||
// tvViewModel?.backgroundImage?.observe(owner) { imageUrl ->
|
||||
// if (imageUrl != "") {
|
||||
// Glide.with(viewHolder.view.context)
|
||||
// .load(imageUrl)
|
||||
// .centerCrop()
|
||||
// .into(cardView.mainImageView)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onUnbindViewHolder(viewHolder: ViewHolder) {
|
||||
val cardView = viewHolder.view as ImageCardView
|
||||
// Remove references to images so that the garbage collector can free up memory
|
||||
cardView.badgeImage = null
|
||||
cardView.mainImage = null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.content.Context
|
||||
|
||||
class Encryptor {
|
||||
external fun init(context: Context)
|
||||
|
||||
external fun encrypt(t: String, e: String, r: String, n: String, i: String): String
|
||||
|
||||
external fun hash(data: ByteArray): ByteArray?
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native-lib")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.lizongying.mytv.databinding.InfoBinding
|
||||
|
||||
class InfoFragment : Fragment() {
|
||||
private var _binding: InfoBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = InfoBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
fun setInfo(info: TV) {
|
||||
binding.textView.text = info.title
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "InfoFragment"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.Signature
|
||||
import android.content.pm.SigningInfo
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
@@ -11,11 +17,14 @@ import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import java.security.MessageDigest
|
||||
|
||||
|
||||
class MainActivity : FragmentActivity() {
|
||||
|
||||
private val playbackFragment = PlaybackFragment()
|
||||
private val mainFragment = MainFragment()
|
||||
private val infoFragment = InfoFragment()
|
||||
|
||||
private var doubleBackToExitPressedOnce = false
|
||||
|
||||
@@ -27,11 +36,35 @@ class MainActivity : FragmentActivity() {
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.main_browse_fragment, playbackFragment)
|
||||
.add(R.id.main_browse_fragment, mainFragment)
|
||||
.add(R.id.main_browse_fragment, infoFragment)
|
||||
.hide(infoFragment)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
fun switchInfoFragment(tv: TV) {
|
||||
infoFragment.setInfo(tv)
|
||||
|
||||
if (infoFragment.isHidden) {
|
||||
supportFragmentManager.beginTransaction().show(infoFragment).commit()
|
||||
}
|
||||
}
|
||||
|
||||
fun showInfoFragment(tv: TV) {
|
||||
infoFragment.setInfo(tv)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.show(infoFragment)
|
||||
.commit()
|
||||
}
|
||||
|
||||
fun hideInfoFragment() {
|
||||
supportFragmentManager.beginTransaction()
|
||||
.hide(infoFragment)
|
||||
.commit()
|
||||
}
|
||||
|
||||
fun play(tv: TV) {
|
||||
Log.i(TAG, "play: $tv")
|
||||
playbackFragment.play(tv)
|
||||
}
|
||||
|
||||
@@ -103,9 +136,7 @@ class MainActivity : FragmentActivity() {
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_MENU -> {
|
||||
val packageInfo = packageManager.getPackageInfo(packageName, 0)
|
||||
|
||||
val versionName = packageInfo.versionName
|
||||
val versionName = getPackageInfo().versionName
|
||||
|
||||
val textView = TextView(this)
|
||||
textView.text =
|
||||
@@ -168,6 +199,57 @@ class MainActivity : FragmentActivity() {
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
private fun getPackageInfo(): PackageInfo {
|
||||
val flag = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
PackageManager.GET_SIGNATURES
|
||||
} else {
|
||||
PackageManager.GET_SIGNING_CERTIFICATES
|
||||
}
|
||||
|
||||
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
packageManager.getPackageInfo(packageName, flag)
|
||||
} else {
|
||||
packageManager.getPackageInfo(
|
||||
packageName,
|
||||
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAppSignature(): String {
|
||||
val packageInfo = getPackageInfo()
|
||||
|
||||
var sign: Signature? = null
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
val signatures: Array<out Signature>? = packageInfo.signatures
|
||||
if (signatures != null) {
|
||||
sign = signatures[0]
|
||||
}
|
||||
} else {
|
||||
val signingInfo: SigningInfo? = packageInfo.signingInfo
|
||||
if (signingInfo != null) {
|
||||
sign = signingInfo.apkContentsSigners[0]
|
||||
}
|
||||
}
|
||||
if (sign == null) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return hashSignature(sign)
|
||||
}
|
||||
|
||||
private fun hashSignature(signature: Signature): String {
|
||||
return try {
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
md.update(signature.toByteArray())
|
||||
val digest = md.digest()
|
||||
digest.let { it -> it.joinToString("") { "%02x".format(it) } }
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error hashing signature", e)
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.leanback.app.BrowseSupportFragment
|
||||
import androidx.leanback.widget.ArrayObjectAdapter
|
||||
@@ -15,6 +18,9 @@ import androidx.leanback.widget.Presenter
|
||||
import androidx.leanback.widget.Row
|
||||
import androidx.leanback.widget.RowPresenter
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.lizongying.mytv.models.TVListViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainFragment : BrowseSupportFragment() {
|
||||
|
||||
@@ -22,13 +28,40 @@ class MainFragment : BrowseSupportFragment() {
|
||||
|
||||
private val list2: MutableList<Info> = mutableListOf()
|
||||
|
||||
private var request: Request? = null
|
||||
|
||||
private var rowsAdapter: ArrayObjectAdapter? = null
|
||||
|
||||
private var tvListViewModel = TVListViewModel()
|
||||
|
||||
private var sharedPref: SharedPreferences? = null
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
Log.i(TAG, "onCreate")
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)
|
||||
|
||||
setupUIElements()
|
||||
request = activity?.let { Request(it) }
|
||||
loadRows()
|
||||
setupEventListeners()
|
||||
|
||||
view?.post {
|
||||
request?.fetchPage()
|
||||
}
|
||||
|
||||
tvListViewModel.getListLiveData().value?.forEach { tvViewModel ->
|
||||
tvViewModel.videoUrl.observe(viewLifecycleOwner) { _ ->
|
||||
Log.i(TAG, "tv ${tvViewModel.getTV()}")
|
||||
if (tvViewModel.updateByYSP()) {
|
||||
val tv = tvViewModel.getTV()
|
||||
if (tv.id == itemPosition) {
|
||||
(activity as? MainActivity)?.play(tv)
|
||||
// (activity as? MainActivity)?.switchInfoFragment(tv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUIElements() {
|
||||
@@ -36,40 +69,61 @@ class MainFragment : BrowseSupportFragment() {
|
||||
// headersState = HEADERS_DISABLED
|
||||
}
|
||||
|
||||
private var count: Int = 0
|
||||
private fun updateRows(tv: TV) {
|
||||
// 获取适配器中的数据
|
||||
val dataList = rowsAdapter?.replace(tv.id, tv)
|
||||
//
|
||||
//// 修改数据
|
||||
//// 这里假设 dataList 是一个可变的列表
|
||||
// dataList[position] = updatedData
|
||||
//
|
||||
//// 刷新适配器
|
||||
// rowsAdapter.notifyItemChanged(position)
|
||||
// rowsAdapter.notifyItemRangeChanged()
|
||||
}
|
||||
|
||||
private fun loadRows() {
|
||||
val list = TVList.list
|
||||
val rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
|
||||
|
||||
rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
|
||||
|
||||
// val cardPresenter = CardPresenter(lifecycleScope, viewLifecycleOwner)
|
||||
val cardPresenter = CardPresenter(lifecycleScope)
|
||||
|
||||
var idx: Long = 0
|
||||
for ((k, v) in list) {
|
||||
val listRowAdapter = ArrayObjectAdapter(cardPresenter)
|
||||
var idx2 = 0
|
||||
for ((k1, v1) in v) {
|
||||
val tv = TV(
|
||||
count,
|
||||
k1,
|
||||
v1.toList()
|
||||
)
|
||||
for ((_, v1) in v) {
|
||||
list2.add(
|
||||
Info(
|
||||
idx.toInt(), idx2, tv
|
||||
idx.toInt(), idx2, v1
|
||||
)
|
||||
)
|
||||
listRowAdapter.add(tv)
|
||||
count++
|
||||
listRowAdapter.add(v1)
|
||||
idx2++
|
||||
|
||||
tvListViewModel.addTV(v1)
|
||||
}
|
||||
val header = HeaderItem(idx, k)
|
||||
rowsAdapter.add(ListRow(header, listRowAdapter))
|
||||
rowsAdapter!!.add(ListRow(header, listRowAdapter))
|
||||
idx++
|
||||
}
|
||||
|
||||
adapter = rowsAdapter
|
||||
|
||||
(activity as? MainActivity)?.play(list2.first().item as TV)
|
||||
itemPosition = sharedPref?.getInt("position", 0)!!
|
||||
|
||||
val tvModel = tvListViewModel.getTVModel(itemPosition)
|
||||
if (tvModel?.ysp() != null) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvModel.let { request?.fetchData(it) }
|
||||
}
|
||||
} else {
|
||||
(activity as? MainActivity)?.play(list2[itemPosition].item)
|
||||
// (activity as? MainActivity)?.switchInfoFragment(list2[itemPosition].item)
|
||||
}
|
||||
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
|
||||
@@ -79,24 +133,41 @@ class MainFragment : BrowseSupportFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun savePosition(position: Int) {
|
||||
with(sharedPref!!.edit()) {
|
||||
putInt("position", position)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
fun prev() {
|
||||
view?.post {
|
||||
itemPosition--
|
||||
if (itemPosition == -1) {
|
||||
itemPosition = list2.size - 1
|
||||
}
|
||||
savePosition(itemPosition)
|
||||
|
||||
val l = list2[itemPosition]
|
||||
l.item?.let { (activity as? MainActivity)?.play(it) }
|
||||
|
||||
val tvModel = tvListViewModel.getTVModel(itemPosition)
|
||||
if (tvModel?.ysp() != null) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvModel.let { request?.fetchData(it) }
|
||||
}
|
||||
} else {
|
||||
l.item.let { (activity as? MainActivity)?.play(it) }
|
||||
}
|
||||
|
||||
setSelectedPosition(
|
||||
l.rowPosition, false,
|
||||
SelectItemViewHolderTask(l.itemPosition)
|
||||
)
|
||||
// Toast.makeText(
|
||||
// activity,
|
||||
// "${l.title} ${tv.videoIndex}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
Toast.makeText(
|
||||
activity,
|
||||
l.item.title,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,56 +177,59 @@ class MainFragment : BrowseSupportFragment() {
|
||||
if (itemPosition == list2.size) {
|
||||
itemPosition = 0
|
||||
}
|
||||
savePosition(itemPosition)
|
||||
|
||||
val l = list2[itemPosition]
|
||||
l.item?.let { (activity as? MainActivity)?.play(it) }
|
||||
|
||||
val tvModel = tvListViewModel.getTVModel(itemPosition)
|
||||
if (tvModel?.ysp() != null) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvModel.let { request?.fetchData(it) }
|
||||
}
|
||||
} else {
|
||||
l.item.let { (activity as? MainActivity)?.play(it) }
|
||||
}
|
||||
|
||||
setSelectedPosition(
|
||||
l.rowPosition, false,
|
||||
SelectItemViewHolderTask(l.itemPosition)
|
||||
)
|
||||
// Toast.makeText(
|
||||
// activity,
|
||||
// "${l.title} ${tv.videoIndex}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
Toast.makeText(
|
||||
activity,
|
||||
l.item.title,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
fun prevSource() {
|
||||
view?.post {
|
||||
val item = list2[itemPosition]
|
||||
val tv = item.item as TV
|
||||
val tv = list2[itemPosition].item
|
||||
if (tv.videoUrl.size > 1) {
|
||||
tv.videoIndex--
|
||||
if (tv.videoIndex == -1) {
|
||||
tv.videoIndex = tv.videoUrl.size - 1
|
||||
}
|
||||
|
||||
tv.videoIndex--
|
||||
if (tv.videoIndex == -1) {
|
||||
tv.videoIndex = tv.videoUrl.size - 1
|
||||
(activity as? MainActivity)?.play(tv)
|
||||
// (activity as? MainActivity)?.switchInfoFragment(tv)
|
||||
}
|
||||
|
||||
(activity as? MainActivity)?.play(tv)
|
||||
// Toast.makeText(
|
||||
// activity,
|
||||
// "${l.title} ${tv.videoIndex}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
}
|
||||
}
|
||||
|
||||
fun nextSource() {
|
||||
view?.post {
|
||||
val item = list2[itemPosition]
|
||||
val tv = item.item as TV
|
||||
val tv = list2[itemPosition].item
|
||||
|
||||
tv.videoIndex++
|
||||
if (tv.videoIndex == tv.videoUrl.size) {
|
||||
tv.videoIndex = 0
|
||||
if (tv.videoUrl.size > 1) {
|
||||
tv.videoIndex++
|
||||
if (tv.videoIndex == tv.videoUrl.size) {
|
||||
tv.videoIndex = 0
|
||||
}
|
||||
|
||||
(activity as? MainActivity)?.play(tv)
|
||||
// (activity as? MainActivity)?.switchInfoFragment(tv)
|
||||
}
|
||||
|
||||
(activity as? MainActivity)?.play(tv)
|
||||
// Toast.makeText(
|
||||
// activity,
|
||||
// "${l.title} ${tv.videoIndex}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,12 +245,21 @@ class MainFragment : BrowseSupportFragment() {
|
||||
rowViewHolder: RowPresenter.ViewHolder,
|
||||
row: Row
|
||||
) {
|
||||
Log.d(TAG, "onItemClicked")
|
||||
if (item is TV) {
|
||||
Log.d(TAG, "Item: $item")
|
||||
(activity as? MainActivity)?.play(item)
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
itemPosition = item.id
|
||||
savePosition(itemPosition)
|
||||
|
||||
val tvModel = tvListViewModel.getTVModel(itemPosition)
|
||||
if (tvModel?.ysp() != null) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
tvModel.let { request?.fetchData(it) }
|
||||
}
|
||||
} else {
|
||||
(activity as? MainActivity)?.play(item)
|
||||
// (activity as? MainActivity)?.switchInfoFragment(item)
|
||||
}
|
||||
|
||||
(activity as? MainActivity)?.switchMainFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,16 +269,12 @@ class MainFragment : BrowseSupportFragment() {
|
||||
itemViewHolder: Presenter.ViewHolder?, item: Any?,
|
||||
rowViewHolder: RowPresenter.ViewHolder, row: Row
|
||||
) {
|
||||
if (item is TV) {
|
||||
Log.i(TAG, "Item: ${item.id}")
|
||||
}
|
||||
if (itemViewHolder == null) {
|
||||
view?.post {
|
||||
val l = list2[itemPosition]
|
||||
Log.i(TAG, "$l")
|
||||
val it = list2[itemPosition]
|
||||
setSelectedPosition(
|
||||
l.rowPosition, false,
|
||||
SelectItemViewHolderTask(l.itemPosition)
|
||||
it.rowPosition, false,
|
||||
SelectItemViewHolderTask(it.itemPosition)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class PlaybackFragment : VideoSupportFragment() {
|
||||
val videoUrl = tv.videoUrl[tv.videoIndex]
|
||||
|
||||
if (videoUrl == "") {
|
||||
Log.e(TAG, "tv $tv")
|
||||
Log.e(TAG, "videoUrl is empty")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.lizongying.mytv.api.ApiClient
|
||||
import com.lizongying.mytv.api.LiveInfo
|
||||
import com.lizongying.mytv.api.LiveInfoRequest
|
||||
import com.lizongying.mytv.api.ProtoClient
|
||||
import com.lizongying.mytv.api.YSP
|
||||
import com.lizongying.mytv.api.YSPApiService
|
||||
import com.lizongying.mytv.api.YSPProtoService
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import com.lizongying.mytv.proto.Ysp.cn.yangshipin.oms.common.proto.pageModel
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
class Request(var context: Context) {
|
||||
private var ysp: YSP? = null
|
||||
private var yspApiService: YSPApiService? = null
|
||||
private var yspProtoService: YSPProtoService? = null
|
||||
|
||||
private var mapping = mapOf(
|
||||
"CCTV4K" to "CCTV4K",
|
||||
"CCTV1" to "CCTV1 综合",
|
||||
"CCTV2" to "CCTV2 财经",
|
||||
"CCTV4" to "CCTV4 中文国际",
|
||||
"CCTV5" to "CCTV5 体育",
|
||||
"CCTV5+" to "CCTV5+ 体育赛事",
|
||||
"CCTV7" to "CCTV7 国防军事",
|
||||
"CCTV9" to "CCTV9 记录",
|
||||
"CCTV10" to "CCTV10 科教",
|
||||
"CCTV11" to "CCTV11 戏曲",
|
||||
"CCTV12" to "CCTV12 社会与法",
|
||||
// "CCTV13" to "CCTV13",
|
||||
"CCTV14" to "CCTV14 少儿",
|
||||
"CCTV15" to "CCTV15 音乐",
|
||||
"CCTV16-HD" to "CCTV16 奥林匹克",
|
||||
"CCTV17" to "CCTV17 农业农村",
|
||||
"CGTN" to "CGTN",
|
||||
"CGTN法语频道" to "CGTN 法语频道",
|
||||
"CGTN俄语频道" to "CGTN 俄语频道",
|
||||
"CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道",
|
||||
"CGTN西班牙语频道" to "CGTN 西班牙语频道",
|
||||
// "CGTN外语纪录频道" to "CGTN外语纪录频道",
|
||||
|
||||
"东方卫视" to "东方卫视",
|
||||
"湖南卫视" to "湖南卫视",
|
||||
"湖北卫视" to "湖北卫视",
|
||||
"辽宁卫视" to "辽宁卫视",
|
||||
"江苏卫视" to "江苏卫视",
|
||||
"江西卫视" to "江西卫视",
|
||||
"山东卫视" to "山东卫视",
|
||||
"广东卫视" to "广东卫视",
|
||||
"广西卫视" to "广西卫视",
|
||||
"重庆卫视" to "重庆卫视",
|
||||
"河南卫视" to "河南卫视",
|
||||
"河北卫视" to "河北卫视",
|
||||
"贵州卫视" to "贵州卫视",
|
||||
"北京卫视" to "北京卫视",
|
||||
"黑龙江卫视" to "黑龙江卫视",
|
||||
"浙江卫视" to "浙江卫视",
|
||||
"安徽卫视" to "安徽卫视",
|
||||
"深圳卫视" to "深圳卫视",
|
||||
"四川卫视" to "四川卫视",
|
||||
"福建东南卫视" to "东南卫视",
|
||||
"海南卫视" to "海南卫视",
|
||||
)
|
||||
|
||||
init {
|
||||
if (context is MainActivity) {
|
||||
ysp = YSP(context)
|
||||
}
|
||||
yspApiService = ApiClient().yspApiService
|
||||
yspProtoService = ProtoClient().yspProtoService
|
||||
}
|
||||
|
||||
fun fetchData(tvModel: TVViewModel) {
|
||||
val data = ysp?.switch(tvModel)
|
||||
|
||||
val request = data?.let { LiveInfoRequest(it) }
|
||||
request?.let { yspApiService?.getLiveInfo(it) }
|
||||
?.enqueue(object : Callback<LiveInfo> {
|
||||
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
|
||||
if (response.isSuccessful) {
|
||||
val liveInfo = response.body()
|
||||
if (liveInfo?.data?.playurl != null) {
|
||||
tvModel.updateVideoUrlByYSP(liveInfo.data.playurl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun fetchPage() {
|
||||
yspProtoService?.getPage()?.enqueue(object : Callback<pageModel.Response> {
|
||||
override fun onResponse(
|
||||
call: Call<pageModel.Response>,
|
||||
response: Response<pageModel.Response>
|
||||
) {
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body()
|
||||
|
||||
if (body?.data?.feedModuleListCount == 1) {
|
||||
for (item in body.data?.feedModuleListList!![0]?.dataTvChannelListList!!) {
|
||||
if (item.isVip && !item.isLimitedFree) {
|
||||
continue
|
||||
}
|
||||
Log.i(
|
||||
TAG,
|
||||
"${item.channelName} ,${item.tvLogo},${item.pid},${item.streamId}"
|
||||
)
|
||||
var channelType = "央视频道"
|
||||
if (item?.channelType === "weishi") {
|
||||
channelType = "地方频道"
|
||||
}
|
||||
if (!mapping.containsKey(item.channelName)) {
|
||||
continue
|
||||
}
|
||||
val tv = TVList.list[channelType]?.get(mapping[item.channelName])
|
||||
if (tv != null) {
|
||||
tv.logo = item.tvLogo
|
||||
tv.pid = item.pid
|
||||
tv.sid = item.streamId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<pageModel.Response>, t: Throwable) {
|
||||
Log.e(TAG, "Page request failed", t)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun fetchProgram(tvModel: TVViewModel) {
|
||||
yspProtoService?.getProgram("", "")?.enqueue(object : Callback<LiveInfo> {
|
||||
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
|
||||
if (response.isSuccessful) {
|
||||
val liveInfo = response.body()
|
||||
Log.i(TAG, "${liveInfo?.data?.playurl}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "Request"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@ data class TV(
|
||||
var title: String,
|
||||
var videoUrl: List<String>,
|
||||
var videoIndex: Int = 0,
|
||||
var logo: String = "",
|
||||
var pid: String = "",
|
||||
var sid: String = "",
|
||||
) : Serializable {
|
||||
|
||||
override fun toString(): String {
|
||||
@@ -15,6 +18,9 @@ data class TV(
|
||||
", title='" + title + '\'' +
|
||||
", videoUrl='" + videoUrl + '\'' +
|
||||
", videoIndex='" + videoIndex + '\'' +
|
||||
", logo='" + logo + '\'' +
|
||||
", pid='" + pid + '\'' +
|
||||
", sid='" + sid + '\'' +
|
||||
'}'
|
||||
}
|
||||
|
||||
|
||||
@@ -1,113 +1,248 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.util.Log
|
||||
|
||||
object TVList {
|
||||
val list: Map<String, Map<String, Set<String>>> by lazy {
|
||||
val list: Map<String, Map<String, TV>> by lazy {
|
||||
setupTV()
|
||||
}
|
||||
|
||||
private fun setupTV(): Map<String, Map<String, Set<String>>> {
|
||||
val tvs = """
|
||||
央视频道,CCTV1 综合,http://tvpull.dxhmt.cn/tv/11481-4.m3u8
|
||||
央视频道,CCTV1 综合,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv1hd265/57/20191230/index.m3u8?&encrypt=
|
||||
央视频道,CCTV2 财经,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv2hd265/55/20200407/index.m3u8?&encrypt=
|
||||
央视频道,CCTV3 综艺,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv3hd/3000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV4 中文国际,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8
|
||||
央视频道,CCTV4 中文国际,http://hlsbkmgsplive.miguvideo.com/wd_r2/cctv/cctv4hd/1500/index.m3u8?&encrypt=
|
||||
央视频道,CCTV4 中文国际美洲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv4meihd/57/index.m3u8?&encrypt=
|
||||
央视频道,CCTV4 中文国际欧洲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv4ouhd/51/index.m3u8?&encrypt=
|
||||
央视频道,CCTV5 体育,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv5hd265/57/20191230/index.m3u8?&encrypt=
|
||||
央视频道,CCTV5+ 体育赛事,http://hlsbkmgsplive.miguvideo.com/wd_r2/cctv/cctv5plusnew/2500/index.m3u8?&encrypt=
|
||||
央视频道,CCTV6 电影,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv6hd/3000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV7 国防军事,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv7hd/51/index.m3u8?&encrypt=
|
||||
央视频道,CCTV8 电视剧,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv8hd/3000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV9 记录,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv9hd/57/index.m3u8?&encrypt=
|
||||
央视频道,CCTV10 科教,http://hlsbkmgsplive.miguvideo.com/wd_r2/2018/ocn/cctv10hd/2000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV11 戏曲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv11hd/57/20200103/index.m3u8?&encrypt=
|
||||
央视频道,CCTV12 社会与法,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv12hd/57/index.m3u8?&encrypt=
|
||||
央视频道,CCTV13 新闻,https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8
|
||||
央视频道,CCTV13 新闻,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/cctv13/2000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV14 少儿,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv14hd/3000/index.m3u8?&encrypt=
|
||||
央视频道,CCTV15 音乐,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225785/index.m3u8
|
||||
央视频道,CCTV15 音乐,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv15hd/51/index.m3u8?&encrypt=
|
||||
央视频道,CCTV17 农业农村,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv17hd/57/index.m3u8?&encrypt=
|
||||
央视频道,CGTN,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/cctvnews/1000/index.m3u8?&encrypt=
|
||||
央视频道,CGTN 新闻频道,http://live.cgtn.com/1000/prog_index.m3u8
|
||||
央视频道,CGTN 纪录频道,https://livedoc.cgtn.com/500d/prog_index.m3u8
|
||||
央视频道,CGTN 法语频道,https://livefr.cgtn.com/1000f/prog_index.m3u8
|
||||
央视频道,CGTN 俄语频道,http://liveru.cgtn.com/1000r/prog_index.m3u8
|
||||
央视频道,CGTN 西班牙语频道,http://livees.cgtn.com/500e/prog_index.m3u8
|
||||
央视频道,CGTN 阿拉伯语频道,http://livear.cgtn.com/1000a/prog_index.m3u8
|
||||
央视频道,CGTN 拉丁美洲频道,http://livees.cgtn.com/1000e/prog_index.m3u8
|
||||
央视频道,书画频道,http://211.103.180.178:8234/live_hls/hdmi.m3u8
|
||||
private var count: Int = 0
|
||||
|
||||
地方频道,东方卫视,http://hlsbkmgsplive.miguvideo.com/wd_r4/dfl/dongfangwshd/3000/index.m3u8?&encrypt=
|
||||
地方频道,内蒙古卫视,http://hlsbkmgsplive.miguvideo.com/envivo_w/2018/SD/neimeng/1000/index.m3u8?&encrypt=
|
||||
地方频道,湖南卫视,http://hlsbkmgsplive.miguvideo.com/wd-hunanhd-2500/index.m3u8?&encrypt=
|
||||
地方频道,湖北卫视,http://hlsbkmgsplive.miguvideo.com/wd_r2/2018/ocn/hubeiwshd/2000/index.m3u8?&encrypt=
|
||||
地方频道,辽宁卫视,http://hlsbkmgsplive.miguvideo.com/wd_r2/2018/ocn/liaoningwshd/2000/index.m3u8?&encrypt=
|
||||
地方频道,江苏卫视,http://hlsbkmgsplive.miguvideo.com/wd_r2/cctv/jiangsuhd/2500/index.m3u8?&encrypt=
|
||||
地方频道,江西卫视,http://hlsbkmgsplive.miguvideo.com/migu/kailu/jxwshd/57/20190820/index.m3u8?&encrypt=
|
||||
地方频道,西藏卫视,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/xizang/1000/index.m3u8?&encrypt=
|
||||
地方频道,山东卫视,http://hlsbkmgsplive.miguvideo.com/wd-shandonghd-1200/index.m3u8?&encrypt=
|
||||
地方频道,广东卫视,http://hlsbkmgsplive.miguvideo.com/ws_w/2018/gdws/gdws2000/2000/index.m3u8?&encrypt=
|
||||
地方频道,广西卫视,http://hlsbkmgsplive.miguvideo.com/wd-guangxiwssd-600/index.m3u8?&encrypt=
|
||||
地方频道,重庆卫视,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/chongqing/1000/index.m3u8?&encrypt=
|
||||
地方频道,甘肃卫视,http://hlsbkmgsplive.miguvideo.com/envivo_v/2018/SD/gansu/1000/index.m3u8?&encrypt=
|
||||
地方频道,青海卫视,http://hlsbkmgsplive.miguvideo.com/envivo_w/2018/SD/qinghai/1000/index.m3u8?&encrypt=
|
||||
地方频道,陕西卫视,http://hlsbkmgsplive.miguvideo.com/envivo_w/2018/SD/shan3xi/1000/index.m3u8?&encrypt=
|
||||
地方频道,河南卫视,http://hlsbkmgsplive.miguvideo.com/wd-henanwssd-600/index.m3u8?&encrypt=
|
||||
地方频道,大湾区卫视,http://hlsbkmgsplive.miguvideo.com/wd_r3/2018/nfmedia/nfws/1000/index.m3u8?&encrypt=
|
||||
地方频道,云南卫视,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/yunnan/1000/index.m3u8?&encrypt=
|
||||
地方频道,贵州卫视,http://hlsbkmgsplive.miguvideo.com/wd-guizhouwssd-600/index.m3u8?&encrypt=
|
||||
地方频道,新疆卫视,http://hlsbkmgsplive.miguvideo.com/wd-xinjiangwssd-600/index.m3u8?&encrypt=
|
||||
地方频道,北京卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225728/index.m3u8
|
||||
地方频道,重庆卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226409/index.m3u8
|
||||
地方频道,天津卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225740/index.m3u8
|
||||
地方频道,黑龙江卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226327/index.m3u8
|
||||
地方频道,辽宁卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226546/index.m3u8
|
||||
地方频道,吉林卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226397/index.m3u8
|
||||
地方频道,河北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226406/index.m3u8
|
||||
地方频道,河南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226480/index.m3u8
|
||||
地方频道,山东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226209/index.m3u8
|
||||
地方频道,山西卫视,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225763/index.m3u8
|
||||
地方频道,湖北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226477/index.m3u8
|
||||
地方频道,湖南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226307/index.m3u8
|
||||
地方频道,浙江卫视,http://hw-m-l.cztv.com/channels/lantian/channel01/1080p.m3u8
|
||||
地方频道,江苏卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8
|
||||
地方频道,江西卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226344/index.m3u8
|
||||
地方频道,安徽卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226391/index.m3u8
|
||||
地方频道,广东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226216/index.m3u8
|
||||
地方频道,广西卫视,http://live.gxrb.com.cn/tv/gxtvlive03/index.m3u8
|
||||
地方频道,深圳卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8
|
||||
地方频道,四川卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/index.m3u8
|
||||
地方频道,贵州卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226474/index.m3u8
|
||||
地方频道,云南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226444/index.m3u8
|
||||
地方频道,东南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226341/index.m3u8
|
||||
地方频道,海南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226465/index.m3u8
|
||||
地方频道,内蒙古卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226389/index.m3u8
|
||||
地方频道,陕西卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226457/index.m3u8
|
||||
地方频道,甘肃卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225633/index.m3u8
|
||||
地方频道,宁夏卫视,https://hls.ningxiahuangheyun.com/tv/nxws.m3u8
|
||||
地方频道,新疆卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226460/index.m3u8
|
||||
地方频道,青海卫视,http://stream.qhbtv.com/qhws/sd/live.m3u8
|
||||
地方频道,安多卫视,http://stream.qhbtv.com/adws/sd/live.m3u8
|
||||
地方频道,西藏卫视,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226212/index.m3u8
|
||||
地方频道,延边卫视,http://live.ybtvyun.com/video/s10006-44f040627ca1/index.m3u8
|
||||
private fun setupTV(): Map<String, Map<String, TV>> {
|
||||
val tvs = """
|
||||
央视频道
|
||||
CCTV4K,,https://resources.yangshipin.cn/assets/oms/image/202306/3e9d06fd7244d950df5838750f1c6ac3456e172b51caca2c16d2282125b111e8.png?imageMogr2/format/webp,600002264,2000266303
|
||||
CCTV1 综合,http://tvpull.dxhmt.cn/tv/11481-4.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/d57905b93540bd15f0c48230dbbbff7ee0d645ff539e38866e2d15c8b9f7dfcd.png?imageMogr2/format/webp,600001859,2000210103
|
||||
CCTV2 财经,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226195/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/20115388de0207131af17eac86c33049b95d69eaff064e55653a1b941810a006.png?imageMogr2/format/webp,600001800,2000203603
|
||||
CCTV3 综艺,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226397/index.m3u8
|
||||
CCTV4 中文国际,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8;http://hlsbkmgsplive.miguvideo.com/wd_r2/cctv/cctv4hd/1500/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/f357e58fdbcc076a3d65e1f958c942b2e14f14342c60736ceed98b092d35356a.png?imageMogr2/format/webp,600001814,2000204803
|
||||
CCTV4 中文国际美洲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv4meihd/57/index.m3u8?&encrypt=
|
||||
CCTV4 中文国际欧洲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv4ouhd/51/index.m3u8?&encrypt=
|
||||
CCTV5 体育,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv5hd265/57/20191230/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/0a6a7138952675983a3d854df7688557b286d59aa06166edae51506f9204d655.png?imageMogr2/format/webp,600001818,2000205103
|
||||
CCTV5+ 体育赛事,http://hlsbkmgsplive.miguvideo.com/wd_r2/cctv/cctv5plusnew/2500/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/649ad76a90bfef55b05db9fe52e006487280f619089099d5dc971e387fc6eff0.png?imageMogr2/format/webp,600001817,2000204503
|
||||
CCTV6 电影,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv6hd/3000/index.m3u8?&encrypt=
|
||||
CCTV7 国防军事,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv7hd/51/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/b29af94e295ebdf646cefb68122c429b9cd921f498ca20d2d8070252536f9ff9.png?imageMogr2/format/webp,600004092,2000510003
|
||||
CCTV8 电视剧,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv8hd/3000/index.m3u8?&encrypt=
|
||||
CCTV9 记录,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv9hd/57/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/2ed1b4deeca179d5db806bb941790f82eb92a1b7299c1c38fe027f95a5caee5e.png?imageMogr2/format/webp,600004078,2000499403
|
||||
CCTV10 科教,http://hlsbkmgsplive.miguvideo.com/wd_r2/2018/ocn/cctv10hd/2000/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/aa6157ec65188cd41826e5a2f088c3d6d153205f5f6428258d12c59999e221aa.png?imageMogr2/format/webp,600001805,2000203503
|
||||
CCTV11 戏曲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/cctv11hd/57/20200103/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/ed12ed7c7a1034dae4350011fe039284c5d5a836506b28c9e32e3c75299625c0.png?imageMogr2/format/webp,600001806,2000204103
|
||||
CCTV12 社会与法,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv12hd/57/index.m3u8?&encrypt=, https://resources.yangshipin.cn/assets/oms/image/202306/484083cffaa40df7e659565e8cb4d1cc740158a185512114167aa21fa0c59240.png?imageMogr2/format/webp,600001807,2000202603
|
||||
CCTV13 新闻,https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8;http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/cctv13/2000/index.m3u8?&encrypt=
|
||||
CCTV14 少儿,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226193/index.m3u8;http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv14hd/3000/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/af6b603896938dc346fbb16abfc63c12cba54b0ec9d18770a15d347d115f12d5.png?imageMogr2/format/webp,600001809,2000204403
|
||||
CCTV15 音乐,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225785/index.m3u8;http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv15hd/51/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/2ceee92188ef684efe0d8b90839c4f3ad450d179dc64d59beff417059453af47.png?imageMogr2/format/webp,600001815,2000205003
|
||||
CCTV16 奥林匹克,http://39.134.24.162/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/53793fa7bacd3a93ff6dc5d2758418985e1f952a316c335d663b572d8bdcd74d.png?imageMogr2/format/webp,600098637,2012375003
|
||||
CCTV17 农业农村,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv17hd/57/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/ddef563072f8bad2bea5b9e52674cb7b4ed50efb20c26e61994dfbdf05c1e3c0.png?imageMogr2/format/webp,600001810,2000204203
|
||||
CGTN,http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/cctvnews/1000/index.m3u8?&encrypt=,https://resources.yangshipin.cn/assets/oms/image/202306/a72dff758ca1c17cd0ecc8cedc11b893d208f409d5e6302faa0e9d298848abc3.png?imageMogr2/format/webp,600014550,2001656803
|
||||
CGTN 新闻频道,http://live.cgtn.com/1000/prog_index.m3u8
|
||||
CGTN 纪录频道,https://livedoc.cgtn.com/500d/prog_index.m3u8
|
||||
CGTN 法语频道,https://livefr.cgtn.com/1000f/prog_index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/a8d0046a47433d952bf6ed17062deb8bd2184ba9aec0f7781df6bf9487a3ffcf.png?imageMogr2/format/webp,600084704,2010153503
|
||||
CGTN 俄语频道,http://liveru.cgtn.com/1000r/prog_index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/bf0a820893cbaf20dd0333e27042e1ef9c8806e5b602b6a8c95af399db0bc77a.png?imageMogr2/format/webp,600084758,2010152603
|
||||
CGTN 西班牙语频道,http://livees.cgtn.com/500e/prog_index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202309/7c337e3dbe64402ec7e4678a619a4a6d95144e42f35161181ff78e143b7cf67a.png?imageMogr2/format/webp,600084744,2010152503
|
||||
CGTN 阿拉伯语频道,http://livear.cgtn.com/1000a/prog_index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/2e44e2aa3e7a1cedf07fd0ae59fe69e86a60a2632660a006e3e9e7397b2d107e.png?imageMogr2/format/webp,600084782,2010155203
|
||||
CGTN 拉丁美洲频道,http://livees.cgtn.com/1000e/prog_index.m3u8
|
||||
书画频道,http://211.103.180.178:8234/live_hls/hdmi.m3u8
|
||||
|
||||
地方频道
|
||||
东方卫视,,https://resources.yangshipin.cn/assets/oms/image/202306/9bd372ca292a82ce3aa08772b07efc4af1f85c21d1f268ea33440c49e9a0a488.png?imageMogr2/format/webp,600002483,2000292403
|
||||
内蒙古卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226389/index.m3u8
|
||||
湖南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226307/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/4120e89d3079d08aa17d382f69a2308ec70839b278367763c34a34666c75cb88.png?imageMogr2/format/webp,600002475,2000296203
|
||||
湖北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226477/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/7a6be5a2bb1dc53a945c016ff1f525dc4a84c51db371c15c89aa55404b0ba784.png?imageMogr2/format/webp,600002508,2000294503
|
||||
辽宁卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226546/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/ac4ed6058a87c101ae7147ebc38905d0cae047fb73fd277ee5049b84f52bda36.png?imageMogr2/format/webp,600002505,2000281303
|
||||
江苏卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/380ad685c0c1d5b2c902246b8d2df6d3f9b45e2837abcfe493075bbded597a31.png?imageMogr2/format/webp,600002521,2000295603
|
||||
江西卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226344/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/3c760d0d00463855890e8a1864ea4a6b6dd66b90c29b4ac714a4b17c16519871.png?imageMogr2/format/webp,600002503,2000294103
|
||||
西藏卫视,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226212/index.m3u8
|
||||
山东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226209/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/22d403f07a7cf5410b3ad3ddb65a11aa229a32475fac213f5344c9f0ec330ca1.png?imageMogr2/format/webp,600002513,2000294803
|
||||
山西卫视,http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225763/index.m3u8
|
||||
广东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226216/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/28886880a4dc0f06fb7e0a528a1def0591d61a65870e29176ede0cc92033bbfd.png?imageMogr2/format/webp,600002485,2000292703
|
||||
广西卫视,http://live.gxrb.com.cn/tv/gxtvlive03/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/54b7e97cb816bb223fe05f3fc44da2c7820eb66e8550c19d23100f2c414ecc38.png?imageMogr2/format/webp,600002509,2000294203
|
||||
重庆卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226409/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/657651f411de2673d1770d9a78b44c1265704f7468cc41d4be7f51d630768494.png?imageMogr2/format/webp,600002531,2000297803
|
||||
甘肃卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225633/index.m3u8
|
||||
青海卫视,http://stream.qhbtv.com/qhws/sd/live.m3u8
|
||||
陕西卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226457/index.m3u8
|
||||
河南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226480/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/74925962148a6d31c85808b6cd4e444c2a54bab393d2c5fc85e960b50e22fa86.png?imageMogr2/format/webp,600002525,2000296103
|
||||
河北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226406/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/d545becdc81c60197b08c7f47380705e4665ed3fe55efc8b855e486f6e655378.png?imageMogr2/format/webp,600002493,2000293403
|
||||
云南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226444/index.m3u8
|
||||
贵州卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226474/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/4eb45f4781d33d872af027dc01c941559aab55667dd99cc5c22bef7037807b13.png?imageMogr2/format/webp,600002490,2000293303
|
||||
新疆卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226460/index.m3u8
|
||||
北京卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225728/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/f4f23633c578beea49a3841d88d3490100f029ee349059fa532869db889872c5.png?imageMogr2/format/webp,600002309,2000272103
|
||||
天津卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225740/index.m3u8
|
||||
黑龙江卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226327/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/d8273ae9be698ce2db21f5b886ecac95a73429593f93713c60ed8c12c38bf0d3.png?imageMogr2/format/webp,600002498,2000293903
|
||||
吉林卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226397/index.m3u8
|
||||
浙江卫视,http://hw-m-l.cztv.com/channels/lantian/channel01/1080p.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/a66c836bd98ba3e41a2e9a570d4b9c50dedc6839e9de333e2e78212ad505f37e.png?imageMogr2/format/webp,600002520,2000295503
|
||||
安徽卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226391/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/f35fa04b51b1ee4984b03578b65403570868ebca03c6c01e11b097f999a58d9b.png?imageMogr2/format/webp,600002532,2000298003
|
||||
深圳卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/d59fec04c902e3581c617136d02d4b9b8c4cbe64272781ddd3525e80c823edb7.png?imageMogr2/format/webp,600002481,2000292203
|
||||
四川卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/3276a414ae0eaa0f116f2045cd913367967d0c7c1e978e8621ac3879436c6ed7.png?imageMogr2/format/webp,600002516,2000295003
|
||||
东南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226341/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/3208fe6564a293c21b711333fb3edb05bb5b406cff840573c9a8d839680a1579.png?imageMogr2/format/webp,600002484,2000292503
|
||||
海南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226465/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/6e060391fde0469801fc3d84dbf204b4f8d650d251f17d7595a6964c0bb99e81.png?imageMogr2/format/webp,600002506,2000291503
|
||||
宁夏卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225748/index.m3u8
|
||||
安多卫视,http://stream.qhbtv.com/adws/sd/live.m3u8
|
||||
三沙卫视,https://pullsstv90080111.ssws.tv/live/SSTV20220729.m3u8
|
||||
延边卫视,http://live.ybtvyun.com/video/s10006-44f040627ca1/index.m3u8
|
||||
浙江少儿,http://hw-m-l.cztv.com/channels/lantian/channel008/1080p.m3u8
|
||||
南京少儿,http://live.nbs.cn/channels/njtv/sepd/500k.m3u8
|
||||
|
||||
移动专区
|
||||
CCTV1,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226231/index.m3u8
|
||||
CCTV2,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226195/index.m3u8
|
||||
CCTV3,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226397/index.m3u8
|
||||
CCTV4,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8
|
||||
CCTV5,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226395/index.m3u8
|
||||
CCTV5+,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226221/index.m3u8
|
||||
CCTV6,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226393/index.m3u8
|
||||
CCTV7,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226192/index.m3u8
|
||||
CCTV8,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226391/index.m3u8
|
||||
CCTV9,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226197/index.m3u8
|
||||
CCTV10,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226189/index.m3u8
|
||||
CCTV11,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226240/index.m3u8
|
||||
CCTV12,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226190/index.m3u8
|
||||
CCTV13,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226233/index.m3u8
|
||||
CCTV14,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226193/index.m3u8
|
||||
CCTV15,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225785/index.m3u8
|
||||
CCTV16,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8
|
||||
CCTV17,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226198/index.m3u8
|
||||
CETV1,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225753/index.m3u8
|
||||
CETV2,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225756/index.m3u8
|
||||
CETV3,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226226/index.m3u8
|
||||
CETV4,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226225/index.m3u8
|
||||
浙江卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226199/index.m3u8
|
||||
四川卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/index.m3u8
|
||||
重庆卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226202/index.m3u8
|
||||
安徽卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226203/index.m3u8
|
||||
天津卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226204/index.m3u8
|
||||
山西卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225763/index.m3u8
|
||||
山东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226209/index.m3u8
|
||||
山东教育,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226238/index.m3u8
|
||||
东南卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225766/index.m3u8
|
||||
海南卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225769/index.m3u8
|
||||
厦门卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226219/index.m3u8
|
||||
河南卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225767/index.m3u8
|
||||
湖北卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226194/index.m3u8
|
||||
河北卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225750/index.m3u8
|
||||
湖南卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226211/index.m3u8
|
||||
金鹰卡通,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225744/index.m3u8
|
||||
东方卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226217/index.m3u8
|
||||
哈哈炫动,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226213/index.m3u8
|
||||
辽宁卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226201/index.m3u8
|
||||
黑龙江卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226215/index.m3u8
|
||||
吉林卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225792/index.m3u8
|
||||
广西卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225770/index.m3u8
|
||||
江西卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225764/index.m3u8
|
||||
江苏卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8
|
||||
优漫卡通,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225795/index.m3u8
|
||||
深圳卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8
|
||||
广东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226216/index.m3u8
|
||||
大湾区卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226218/index.m3u8
|
||||
北京卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226222/index.m3u8
|
||||
北京卡酷,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225743/index.m3u8
|
||||
冬奥纪实,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226232/index.m3u8
|
||||
嘉佳卡通,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226227/index.m3u8
|
||||
云南卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225751/index.m3u8
|
||||
贵州卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225793/index.m3u8
|
||||
宁夏卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225748/index.m3u8
|
||||
甘肃卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225754/index.m3u8
|
||||
西藏卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226212/index.m3u8
|
||||
安多卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226228/index.m3u8
|
||||
康巴卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226234/index.m3u8
|
||||
新疆卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225747/index.m3u8
|
||||
兵团卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226214/index.m3u8
|
||||
延边卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226220/index.m3u8
|
||||
内蒙古卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225786/index.m3u8
|
||||
康巴卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226234/index.m3u8
|
||||
电视指南,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226987/index.m3u8
|
||||
风云足球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226984/index.m3u8
|
||||
风云剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226950/index.m3u8
|
||||
风云音乐,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226953/index.m3u8
|
||||
央视台球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226956/index.m3u8
|
||||
第一剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226959/index.m3u8
|
||||
女性时尚,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226969/index.m3u8
|
||||
怀旧剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226972/index.m3u8
|
||||
兵器科技,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226975/index.m3u8
|
||||
高尔夫网球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226978/index.m3u8
|
||||
央视文化精品,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226981/index.m3u8
|
||||
哒啵电竞,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226951/index.m3u8
|
||||
哒啵赛事,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226954/index.m3u8
|
||||
CHC高清电影,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226463/index.m3u8
|
||||
CHC家庭影院,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226462/index.m3u8
|
||||
CHC动作电影,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226465/index.m3u8
|
||||
陕西卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225821/index.m3u8
|
||||
农林卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226229/index.m3u8
|
||||
陕西一套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226357/1.m3u8
|
||||
陕西二套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226358/1.m3u8
|
||||
陕西三套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226359/1.m3u8
|
||||
陕西四套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226360/1.m3u8
|
||||
陕西五套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226361/1.m3u8
|
||||
陕西六套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226362/1.m3u8
|
||||
陕西七套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226363/1.m3u8
|
||||
陕西八套,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226364/1.m3u8
|
||||
西安新闻综合,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226366/1.m3u8
|
||||
西安都市,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226367/1.m3u8
|
||||
西安商务资讯,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226368/1.m3u8
|
||||
西安影视,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226369/1.m3u8
|
||||
西安丝路,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226370/1.m3u8
|
||||
西安教育,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226371/index.m3u8
|
||||
咸阳-1,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226372/index.m3u8
|
||||
杨凌-1,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226373/index.m3u8
|
||||
延安-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226374/1.m3u8
|
||||
延安-2,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226375/1.m3u8
|
||||
铜川-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226379/1.m3u8
|
||||
铜川-2,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226380/1.m3u8
|
||||
宝鸡-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226383/1.m3u8
|
||||
宝鸡-2,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226384/1.m3u8
|
||||
宁强-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226390/1.m3u8
|
||||
宁强-2,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226389/1.m3u8
|
||||
汉中-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226331/1.m3u8
|
||||
汉中-3,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225991/index.m3u8
|
||||
佛坪-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226454/1.m3u8
|
||||
镇巴-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226457/1.m3u8
|
||||
略阳-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226322/1.m3u8
|
||||
西乡-1,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226556/index.m3u8
|
||||
榆林-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226377/1.m3u8
|
||||
商洛-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226378/1.m3u8
|
||||
渭南-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226376/1.m3u8
|
||||
安康-1,http://dbiptv.sn.chinamobile.com/PLTV/88888888/224/3221226385/1.m3u8
|
||||
纪实人文,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226230/index.m3u8
|
||||
山东教育卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226238/index.m3u8
|
||||
置业频道,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226241/index.m3u8
|
||||
京视剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226242/index.m3u8
|
||||
家庭理财,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226244/index.m3u8
|
||||
奕坦春秋,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226245/index.m3u8
|
||||
发现之旅,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226235/index.m3u8
|
||||
老故事,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226236/index.m3u8
|
||||
""".trimIndent()
|
||||
|
||||
val map: MutableMap<String, MutableMap<String, LinkedHashSet<String>>> = mutableMapOf()
|
||||
val map: MutableMap<String, MutableMap<String, TV>> = mutableMapOf()
|
||||
|
||||
var channel = ""
|
||||
for (i in tvs.split("\n")) {
|
||||
if (!i.contains(",")) {
|
||||
if (i.trim() == "") {
|
||||
continue
|
||||
}
|
||||
val (channel, title, url) = i.split(",")
|
||||
if (!i.contains(",")) {
|
||||
channel = i.trim()
|
||||
continue
|
||||
}
|
||||
val p = i.split(",")
|
||||
val titleMap = map[channel] ?: mutableMapOf()
|
||||
|
||||
val urlSet = titleMap[title] ?: LinkedHashSet()
|
||||
urlSet.add(url)
|
||||
val tv = titleMap[p[0]] ?: TV(
|
||||
count,
|
||||
p[0],
|
||||
p[1].split(";").map { it.trim() }
|
||||
)
|
||||
count++
|
||||
|
||||
titleMap[title] = urlSet
|
||||
if (p.size > 2) {
|
||||
tv.logo = p[2]
|
||||
}
|
||||
if (p.size > 3) {
|
||||
tv.pid = p[3]
|
||||
}
|
||||
if (p.size > 4) {
|
||||
tv.sid = p[4]
|
||||
}
|
||||
|
||||
titleMap[p[0]] = tv
|
||||
map[channel] = titleMap
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
|
||||
class ApiClient {
|
||||
private val yspUrl = "https://player-api.yangshipin.cn/"
|
||||
|
||||
val yspApiService: YSPApiService by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(yspUrl)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build().create(YSPApiService::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import android.util.Log
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okio.BufferedSink
|
||||
import java.io.IOException
|
||||
|
||||
data class LiveInfo(
|
||||
val code: Int,
|
||||
val msg: String,
|
||||
val data: LiveInfoData,
|
||||
)
|
||||
|
||||
data class LiveInfoData(
|
||||
val playurl: String
|
||||
)
|
||||
|
||||
data class LiveInfoRequest(
|
||||
var data: String,
|
||||
) : RequestBody() {
|
||||
override fun contentType(): MediaType? {
|
||||
return MediaType.parse("application/json;charset=UTF-8")
|
||||
}
|
||||
|
||||
override fun writeTo(sink: BufferedSink) {
|
||||
try {
|
||||
sink.writeUtf8(data)
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "$e")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "LiveInfoRequest"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okio.BufferedSink
|
||||
import java.io.IOException
|
||||
|
||||
data class Page(
|
||||
val code: Int,
|
||||
val msg: String,
|
||||
val data: Data,
|
||||
)
|
||||
|
||||
data class Data(
|
||||
val feedModuleList: List<Module>
|
||||
)
|
||||
|
||||
data class Module(
|
||||
val dataTvChannelList: List<TvChannelListData>
|
||||
)
|
||||
|
||||
data class TvChannelListData(
|
||||
val dataTvChannelList: List<TvChannelListData>
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.protobuf.ProtoConverterFactory
|
||||
|
||||
|
||||
class ProtoClient {
|
||||
private val protoUrl = "https://capi.yangshipin.cn/"
|
||||
|
||||
val yspProtoService: YSPProtoService by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(protoUrl)
|
||||
.addConverterFactory(ProtoConverterFactory.create())
|
||||
.build().create(YSPProtoService::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.lizongying.mytv.Encryptor
|
||||
import com.lizongying.mytv.MainActivity
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import java.util.Date
|
||||
import kotlin.math.floor
|
||||
|
||||
class YSP(var context: Context) {
|
||||
private var cnlid = ""
|
||||
|
||||
private var livepid = ""
|
||||
|
||||
private var stream = "2"
|
||||
|
||||
private var guid = ""
|
||||
|
||||
private var cKey = ""
|
||||
|
||||
private var adjust = 1
|
||||
|
||||
private val sphttps = "1"
|
||||
|
||||
private var platform = "5910204"
|
||||
|
||||
private val cmd = "2"
|
||||
|
||||
private val encryptVer = "8.1"
|
||||
|
||||
private val dtype = "1"
|
||||
|
||||
private val devid = "devid"
|
||||
|
||||
private val otype = "ojson"
|
||||
|
||||
private val appVer = "V1.0.0"
|
||||
|
||||
private val appVersion = "V1.0.0"
|
||||
|
||||
private var randStr = ""
|
||||
|
||||
private val channel = "ysp_tx"
|
||||
|
||||
private var defn = ""
|
||||
|
||||
private var timeStr = ""
|
||||
|
||||
private var signature = ""
|
||||
|
||||
private var encryptor: Encryptor? = null
|
||||
private var sharedPref: SharedPreferences? = null
|
||||
|
||||
init {
|
||||
if (context is MainActivity) {
|
||||
encryptor = Encryptor()
|
||||
encryptor!!.init(context)
|
||||
|
||||
sharedPref = (context as MainActivity).getPreferences(Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
guid = getGuid()
|
||||
}
|
||||
|
||||
fun switch(tvModel: TVViewModel): String {
|
||||
livepid = tvModel.getTV().pid
|
||||
cnlid = tvModel.getTV().sid
|
||||
defn = "fhd"
|
||||
|
||||
guid = getGuid()
|
||||
randStr = getRand()
|
||||
timeStr = getTimeStr()
|
||||
|
||||
// guid = "lq3oqitm_1e15dnzgjnb"
|
||||
// randStr = "BfcCPQp8Hq"
|
||||
// timeStr = "1702166501"
|
||||
|
||||
cKey =
|
||||
encryptor!!.encrypt(cnlid, timeStr, appVer, guid, platform)
|
||||
signature = getSignature()
|
||||
return """{"cnlid":"$cnlid","livepid":"$livepid","stream":"$stream","guid":"$guid","cKey":"$cKey","adjust":$adjust,"sphttps":"$sphttps","platform":"$platform","cmd":"$cmd","encryptVer":"$encryptVer","dtype":"$dtype","devid":"$devid","otype":"$otype","appVer":"$appVer","app_version":"$appVersion","rand_str":"$randStr","channel":"$channel","defn":"$defn","signature":"$signature"}"""
|
||||
|
||||
}
|
||||
|
||||
private fun getTimeStr(): String {
|
||||
return (Date().time / 1000).toString()
|
||||
}
|
||||
|
||||
private fun generateGuid(): String {
|
||||
val timestamp = (System.currentTimeMillis()).toString(36)
|
||||
val originalString = Math.random().toString()
|
||||
val resultString = if (originalString.startsWith("0.")) {
|
||||
originalString.substring(2)
|
||||
} else {
|
||||
originalString
|
||||
}
|
||||
val randomPart = resultString.toLong().toString(36)
|
||||
return timestamp + "_" + randomPart
|
||||
}
|
||||
|
||||
private fun getGuid(): String {
|
||||
// var guid = sharedPref?.getString("guid", "").toString()
|
||||
if (guid == "") {
|
||||
guid = generateGuid()
|
||||
with(sharedPref!!.edit()) {
|
||||
putString("guid", guid)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
return guid
|
||||
}
|
||||
|
||||
private fun getRand(): String {
|
||||
var n = ""
|
||||
val e = "ABCDEFGHIJKlMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
val r = e.length
|
||||
for (i in 0 until 10) {
|
||||
n += e[floor(Math.random() * r).toInt()]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
private fun getSignature(): String {
|
||||
val e =
|
||||
"adjust=${adjust}&appVer=${appVer}&app_version=$appVersion&cKey=$cKey&channel=$channel&cmd=$cmd&cnlid=$cnlid&defn=${defn}&devid=${devid}&dtype=${dtype}&encryptVer=${encryptVer}&guid=${guid}&livepid=${livepid}&otype=${otype}&platform=${platform}&rand_str=${randStr}&sphttps=${sphttps}&stream=${stream}".toByteArray()
|
||||
|
||||
val hashedData = encryptor?.hash(e) ?: return ""
|
||||
return hashedData.let { it -> it.joinToString("") { "%02x".format(it) } }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "YSP"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.POST
|
||||
|
||||
|
||||
interface YSPApiService {
|
||||
@POST("v1/player/get_live_info")
|
||||
@Headers(
|
||||
"content-type: application/json;charset=UTF-8",
|
||||
"referer: https://www.yangshipin.cn/",
|
||||
"yspappid: 519748109",
|
||||
"cookie: guid=1; vplatform=109"
|
||||
)
|
||||
fun getLiveInfo(
|
||||
@Body request: LiveInfoRequest,
|
||||
): Call<LiveInfo>
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lizongying.mytv.api
|
||||
|
||||
import com.lizongying.mytv.proto.Ysp.cn.yangshipin.oms.common.proto.pageModel
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface YSPProtoService {
|
||||
@GET("api/oms/pc/page/PG00000004")
|
||||
@Headers(
|
||||
"yspappid: 519748109",
|
||||
"platform: 109",
|
||||
)
|
||||
fun getPage(
|
||||
): Call<pageModel.Response>
|
||||
|
||||
@GET("api/yspepg/program/{livepid}/{cnlid}")
|
||||
@Headers(
|
||||
"yspappid: 519748109",
|
||||
"platform: 109",
|
||||
)
|
||||
fun getProgram(
|
||||
@Path("livepid") livepid: String,
|
||||
@Path("cnlid") cnlid: String,
|
||||
): Call<LiveInfo>
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lizongying.mytv.models
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.lizongying.mytv.TV
|
||||
|
||||
class TVListViewModel : ViewModel() {
|
||||
private val tvListLiveData = MutableLiveData<MutableList<TV>>()
|
||||
|
||||
private val tvModelListLiveData = MutableLiveData<MutableList<TVViewModel>>()
|
||||
|
||||
fun getListLiveData(): MutableLiveData<MutableList<TVViewModel>> {
|
||||
return tvModelListLiveData
|
||||
}
|
||||
|
||||
fun addTV(tv: TV) {
|
||||
val currentList = tvListLiveData.value ?: mutableListOf()
|
||||
currentList.add(tv)
|
||||
tvListLiveData.value = currentList
|
||||
|
||||
val currentModelList = tvModelListLiveData.value ?: mutableListOf()
|
||||
currentModelList.add(TVViewModel(tv))
|
||||
tvModelListLiveData.value = currentModelList
|
||||
}
|
||||
|
||||
fun updateTV(tv: TV) {
|
||||
val currentList = tvListLiveData.value ?: mutableListOf()
|
||||
currentList[tv.id] = tv
|
||||
tvListLiveData.value = currentList
|
||||
|
||||
val currentModelList = tvModelListLiveData.value ?: mutableListOf()
|
||||
currentModelList[tv.id].update(tv)
|
||||
tvModelListLiveData.value = currentModelList
|
||||
}
|
||||
|
||||
fun getTV(id: Int): TV? {
|
||||
return tvListLiveData.value?.get(id)
|
||||
}
|
||||
|
||||
fun getTVModel(id: Int): TVViewModel? {
|
||||
return tvModelListLiveData.value?.get(id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.lizongying.mytv.models
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.lizongying.mytv.TV
|
||||
|
||||
class TVViewModel(private var tv: TV) : ViewModel() {
|
||||
private var mapping = mapOf(
|
||||
"CCTV4K" to "CCTV4K",
|
||||
// "CCTV1" to "CCTV1 综合",
|
||||
"CCTV2" to "CCTV2 财经",
|
||||
"CCTV4" to "CCTV4 中文国际",
|
||||
"CCTV5" to "CCTV5 体育",
|
||||
"CCTV5+" to "CCTV5+ 体育赛事",
|
||||
"CCTV7" to "CCTV7 国防军事",
|
||||
"CCTV9" to "CCTV9 记录",
|
||||
"CCTV10" to "CCTV10 科教",
|
||||
"CCTV11" to "CCTV11 戏曲",
|
||||
"CCTV12" to "CCTV12 社会与法",
|
||||
// "CCTV13" to "CCTV13",
|
||||
"CCTV14" to "CCTV14 少儿",
|
||||
"CCTV15" to "CCTV15 音乐",
|
||||
"CCTV16-HD" to "CCTV16 奥林匹克",
|
||||
"CCTV17" to "CCTV17 农业农村",
|
||||
"CGTN" to "CGTN",
|
||||
"CGTN法语频道" to "CGTN 法语频道",
|
||||
"CGTN俄语频道" to "CGTN 俄语频道",
|
||||
"CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道",
|
||||
"CGTN西班牙语频道" to "CGTN 西班牙语频道",
|
||||
// "CGTN外语纪录频道" to "CGTN外语纪录频道",
|
||||
|
||||
"东方卫视" to "东方卫视",
|
||||
"湖南卫视" to "湖南卫视",
|
||||
"湖北卫视" to "湖北卫视",
|
||||
"辽宁卫视" to "辽宁卫视",
|
||||
"江苏卫视" to "江苏卫视",
|
||||
"江西卫视" to "江西卫视",
|
||||
"山东卫视" to "山东卫视",
|
||||
"广东卫视" to "广东卫视",
|
||||
"广西卫视" to "广西卫视",
|
||||
"重庆卫视" to "重庆卫视",
|
||||
"河南卫视" to "河南卫视",
|
||||
"河北卫视" to "河北卫视",
|
||||
"贵州卫视" to "贵州卫视",
|
||||
"北京卫视" to "北京卫视",
|
||||
"黑龙江卫视" to "黑龙江卫视",
|
||||
"浙江卫视" to "浙江卫视",
|
||||
"安徽卫视" to "安徽卫视",
|
||||
"深圳卫视" to "深圳卫视",
|
||||
"四川卫视" to "四川卫视",
|
||||
"福建东南卫视" to "东南卫视",
|
||||
"海南卫视" to "海南卫视",
|
||||
).entries.associate { (key, value) -> value to key }
|
||||
|
||||
private var updateByYSP = false
|
||||
|
||||
private val _videoUrl = MutableLiveData<List<String>>()
|
||||
val videoUrl: LiveData<List<String>>
|
||||
get() = _videoUrl
|
||||
|
||||
private val _pid = MutableLiveData<String>()
|
||||
val pid: LiveData<String>
|
||||
get() = _pid
|
||||
|
||||
private val _sid = MutableLiveData<String>()
|
||||
val sid: LiveData<String>
|
||||
get() = _sid
|
||||
|
||||
private val _backgroundImage = MutableLiveData<String>()
|
||||
val backgroundImage: LiveData<String>
|
||||
get() = _backgroundImage
|
||||
|
||||
// 方法用于更新背景图信息
|
||||
fun updateBackgroundImage(url: String) {
|
||||
_backgroundImage.value = url
|
||||
}
|
||||
|
||||
fun updateVideoUrl(url: String) {
|
||||
tv.videoUrl = listOf(url)
|
||||
tv.videoIndex = 0
|
||||
_videoUrl.value = listOf(url)
|
||||
}
|
||||
|
||||
fun updateVideoUrlByYSP(url: String) {
|
||||
updateByYSP = true
|
||||
updateVideoUrl(url)
|
||||
}
|
||||
|
||||
init {
|
||||
_videoUrl.value = tv.videoUrl
|
||||
_pid.value = tv.pid
|
||||
_sid.value = tv.sid
|
||||
}
|
||||
|
||||
fun updateByYSP(): Boolean {
|
||||
return updateByYSP
|
||||
}
|
||||
|
||||
fun update(t: TV) {
|
||||
tv = t
|
||||
}
|
||||
|
||||
fun getTV(): TV {
|
||||
return tv
|
||||
}
|
||||
|
||||
fun ysp(): String? {
|
||||
return mapping[tv.title]
|
||||
}
|
||||
|
||||
fun getBackgroundImage(): String {
|
||||
return tv.logo ?: ""
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user