Compare commits

...
14 Commits
Author SHA1 Message Date
Li ZongYing 4fb27ba502 fix channel number did not disappear 2024-02-05 06:12:01 +08:00
李宗英 1714633cb7 Merge pull request #205 from LeGend-wLw/main
移除硬编码,更改为json格式,并支持从服务器上动态更新channels。
2024-02-04 22:46:08 +08:00
LeGend-wLw f7b024f6da 防止多次初始化 2024-02-04 16:42:56 +08:00
LeGend-wLw dd8df63b01 添加初始化TVList行为 2024-02-04 16:42:38 +08:00
LeGend-wLw a4c95efd71 添加从服务器上获取channel.json逻辑,但未启用 2024-02-04 16:37:59 +08:00
LeGend-wLw 9f32fa3673 移除MustToken和needToken,移动到TV类中 2024-02-04 16:37:20 +08:00
LeGend-wLw b3d0093ab0 修改为从json文件中读取channel信息 2024-02-04 16:36:34 +08:00
LeGend-wLw 5798d3a5fe 更改TV类中成员,使能和json对应 2024-02-04 16:36:05 +08:00
LeGend-wLw 4eb90de79d 当前转换成json的channel信息 2024-02-04 16:35:38 +08:00
LeGend-wLw b8232971e2 服务器地址,未更新 2024-02-04 16:35:20 +08:00
LeGend-wLw bc3681b0a6 将从tvModel中获取needToken和MustToken改成从TV类中获取needToken和MustToken 2024-02-04 16:34:59 +08:00
Li ZongYing 088808c3fd fix retry bug 2024-02-03 20:07:08 +08:00
Li ZongYing 73239a6677 replay 2024-02-01 17:04:02 +08:00
Li ZongYing cc2514a81a performance optimization 2024-01-28 16:00:33 +08:00
19 changed files with 1333 additions and 441 deletions
+29 -1
View File
@@ -1,6 +1,6 @@
# 我的电视
安卓电视直播软件,内置直播源
电视直播软件,安装即可使用
## 使用
@@ -14,6 +14,18 @@
## 更新日志
### v1.5.2(通用版)
* 修复APP恢复后频道号、频道列表不自动消失的问题
### v1.5.1(高版本专用)
* 性能优化
### v1.5.0(通用版)
* 修复部分情况下APP切换后无法继续播放的问题
### v1.4.9(高版本专用)
* 同步v1.4.8
@@ -82,6 +94,22 @@
adb install my-tv.apk
```
## TODO
* 音量不同
* 大湾区卫视、广东4k超高清、广东珠江
* CETV教育频道
* CHC高清三个电影频道
* 地方频道
* 收藏夹
* 自定义源
* 凤凰卫视、凤凰资讯台
* 海外
* 1.5.0 无法安装,1.5.1 可以安装
* 获取系统时间
* 选中的图标比例能否相差更大
* 自动重连
## 赞赏
![image](./screenshots/appreciate.jpeg)
+2 -2
View File
@@ -5,7 +5,7 @@ plugins {
android {
namespace 'com.lizongying.mytv'
compileSdk 33
compileSdk 34
viewBinding {
enabled = true
@@ -90,7 +90,7 @@ static def VersionName() {
}
dependencies {
def media3_version = "1.1.1"
def media3_version = "1.2.1"
implementation "androidx.media3:media3-ui:$media3_version"
+5 -3
View File
@@ -9,17 +9,19 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:largeHeap="true"
android:icon="@drawable/logo"
android:logo="@drawable/logo"
android:banner="@drawable/banner"
android:label="@string/app_name"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.MyTV">
<activity
android:keepScreenOn="true"
android:name=".MainActivity"
android:banner="@drawable/banner"
android:exported="true"
android:icon="@drawable/logo"
android:logo="@drawable/logo"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Binary file not shown.
Binary file not shown.
@@ -48,6 +48,13 @@ class ChannelFragment : Fragment() {
}
}
override fun onResume() {
super.onResume()
if (view?.visibility == View.VISIBLE) {
handler.postDelayed(hideRunnable, delay)
}
}
override fun onPause() {
super.onPause()
handler.removeCallbacks(hideRunnable)
@@ -35,16 +35,17 @@ class MainActivity : FragmentActivity() {
private lateinit var gestureDetector: GestureDetector
private val handler = Handler()
private val delay: Long = 4000
private val delayHideHelp: Long = 10000
private val delayHideMain: Long = 5000
private val delayHideSetting: Long = 10000
private lateinit var sharedPref: SharedPreferences
lateinit var sharedPref: SharedPreferences
private var channelReversal = false
private var channelNum = true
private var versionName = ""
override fun onCreate(savedInstanceState: Bundle?) {
Log.i(TAG, "onCreate")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@@ -60,7 +61,6 @@ class MainActivity : FragmentActivity() {
.add(R.id.main_browse_fragment, mainFragment)
.hide(mainFragment)
.commit()
mainFragment.view?.requestFocus()
}
gestureDetector = GestureDetector(this, GestureListener())
@@ -132,11 +132,11 @@ class MainActivity : FragmentActivity() {
}
fun keepRunnable() {
handler.removeCallbacks(hideRunnable)
handler.postDelayed(hideRunnable, delay)
handler.removeCallbacks(hideMain)
handler.postDelayed(hideMain, delayHideMain)
}
private val hideRunnable = Runnable {
private val hideMain = Runnable {
if (!mainFragment.isHidden) {
supportFragmentManager.beginTransaction().hide(mainFragment).commit()
}
@@ -174,7 +174,7 @@ class MainActivity : FragmentActivity() {
}
override fun onFling(
e1: MotionEvent,
e1: MotionEvent?,
e2: MotionEvent,
velocityX: Float,
velocityY: Float
@@ -222,7 +222,7 @@ class MainActivity : FragmentActivity() {
this.channelNum = channelNum
}
private fun showHelp() {
private fun showSetting() {
if (!mainFragment.isHidden) {
return
}
@@ -230,15 +230,15 @@ class MainActivity : FragmentActivity() {
Log.i(TAG, "settingFragment ${settingFragment.isVisible}")
if (!settingFragment.isVisible) {
settingFragment.show(supportFragmentManager, "setting")
handler.removeCallbacks(hideHelp)
handler.postDelayed(hideHelp, delayHideHelp)
handler.removeCallbacks(hideSetting)
handler.postDelayed(hideSetting, delayHideSetting)
} else {
handler.removeCallbacks(hideHelp)
handler.removeCallbacks(hideSetting)
settingFragment.dismiss()
}
}
private val hideHelp = Runnable {
private val hideSetting = Runnable {
if (settingFragment.isVisible) {
settingFragment.dismiss()
}
@@ -359,27 +359,27 @@ class MainActivity : FragmentActivity() {
}
KeyEvent.KEYCODE_BOOKMARK -> {
showHelp()
showSetting()
return true
}
KeyEvent.KEYCODE_UNKNOWN -> {
showHelp()
showSetting()
return true
}
KeyEvent.KEYCODE_HELP -> {
showHelp()
showSetting()
return true
}
KeyEvent.KEYCODE_SETTINGS -> {
showHelp()
showSetting()
return true
}
KeyEvent.KEYCODE_MENU -> {
showHelp()
showSetting()
return true
}
@@ -477,7 +477,7 @@ class MainActivity : FragmentActivity() {
private fun hashSignature(signature: Signature): String {
return try {
val md = MessageDigest.getInstance("SHA-256")
val md = MessageDigest.getInstance("MD5")
md.update(signature.toByteArray())
val digest = md.digest()
digest.let { it -> it.joinToString("") { "%02x".format(it) } }
@@ -487,6 +487,25 @@ class MainActivity : FragmentActivity() {
}
}
override fun onStart() {
Log.i(TAG, "onStart")
super.onStart()
}
override fun onResume() {
Log.i(TAG, "onResume")
super.onResume()
if (!mainFragment.isHidden){
handler.postDelayed(hideMain, delayHideMain)
}
}
override fun onPause() {
Log.i(TAG, "onPause")
super.onPause()
handler.removeCallbacks(hideMain)
}
companion object {
private const val TAG = "MainActivity"
private const val CHANNEL_REVERSAL = "channel_reversal"
@@ -1,6 +1,5 @@
package com.lizongying.mytv
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.os.Handler
@@ -35,7 +34,7 @@ class MainFragment : BrowseSupportFragment() {
var tvListViewModel = TVListViewModel()
private var sharedPref: SharedPreferences? = null
private lateinit var sharedPref: SharedPreferences
private var lastVideoUrl = ""
@@ -45,15 +44,21 @@ class MainFragment : BrowseSupportFragment() {
private var ready = 0
override fun onCreate(savedInstanceState: Bundle?) {
Log.i(TAG, "onCreate")
super.onCreate(savedInstanceState)
headersState = HEADERS_DISABLED
}
override fun onStart() {
Log.i(TAG, "onStart")
super.onStart()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
activity?.let { request.initYSP(it) }
sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)
sharedPref = (activity as? MainActivity)?.sharedPref!!
loadRows()
@@ -84,9 +89,8 @@ class MainFragment : BrowseSupportFragment() {
tvViewModel.change.observe(viewLifecycleOwner) { _ ->
if (tvViewModel.change.value != null) {
val title = tvViewModel.title.value
Log.i(TAG, "switch $title")
if (tvViewModel.pid.value != "") {
Log.i(TAG, "request $title ${tvViewModel.pid.value}")
Log.i(TAG, "request $title")
lifecycleScope.launch(Dispatchers.IO) {
tvViewModel.let { request.fetchData(it) }
}
@@ -135,6 +139,7 @@ class MainFragment : BrowseSupportFragment() {
val cardPresenter = CardPresenter(viewLifecycleOwner)
var idx: Long = 0
context?.let { TVList.init(it) }
for ((k, v) in TVList.list) {
val listRowAdapter = ArrayObjectAdapter(cardPresenter)
for ((idx2, v1) in v.withIndex()) {
@@ -152,7 +157,7 @@ class MainFragment : BrowseSupportFragment() {
adapter = rowsAdapter
itemPosition = sharedPref?.getInt(POSITION, 0)!!
itemPosition = sharedPref.getInt(POSITION, 0)
if (itemPosition >= tvListViewModel.size()) {
itemPosition = 0
}
@@ -300,7 +305,7 @@ class MainFragment : BrowseSupportFragment() {
inner class UpdateProgramRunnable : Runnable {
override fun run() {
tvListViewModel.tvListViewModel.value?.filter { it.programId.value != null }
tvListViewModel.tvListViewModel.value?.filter { it.programId.value != null && it.programId.value != "" }
?.forEach { tvViewModel ->
updateProgram(
tvViewModel
@@ -310,14 +315,19 @@ class MainFragment : BrowseSupportFragment() {
}
}
override fun onResume() {
Log.i(TAG, "onResume")
super.onResume()
}
override fun onStop() {
Log.i(TAG, "onStop")
super.onStop()
with(sharedPref!!.edit()) {
with(sharedPref.edit()) {
putInt(POSITION, itemPosition)
apply()
}
Log.i(TAG, "POSITION saved")
Log.i(TAG, "$POSITION saved")
}
override fun onDestroy() {
@@ -326,11 +336,6 @@ class MainFragment : BrowseSupportFragment() {
handler.removeCallbacks(mUpdateProgramRunnable)
}
override fun onResume() {
super.onResume()
view?.post { view?.requestFocus() }
}
companion object {
private const val TAG = "MainFragment"
private const val POSITION = "position"
@@ -74,23 +74,31 @@ class PlayerFragment : Fragment() {
@OptIn(UnstableApi::class)
fun play(tvViewModel: TVViewModel) {
this.tvViewModel = tvViewModel
val videoUrlCurrent = tvViewModel.getVideoUrlCurrent()
playerView?.player?.run {
setMediaItem(MediaItem.fromUri(videoUrlCurrent))
setMediaItem(MediaItem.fromUri(tvViewModel.getVideoUrlCurrent()))
prepare()
}
}
override fun onStart() {
Log.i(TAG, "onStart")
super.onStart()
if (playerView != null) {
playerView!!.player?.play()
if (playerView != null && playerView!!.player?.isPlaying == false) {
Log.i(TAG, "replay")
playerView!!.player?.prepare()
} else {
Log.i(TAG, "playing")
}
}
override fun onStop() {
super.onStop()
if (playerView != null) {
override fun onResume() {
Log.i(TAG, "onResume")
super.onResume()
}
override fun onPause() {
super.onPause()
if (playerView != null && playerView!!.player?.isPlaying == true) {
playerView!!.player?.stop()
}
}
+144 -46
View File
@@ -32,10 +32,16 @@ class Request {
private var yspBtraceService: YSPBtraceService = ApiClient().yspBtraceService
private var yspProtoService: YSPProtoService = ApiClient().yspProtoService
private var ysp: YSP? = null
private var token = ""
// TODO onDestroy
private val handler = Handler(Looper.getMainLooper())
private lateinit var myRunnable: MyRunnable
private lateinit var btraceRunnable: BtraceRunnable
private var tokenRunnable: TokenRunnable = TokenRunnable()
private val regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
private val input =
"""{"mver":"1","subver":"1.2","host":"www.yangshipin.cn/#/tv/home?pid=","referer":"","canvas":"YSPANGLE(Apple,AppleM1Pro,OpenGL4.1)"}""".toByteArray()
private var mapping = mapOf(
"CCTV4K" to "CCTV4K 超高清",
@@ -85,16 +91,22 @@ class Request {
"新疆卫视" to "新疆卫视",
)
init {
handler.post(tokenRunnable)
}
fun initYSP(context: Context) {
ysp = YSP(context)
//TODO 不确定在哪里初始化
TVList.init(context)
}
var call: Call<LiveInfo>? = null
fun fetchVideo(tvModel: TVViewModel, cookie: String) {
call?.cancel()
if (::myRunnable.isInitialized) {
handler.removeCallbacks(myRunnable)
if (::btraceRunnable.isInitialized) {
handler.removeCallbacks(btraceRunnable)
}
val title = tvModel.title.value
@@ -115,7 +127,6 @@ class Request {
Base64.DEFAULT
)
val decodedString = String(decodedBytes)
val regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
val matchResult = regex.find(decodedString)
if (matchResult != null) {
val (key, iv) = matchResult.destructured
@@ -125,17 +136,28 @@ class Request {
keyBytes + byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
ivBytes
).uppercase()
Log.d(TAG, "$title url $url")
// Log.d(TAG, "$title url $url")
tvModel.addVideoUrl(url)
tvModel.allReady()
tvModel.retryTimes = 0
myRunnable = MyRunnable(tvModel)
handler.post(myRunnable)
btraceRunnable = BtraceRunnable(tvModel)
handler.post(btraceRunnable)
} else {
Log.e(TAG, "$title key error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
if (tvModel.getTV().needToken) {
if (tvModel.tokenRetryTimes == tvModel.tokenRetryMaxTimes) {
if (!tvModel.getTV().mustToken) {
fetchVideo(tvModel, cookie)
}
} else {
token = ""
fetchVideo(tvModel)
}
} else {
fetchVideo(tvModel, cookie)
}
}
}
} else {
@@ -146,7 +168,18 @@ class Request {
Log.e(TAG, "$title url error $request $liveInfo")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
if (tvModel.getTV().needToken) {
if (tvModel.tokenRetryTimes == tvModel.tokenRetryMaxTimes) {
if (!tvModel.getTV().mustToken) {
fetchVideo(tvModel, cookie)
}
} else {
token = ""
fetchVideo(tvModel)
}
} else {
fetchVideo(tvModel, cookie)
}
}
}
}
@@ -154,60 +187,126 @@ class Request {
Log.e(TAG, "$title status error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
if (tvModel.getTV().needToken) {
if (tvModel.tokenRetryTimes == tvModel.tokenRetryMaxTimes) {
if (!tvModel.getTV().mustToken) {
fetchVideo(tvModel, cookie)
}
} else {
token = ""
fetchVideo(tvModel)
}
} else {
fetchVideo(tvModel, cookie)
}
}
}
}
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
Log.e(TAG, "$title request error")
Log.e(TAG, "$title request error $t")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
fetchVideo(tvModel, cookie)
if (tvModel.getTV().needToken) {
if (tvModel.tokenRetryTimes == tvModel.tokenRetryMaxTimes) {
if (!tvModel.getTV().mustToken) {
fetchVideo(tvModel, cookie)
}
} else {
token = ""
fetchVideo(tvModel)
}
} else {
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 token = response.body()?.data?.token
Log.i(TAG, "info success $token")
val cookie =
"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)
if (token == "") {
yspTokenService.getInfo()
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful) {
token = response.body()?.data?.token!!
Log.i(TAG, "info success $token")
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; yspappid=519748109;yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchVideo(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
if (tvModel.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
fetchVideo(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; yspappid=519748109"
fetchVideo(tvModel, cookie)
}
}
}
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
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.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
fetchVideo(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; yspappid=519748109"
fetchVideo(tvModel, cookie)
}
}
}
}
})
}
fun fetchData(tvModel: TVViewModel) {
if (tvModel.needToken) {
fetchVideo(tvModel)
})
} else {
val cookie = "vplatform=109"
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; yspappid=519748109;yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchVideo(tvModel, cookie)
}
}
inner class MyRunnable(private val tvModel: TVViewModel) : Runnable {
fun fetchData(tvModel: TVViewModel) {
if (tvModel.getTV().needToken) {
fetchVideo(tvModel)
} else {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; yspappid=519748109"
fetchVideo(tvModel, cookie)
}
}
inner class TokenRunnable : Runnable {
override fun run() {
fetchToken()
handler.postDelayed(this, 600000)
}
}
fun fetchToken() {
yspTokenService.getInfo()
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful) {
token = response.body()?.data?.token!!
Log.i(TAG, "info success $token")
} else {
Log.e(TAG, "token status error")
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "token request error $t")
}
})
}
inner class BtraceRunnable(private val tvModel: TVViewModel) : Runnable {
override fun run() {
fetchBtrace(tvModel)
handler.postDelayed(this, 60000)
@@ -304,8 +403,10 @@ class Request {
val program = response.body()
if (program != null) {
tvViewModel.addProgram(program.dataListList)
Log.i(TAG, "$title program ${program.dataListList.size}")
Log.d(TAG, "$title program ${program.dataListList.size}")
}
} else {
Log.w(TAG, "$title program error")
}
}
@@ -316,15 +417,12 @@ class Request {
}
private fun encryptTripleDES(key: ByteArray, iv: ByteArray): String {
val plaintext =
"""{"mver":"1","subver":"1.2","host":"www.yangshipin.cn/#/tv/home?pid=","referer":"","canvas":"YSPANGLE(Apple,AppleM1Pro,OpenGL4.1)"}"""
return try {
val keySpec = SecretKeySpec(key, "DESede")
val ivSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
val encryptedBytes = cipher.doFinal(plaintext.toByteArray())
return encryptedBytes.let { it -> it.joinToString("") { "%02x".format(it) } }
return cipher.doFinal(input).let { it -> it.joinToString("") { "%02x".format(it) } }
} catch (e: Exception) {
e.printStackTrace()
""
@@ -7,10 +7,14 @@ data class TV(
var title: String,
var videoUrl: List<String>,
var videoIndex: Int = 0,
var channel: String = "",
var logo: String = "",
var pid: String = "",
var sid: String = "",
var programId: String = "",
var needToken:Boolean=false,
var mustToken:Boolean=false,
) : Serializable {
override fun toString(): String {
+39 -301
View File
@@ -1,316 +1,54 @@
package com.lizongying.mytv
import android.content.Context
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File
object TVList {
val list: Map<String, List<TV>> by lazy {
setupTV()
lateinit var list: Map<String, List<TV>>
private val channels = "channels.json"
fun init(context: Context) {
if (::list.isInitialized) {
return
}
synchronized(this) {
if (::list.isInitialized) {
return
}
list = setupTV(context)
}
}
private var mappingLogo = mapOf(
"CCTV4K 超高清" to "https://resources.yangshipin.cn/assets/oms/image/202306/3e9d06fd7244d950df5838750f1c6ac3456e172b51caca2c16d2282125b111e8.png?imageMogr2/format/webp",
"CCTV8K 超高清" to "",
"CCTV1 综合" to "https://resources.yangshipin.cn/assets/oms/image/202306/d57905b93540bd15f0c48230dbbbff7ee0d645ff539e38866e2d15c8b9f7dfcd.png?imageMogr2/format/webp",
"CCTV2 财经" to "https://resources.yangshipin.cn/assets/oms/image/202306/20115388de0207131af17eac86c33049b95d69eaff064e55653a1b941810a006.png?imageMogr2/format/webp",
"CCTV3 综艺" to "https://resources.yangshipin.cn/assets/oms/image/202306/7b7a65c712450da3deb6ca66fbacf4f9aee00d3f20bd80eafb5ada01ec63eb3a.png?imageMogr2/format/webp",
"CCTV4 中文国际" to "https://resources.yangshipin.cn/assets/oms/image/202306/f357e58fdbcc076a3d65e1f958c942b2e14f14342c60736ceed98b092d35356a.png?imageMogr2/format/webp",
"CCTV5 体育" to "https://resources.yangshipin.cn/assets/oms/image/202306/0a6a7138952675983a3d854df7688557b286d59aa06166edae51506f9204d655.png?imageMogr2/format/webp",
"CCTV5+ 体育赛事" to "https://resources.yangshipin.cn/assets/oms/image/202306/649ad76a90bfef55b05db9fe52e006487280f619089099d5dc971e387fc6eff0.png?imageMogr2/format/webp",
"CCTV6 电影" to "https://resources.yangshipin.cn/assets/oms/image/202306/741515efda91f03f455df8a7da4ee11fa9329139c276435cf0a9e2af398d5bf2.png?imageMogr2/format/webp",
"CCTV7 国防军事" to "https://resources.yangshipin.cn/assets/oms/image/202306/b29af94e295ebdf646cefb68122c429b9cd921f498ca20d2d8070252536f9ff9.png?imageMogr2/format/webp",
"CCTV8 电视剧" to "https://resources.yangshipin.cn/assets/oms/image/202306/ad51de94426a0ba039e6dd6a8534ea98ecc813a6176bde87b4f18cc34d6d7590.png?imageMogr2/format/webp",
"CCTV9 记录" to "https://resources.yangshipin.cn/assets/oms/image/202306/2ed1b4deeca179d5db806bb941790f82eb92a1b7299c1c38fe027f95a5caee5e.png?imageMogr2/format/webp",
"CCTV10 科教" to "https://resources.yangshipin.cn/assets/oms/image/202306/aa6157ec65188cd41826e5a2f088c3d6d153205f5f6428258d12c59999e221aa.png?imageMogr2/format/webp",
"CCTV11 戏曲" to "https://resources.yangshipin.cn/assets/oms/image/202306/ed12ed7c7a1034dae4350011fe039284c5d5a836506b28c9e32e3c75299625c0.png?imageMogr2/format/webp",
"CCTV12 社会与法" to "https://resources.yangshipin.cn/assets/oms/image/202306/484083cffaa40df7e659565e8cb4d1cc740158a185512114167aa21fa0c59240.png?imageMogr2/format/webp",
"CCTV13 新闻" to "https://resources.yangshipin.cn/assets/oms/image/202306/266da7b43c03e2312186b4a999e0f060e8f15b10d2cc2c9aa32171819254cf1a.png?imageMogr2/format/webp",
"CCTV14 少儿" to "https://resources.yangshipin.cn/assets/oms/image/202306/af6b603896938dc346fbb16abfc63c12cba54b0ec9d18770a15d347d115f12d5.png?imageMogr2/format/webp",
"CCTV15 音乐" to "https://resources.yangshipin.cn/assets/oms/image/202306/2ceee92188ef684efe0d8b90839c4f3ad450d179dc64d59beff417059453af47.png?imageMogr2/format/webp",
"CCTV16 奥林匹克" to "https://resources.yangshipin.cn/assets/oms/image/202306/53793fa7bacd3a93ff6dc5d2758418985e1f952a316c335d663b572d8bdcd74d.png?imageMogr2/format/webp",
"CCTV17 农业农村" to "https://resources.yangshipin.cn/assets/oms/image/202306/ddef563072f8bad2bea5b9e52674cb7b4ed50efb20c26e61994dfbdf05c1e3c0.png?imageMogr2/format/webp",
"CGTN" to "https://resources.yangshipin.cn/assets/oms/image/202306/a72dff758ca1c17cd0ecc8cedc11b893d208f409d5e6302faa0e9d298848abc3.png?imageMogr2/format/webp",
"CGTN 法语频道" to "https://resources.yangshipin.cn/assets/oms/image/202306/a8d0046a47433d952bf6ed17062deb8bd2184ba9aec0f7781df6bf9487a3ffcf.png?imageMogr2/format/webp",
"CGTN 俄语频道" to "https://resources.yangshipin.cn/assets/oms/image/202306/bf0a820893cbaf20dd0333e27042e1ef9c8806e5b602b6a8c95af399db0bc77a.png?imageMogr2/format/webp",
"CGTN 阿拉伯语频道" to "https://resources.yangshipin.cn/assets/oms/image/202306/2e44e2aa3e7a1cedf07fd0ae59fe69e86a60a2632660a006e3e9e7397b2d107e.png?imageMogr2/format/webp",
"CGTN 西班牙语频道" to "https://resources.yangshipin.cn/assets/oms/image/202309/7c337e3dbe64402ec7e4678a619a4a6d95144e42f35161181ff78e143b7cf67a.png?imageMogr2/format/webp",
"CGTN 纪录频道" to "https://resources.yangshipin.cn/assets/oms/image/202309/74d3ac436a7e374879578de1d87a941fbf566d39d5632b027c5097891ed32bd5.png?imageMogr2/format/webp",
"风云剧场" to "https://resources.yangshipin.cn/assets/oms/image/202306/4d549e53e6d0f632d5a633d1945280797b153e588f919221a07faa869812cc89.png?imageMogr2/format/webp",
"第一剧场" to "https://resources.yangshipin.cn/assets/oms/image/202306/a556bd7d93ce65e18f243a8892b5604f4faa994a4897315914216a710a706208.png?imageMogr2/format/webp",
"怀旧剧场" to "https://resources.yangshipin.cn/assets/oms/image/202306/5661bd04fecdb6e899f801147a22ab5d3a475bf2b62e30aec2c0023190ebc9b1.png?imageMogr2/format/webp",
"世界地理" to "https://resources.yangshipin.cn/assets/oms/image/202306/bb3c6c9e145d698137f5bb64a582021a01b51344b929003630eb769ea65832a9.png?imageMogr2/format/webp",
"风云音乐" to "https://resources.yangshipin.cn/assets/oms/image/202306/bbf1d024c5228b8dd128b0e3cb1717d173fab4ee84c3a4c8a57b1a215362ca3b.png?imageMogr2/format/webp",
"兵器科技" to "https://resources.yangshipin.cn/assets/oms/image/202306/4c6b6a6d3839889f34d33db3c2f80233b26b74d3489b393487635f8704e70796.png?imageMogr2/format/webp",
"风云足球" to "https://resources.yangshipin.cn/assets/oms/image/202306/cd1e2bb52b06a991de168733e5ff0f1d85adc8042d40c8f393f723543e5dd08a.png?imageMogr2/format/webp",
"高尔夫网球" to "https://resources.yangshipin.cn/assets/oms/image/202306/cdd1b31ede7a5ad049ed53d9a072422f829e72dd062ed2c19e077fdd01699071.png?imageMogr2/format/webp",
"女性时尚" to "https://resources.yangshipin.cn/assets/oms/image/202306/fa28955ce8b2539d728bf4c6a13a46ff57ad76eae46627f7bcfb1ed8a613d3fc.png?imageMogr2/format/webp",
"央视文化精品" to "https://resources.yangshipin.cn/assets/oms/image/202306/14ac5ce40482cacd3d4b37435222bfe86af2b452a2f04ecbfc1d13d76edd7c57.png?imageMogr2/format/webp",
"央视台球" to "https://resources.yangshipin.cn/assets/oms/image/202306/10e14a92478011aa6c3c8562e62127f3b1908e29fcd78e4b2b24b9e6d3ec2fbc.png?imageMogr2/format/webp",
"电视指南" to "https://resources.yangshipin.cn/assets/oms/image/202306/244d72c0eb1615ed7d51c2f5db5a67f306aa3f58c05bc2d34de3aa7e956dc8c9.png?imageMogr2/format/webp",
"卫生健康" to "https://resources.yangshipin.cn/assets/oms/image/202306/54a6863656fdfd8f803be193ddf22441c5000a108833889816fd2d8911715ce8.png?imageMogr2/format/webp",
"东方卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/9bd372ca292a82ce3aa08772b07efc4af1f85c21d1f268ea33440c49e9a0a488.png?imageMogr2/format/webp",
"湖南卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/4120e89d3079d08aa17d382f69a2308ec70839b278367763c34a34666c75cb88.png?imageMogr2/format/webp",
"湖北卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/7a6be5a2bb1dc53a945c016ff1f525dc4a84c51db371c15c89aa55404b0ba784.png?imageMogr2/format/webp",
"辽宁卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/ac4ed6058a87c101ae7147ebc38905d0cae047fb73fd277ee5049b84f52bda36.png?imageMogr2/format/webp",
"江苏卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/380ad685c0c1d5b2c902246b8d2df6d3f9b45e2837abcfe493075bbded597a31.png?imageMogr2/format/webp",
"江西卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/3c760d0d00463855890e8a1864ea4a6b6dd66b90c29b4ac714a4b17c16519871.png?imageMogr2/format/webp",
"山东卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/22d403f07a7cf5410b3ad3ddb65a11aa229a32475fac213f5344c9f0ec330ca1.png?imageMogr2/format/webp",
"广东卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/28886880a4dc0f06fb7e0a528a1def0591d61a65870e29176ede0cc92033bbfd.png?imageMogr2/format/webp",
"广西卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/54b7e97cb816bb223fe05f3fc44da2c7820eb66e8550c19d23100f2c414ecc38.png?imageMogr2/format/webp",
"重庆卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/657651f411de2673d1770d9a78b44c1265704f7468cc41d4be7f51d630768494.png?imageMogr2/format/webp",
"河南卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/74925962148a6d31c85808b6cd4e444c2a54bab393d2c5fc85e960b50e22fa86.png?imageMogr2/format/webp",
"河北卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/d545becdc81c60197b08c7f47380705e4665ed3fe55efc8b855e486f6e655378.png?imageMogr2/format/webp",
"贵州卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/4eb45f4781d33d872af027dc01c941559aab55667dd99cc5c22bef7037807b13.png?imageMogr2/format/webp",
"北京卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/f4f23633c578beea49a3841d88d3490100f029ee349059fa532869db889872c5.png?imageMogr2/format/webp",
"黑龙江卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/d8273ae9be698ce2db21f5b886ecac95a73429593f93713c60ed8c12c38bf0d3.png?imageMogr2/format/webp",
"浙江卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/a66c836bd98ba3e41a2e9a570d4b9c50dedc6839e9de333e2e78212ad505f37e.png?imageMogr2/format/webp",
"安徽卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/f35fa04b51b1ee4984b03578b65403570868ebca03c6c01e11b097f999a58d9b.png?imageMogr2/format/webp",
"深圳卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/d59fec04c902e3581c617136d02d4b9b8c4cbe64272781ddd3525e80c823edb7.png?imageMogr2/format/webp",
"四川卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/3276a414ae0eaa0f116f2045cd913367967d0c7c1e978e8621ac3879436c6ed7.png?imageMogr2/format/webp",
"东南卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/3208fe6564a293c21b711333fb3edb05bb5b406cff840573c9a8d839680a1579.png?imageMogr2/format/webp",
"海南卫视" to "https://resources.yangshipin.cn/assets/oms/image/202306/6e060391fde0469801fc3d84dbf204b4f8d650d251f17d7595a6964c0bb99e81.png?imageMogr2/format/webp",
"天津卫视" to "",
"新疆卫视" to "",
)
private var mappingEPG = mapOf(
"CCTV4K 超高清" to "600002264",
"CCTV8K 超高清" to "600156816",
"CCTV1 综合" to "600001859",
"CCTV2 财经" to "600001800",
"CCTV3 综艺" to "600001801",
"CCTV4 中文国际" to "600001814",
"CCTV5 体育" to "600001818",
"CCTV5+ 体育赛事" to "600001817",
"CCTV6 电影" to "600001802",
"CCTV7 国防军事" to "600004092",
"CCTV8 电视剧" to "600001803",
"CCTV9 记录" to "600004078",
"CCTV10 科教" to "600001805",
"CCTV11 戏曲" to "600001806",
"CCTV12 社会与法" to "600001807",
"CCTV13 新闻" to "600001811",
"CCTV14 少儿" to "600001809",
"CCTV15 音乐" to "600001815",
"CCTV16 奥林匹克" to "600098637",
"CCTV17 农业农村" to "600001810",
"CGTN" to "600014550",
"CGTN 法语频道" to "600084704",
"CGTN 俄语频道" to "600084758",
"CGTN 阿拉伯语频道" to "600084782",
"CGTN 西班牙语频道" to "600084744",
"CGTN 记录频道" to "600084781",
"风云剧场" to "600099658",
"第一剧场" to "600099655",
"怀旧剧场" to "600099620",
"世界地理" to "600099637",
"风云音乐" to "600099660",
"兵器科技" to "600099649",
"风云足球" to "600099636",
"高尔夫网球" to "600099659",
"女性时尚" to "600099650",
"央视文化精品" to "600099653",
"央视台球" to "600099652",
"电视指南" to "600099656",
"卫生健康" to "600099651",
"东方卫视" to "600002483",
"湖南卫视" to "600002475",
"湖北卫视" to "600002508",
"辽宁卫视" to "600002505",
"江苏卫视" to "600002521",
"江西卫视" to "600002503",
"山东卫视" to "600002513",
"广东卫视" to "600002485",
"广西卫视" to "600002509",
"重庆卫视" to "600002531",
"河南卫视" to "600002525",
"河北卫视" to "600002493",
"贵州卫视" to "600002490",
"北京卫视" to "600002309",
"黑龙江卫视" to "600002498",
"浙江卫视" to "600002520",
"安徽卫视" to "600002532",
"深圳卫视" to "600002481",
"四川卫视" to "600002516",
"东南卫视" to "600002484",
"海南卫视" to "600002506",
"天津卫视" to "600152137",
"新疆卫视" to "600152138",
)
private var mappingVideo = mapOf(
"CCTV4K 超高清" to arrayOf("600002264", "2000266303"),
"CCTV8K 超高清" to arrayOf("600156816", "2020603421"),
"CCTV1 综合" to arrayOf("600001859", "2000210103"),
"CCTV2 财经" to arrayOf("600001800", "2000203603"),
"CCTV3 综艺" to arrayOf("600001801", "2000203803"),
"CCTV4 中文国际" to arrayOf("600001814", "2000204803"),
"CCTV5 体育" to arrayOf("600001818", "2000205103"),
"CCTV5+ 体育赛事" to arrayOf("600001817", "2000204503"),
"CCTV6 电影" to arrayOf("600001802", "2013693901"),
"CCTV7 国防军事" to arrayOf("600004092", "2000510003"),
"CCTV8 电视剧" to arrayOf("600001803", "2000203903"),
"CCTV9 记录" to arrayOf("600004078", "2000499403"),
"CCTV10 科教" to arrayOf("600001805", "2000203503"),
"CCTV11 戏曲" to arrayOf("600001806", "2000204103"),
"CCTV12 社会与法" to arrayOf("600001807", "2000202603"),
"CCTV13 新闻" to arrayOf("600001811","2000204603"),
"CCTV14 少儿" to arrayOf("600001809", "2000204403"),
"CCTV15 音乐" to arrayOf("600001815", "2000205003"),
"CCTV16 奥林匹克" to arrayOf("600098637", "2012375003"),
"CCTV17 农业农村" to arrayOf("600001810", "2000204203"),
"CGTN" to arrayOf("600014550", "2001656803"),
"CGTN 法语频道" to arrayOf("600084704", "2010153503"),
"CGTN 俄语频道" to arrayOf("600084758", "2010152603"),
"CGTN 阿拉伯语频道" to arrayOf("600084782", "2010155203"),
"CGTN 西班牙语频道" to arrayOf("600084744", "2010152503"),
"CGTN 记录频道" to arrayOf("600084781", "2010155403"),
"风云剧场" to arrayOf("600099658", "2012513603"),
"第一剧场" to arrayOf("600099655", "2012514403"),
"怀旧剧场" to arrayOf("600099620", "2012511203"),
"世界地理" to arrayOf("600099637", "2012513303"),
"风云音乐" to arrayOf("600099660", "2012514103"),
"兵器科技" to arrayOf("600099649", "2012513403"),
"风云足球" to arrayOf("600099636", "2012514203"),
"高尔夫网球" to arrayOf("600099659", "2012512503"),
"女性时尚" to arrayOf("600099650", "2012513903"),
"央视文化精品" to arrayOf("600099653", "2012513803"),
"央视台球" to arrayOf("600099652", "2012513703"),
"电视指南" to arrayOf("600099656", "2012514003"),
"卫生健康" to arrayOf("600099651", "2012513503"),
"东方卫视" to arrayOf("600002483", "2000292403"),
"湖南卫视" to arrayOf("600002475", "2000296203"),
"湖北卫视" to arrayOf("600002508", "2000294503"),
"辽宁卫视" to arrayOf("600002505", "2000281303"),
"江苏卫视" to arrayOf("600002521", "2000295603"),
"江西卫视" to arrayOf("600002503", "2000294103"),
"山东卫视" to arrayOf("600002513", "2000294803"),
"广东卫视" to arrayOf("600002485", "2000292703"),
"广西卫视" to arrayOf("600002509", "2000294203"),
"重庆卫视" to arrayOf("600002531", "2000297803"),
"河南卫视" to arrayOf("600002525", "2000296103"),
"河北卫视" to arrayOf("600002493", "2000293403"),
"贵州卫视" to arrayOf("600002490", "2000293303"),
"北京卫视" to arrayOf("600002309", "2000272103"),
"黑龙江卫视" to arrayOf("600002498", "2000293903"),
"浙江卫视" to arrayOf("600002520", "2000295503"),
"安徽卫视" to arrayOf("600002532", "2000298003"),
"深圳卫视" to arrayOf("600002481", "2000292203"),
"四川卫视" to arrayOf("600002516", "2000295003"),
"东南卫视" to arrayOf("600002484", "2000292503"),
"海南卫视" to arrayOf("600002506", "2000291503"),
"天津卫视" to arrayOf("600152137", "2019927003"),
"新疆卫视" to arrayOf("600152138", "2019927403"),
)
private var count: Int = 0
private fun setupTV(): Map<String, List<TV>> {
val tvs = """
央视频道
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://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8
CCTV5 体育,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226395/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 新闻,https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8;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://39.134.24.162/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8
CCTV17 农业农村,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226198/index.m3u8
CCTV5+ 体育赛事,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226221/index.m3u8
CCTV4K 超高清,
CCTV8K 超高清,
风云剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226950/index.m3u8
第一剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226959/index.m3u8
怀旧剧场,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226972/index.m3u8
世界地理,
风云音乐,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226953/index.m3u8
兵器科技,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226975/index.m3u8
风云足球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226984/index.m3u8
高尔夫网球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226978/index.m3u8
女性时尚,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226969/index.m3u8
央视文化精品,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226981/index.m3u8
央视台球,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226956/index.m3u8
电视指南,http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226987/index.m3u8
卫生健康,
地方频道
东方卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226217/index.m3u8
湖南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226307/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226211/index.m3u8
湖北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226477/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226194/index.m3u8
辽宁卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226546/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226201/index.m3u8
江苏卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8
江西卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226344/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225764/index.m3u8
山东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226209/index.m3u8
广东卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226216/index.m3u8
广西卫视,http://live.gxrb.com.cn/tv/gxtvlive03/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225770/index.m3u8
重庆卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226409/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226202/index.m3u8
河南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226480/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225767/index.m3u8
河北卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226406/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225750/index.m3u8
贵州卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226474/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225793/index.m3u8
北京卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225728/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226222/index.m3u8
黑龙江卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226327/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226215/index.m3u8
浙江卫视,http://hw-m-l.cztv.com/channels/lantian/channel01/1080p.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226199/index.m3u8
安徽卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226391/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226203/index.m3u8
深圳卫视,http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8
四川卫视,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/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/3221226341/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225766/index.m3u8
海南卫视,http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226465/index.m3u8;http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225769/index.m3u8
天津卫视,
新疆卫视,
国际频道
CGTN,http://live.cgtn.com/1000/prog_index.m3u8
CGTN 法语频道,https://livefr.cgtn.com/1000f/prog_index.m3u8
CGTN 俄语频道,http://liveru.cgtn.com/1000r/prog_index.m3u8
CGTN 阿拉伯语频道,http://livear.cgtn.com/1000a/prog_index.m3u8
CGTN 西班牙语频道,http://livees.cgtn.com/500e/prog_index.m3u8;http://livees.cgtn.com/1000e/prog_index.m3u8
CGTN 纪录频道,https://livedoc.cgtn.com/500d/prog_index.m3u8
""".trimIndent()
private fun setupTV(context: Context): Map<String, List<TV>> {
val map: MutableMap<String, MutableList<TV>> = mutableMapOf()
val appDirectory = Utils.getAppDirectory(context)
var channel = ""
for (i in tvs.split("\n")) {
if (i.trim() == "") {
continue
}
if (!i.contains(",")) {
channel = i.trim()
if (channel == "移动专区") {
break
//检查当前目录下是否存在channels.json
val file = File(appDirectory, channels)
if (!file.exists()) {
//不存在则从assets中拷贝
file.createNewFile()
context.resources.openRawResource(R.raw.channels).use { input ->
file.outputStream().use { output ->
input.copyTo(output)
}
continue
}
val p = i.split(",")
val titleMap = map[channel] ?: mutableListOf()
val tv = TV(
count,
p[0],
p[1].split(";").map { it.trim() }
)
val logo = mappingLogo[tv.title]
if (logo != null && logo != "") {
tv.logo = logo
}
val programId = mappingEPG[tv.title]
if (programId != null && programId != "") {
tv.programId = programId
}
val video = mappingVideo[tv.title]
if (video != null) {
tv.pid = video[0]
tv.sid = video[1]
}
titleMap.add(tv)
map[channel] = titleMap
count++
}
//读取channels.json,并转换为Map<String,LIst<TV>>
val json = file.readText()
//防止类型擦除
val type = object : TypeToken<Array<TV>>() {}.type
Gson().fromJson<Array<TV>>(json, type)?.forEach {
if (map.containsKey(it.channel)) {
map[it.channel]?.add(it)
} else {
map[it.channel] = mutableListOf(it)
}
}
return map
}
}
+51 -8
View File
@@ -1,10 +1,12 @@
package com.lizongying.mytv
import android.content.Context
import android.content.res.Resources
import android.util.TypedValue
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.*
import java.io.IOException
object Utils {
fun getDateFormat(format: String): String {
@@ -17,17 +19,58 @@ object Utils {
fun dpToPx(dp: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
Resources.getSystem().displayMetrics
TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics
).toInt()
}
fun dpToPx(dp: Int): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
Resources.getSystem().displayMetrics
TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), Resources.getSystem().displayMetrics
).toInt()
}
/**
* 获取可读写的目录
*
* @param context 应用环境信息
*
* @return 可读写的目录
*
*/
fun getAppDirectory(context: Context): File {
return context.filesDir
}
/**
* 更新channels.json
*
* @param context 应用环境信息
*
* @return 无
*
* @throws IOException 网络请求失败
*/
fun updateChannel(context: Context) {
val client = okhttp3.OkHttpClient()
val request = okhttp3.Request.Builder().url(getServerUrl(context)).build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
val body = response.body()
//覆盖channels.json
val file = File(getAppDirectory(context), "channels.json")
if (!file.exists()) {
file.createNewFile()
}
file.writeText(body!!.string())
}
}
/**
* 从res/values/server.xml获取服务器地址
* @param context 应用环境信息
* @return 服务器地址
*/
private fun getServerUrl(context: Context): String {
return context.resources.getString(R.string.server_url)
}
}
@@ -51,14 +51,14 @@ class YSP(var context: Context) {
private var signature = ""
private var encryptor: Encryptor? = null
private var sharedPref: SharedPreferences? = null
private lateinit var sharedPref: SharedPreferences
init {
if (context is MainActivity) {
encryptor = Encryptor()
encryptor!!.init(context)
sharedPref = (context as MainActivity).getPreferences(Context.MODE_PRIVATE)
sharedPref = (context as MainActivity).sharedPref
}
guid = getGuid()
@@ -77,15 +77,10 @@ class YSP(var context: Context) {
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"}"""
// return """{"cnlid":"2000203803","livepid":"600001801","stream":"2","guid":"lq1y36mb_ccfwmja9zan","cKey":"--01A9F5E89BB86A0C61F4025BEDE15309B6913A79FD1AF1EE7F5EC9C7605F377D1D2281488385C32DEB9E7D0DD3559CB700BD7AF44DD5C9DE0AE14D94B8214027B5D664C108AEE23532348DCC61B86F7C8FBB6CF14D588E6093A25E97DF6D66F4882AB28F17016472DD43D45EF076B7F505176A5E8DEDF2662E5F9AB12B69CB20BCE1579BE724091F3AF6826AE34B713906F3FE139C3783F80EECBD08416DC525E1","adjust":1,"sphttps":"1","platform":"5910204","cmd":"2","encryptVer":"8.1","dtype":"1","devid":"devid","otype":"ojson","appVer":"V1.0.0","app_version":"V1.0.0","rand_str":"IOS2soOw44","channel":"ysp_tx","defn":"fhd","signature":"6ca945f651817de8c6e6910457ceafd6"}"""
}
private fun getTimeStr(): String {
@@ -99,10 +94,10 @@ class YSP(var context: Context) {
}
fun getGuid(): String {
var guid = sharedPref?.getString("guid", "")
var guid = sharedPref.getString("guid", "")
if (guid == null || guid.length < 18) {
guid = generateGuid()
with(sharedPref!!.edit()) {
with(sharedPref.edit()) {
putString("guid", guid)
apply()
}
@@ -112,7 +107,7 @@ class YSP(var context: Context) {
private fun newGuid(): String {
guid = generateGuid()
with(sharedPref!!.edit()) {
with(sharedPref.edit()) {
putString("guid", guid)
apply()
}
@@ -19,8 +19,10 @@ class TVViewModel(private var tv: TV) : ViewModel() {
private var rowPosition: Int = 0
private var itemPosition: Int = 0
var retryTimes: Int = 0
var retryMaxTimes: Int = 8
var retryTimes = 0
var tokenRetryTimes = 0
var retryMaxTimes = 8
var tokenRetryMaxTimes = 2
var programUpdateTime: Long = 0
private val _errInfo = MutableLiveData<String>()
@@ -75,27 +77,6 @@ class TVViewModel(private var tv: TV) : ViewModel() {
var seq = 0
var needToken = false
private val channelsNeedToken = arrayOf(
// "CCTV4K 超高清",
"CCTV3 综艺",
"CCTV6 电影",
"CCTV8 电视剧",
"风云剧场",
"第一剧场",
"怀旧剧场",
"世界地理",
"风云音乐",
"兵器科技",
"风云足球",
"高尔夫网球",
"女性时尚",
"央视文化精品",
"央视台球",
"电视指南",
"卫生健康",
)
fun addVideoUrl(url: String) {
if (_videoUrl.value?.isNotEmpty() == true) {
@@ -147,12 +128,9 @@ 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 {
return rowPosition
}
+954
View File
@@ -0,0 +1,954 @@
[
{
"id": 0,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/d57905b93540bd15f0c48230dbbbff7ee0d645ff539e38866e2d15c8b9f7dfcd.png?imageMogr2/format/webp",
"pid": "600001859",
"sid": "2000210103",
"programId": "600001859",
"needToken": false,
"mustToken": false,
"title": "CCTV1 综合",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226231/index.m3u8"
]
},
{
"id": 1,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/20115388de0207131af17eac86c33049b95d69eaff064e55653a1b941810a006.png?imageMogr2/format/webp",
"pid": "600001800",
"sid": "2000203603",
"programId": "600001800",
"needToken": true,
"mustToken": false,
"title": "CCTV2 财经",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226195/index.m3u8"
]
},
{
"id": 2,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/7b7a65c712450da3deb6ca66fbacf4f9aee00d3f20bd80eafb5ada01ec63eb3a.png?imageMogr2/format/webp",
"pid": "600001801",
"sid": "2000203803",
"programId": "600001801",
"needToken": true,
"mustToken": true,
"title": "CCTV3 综艺",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226397/index.m3u8"
]
},
{
"id": 3,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/f357e58fdbcc076a3d65e1f958c942b2e14f14342c60736ceed98b092d35356a.png?imageMogr2/format/webp",
"pid": "600001814",
"sid": "2000204803",
"programId": "600001814",
"needToken": false,
"mustToken": false,
"title": "CCTV4 中文国际",
"videoUrl": [
"http://39.134.24.161/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226191/index.m3u8"
]
},
{
"id": 4,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/0a6a7138952675983a3d854df7688557b286d59aa06166edae51506f9204d655.png?imageMogr2/format/webp",
"pid": "600001818",
"sid": "2000205103",
"programId": "600001818",
"needToken": true,
"mustToken": false,
"title": "CCTV5 体育",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226395/index.m3u8"
]
},
{
"id": 5,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/741515efda91f03f455df8a7da4ee11fa9329139c276435cf0a9e2af398d5bf2.png?imageMogr2/format/webp",
"pid": "600001802",
"sid": "2013693901",
"programId": "600001802",
"needToken": true,
"mustToken": true,
"title": "CCTV6 电影",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226393/index.m3u8"
]
},
{
"id": 6,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/b29af94e295ebdf646cefb68122c429b9cd921f498ca20d2d8070252536f9ff9.png?imageMogr2/format/webp",
"pid": "600004092",
"sid": "2000510003",
"programId": "600004092",
"needToken": true,
"mustToken": false,
"title": "CCTV7 国防军事",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226192/index.m3u8"
]
},
{
"id": 7,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/ad51de94426a0ba039e6dd6a8534ea98ecc813a6176bde87b4f18cc34d6d7590.png?imageMogr2/format/webp",
"pid": "600001803",
"sid": "2000203903",
"programId": "600001803",
"needToken": true,
"mustToken": true,
"title": "CCTV8 电视剧",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226391/index.m3u8"
]
},
{
"id": 8,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/2ed1b4deeca179d5db806bb941790f82eb92a1b7299c1c38fe027f95a5caee5e.png?imageMogr2/format/webp",
"pid": "600004078",
"sid": "2000499403",
"programId": "600004078",
"needToken": true,
"mustToken": false,
"title": "CCTV9 记录",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226197/index.m3u8"
]
},
{
"id": 9,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/aa6157ec65188cd41826e5a2f088c3d6d153205f5f6428258d12c59999e221aa.png?imageMogr2/format/webp",
"pid": "600001805",
"sid": "2000203503",
"programId": "600001805",
"needToken": true,
"mustToken": false,
"title": "CCTV10 科教",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226189/index.m3u8"
]
},
{
"id": 10,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/ed12ed7c7a1034dae4350011fe039284c5d5a836506b28c9e32e3c75299625c0.png?imageMogr2/format/webp",
"pid": "600001806",
"sid": "2000204103",
"programId": "600001806",
"needToken": true,
"mustToken": false,
"title": "CCTV11 戏曲",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226240/index.m3u8"
]
},
{
"id": 11,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/484083cffaa40df7e659565e8cb4d1cc740158a185512114167aa21fa0c59240.png?imageMogr2/format/webp",
"pid": "600001807",
"sid": "2000202603",
"programId": "600001807",
"needToken": true,
"mustToken": false,
"title": "CCTV12 社会与法",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226190/index.m3u8"
]
},
{
"id": 12,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/266da7b43c03e2312186b4a999e0f060e8f15b10d2cc2c9aa32171819254cf1a.png?imageMogr2/format/webp",
"pid": "600001811",
"sid": "2000204603",
"programId": "600001811",
"needToken": false,
"mustToken": false,
"title": "CCTV13 新闻",
"videoUrl": [
"https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226233/index.m3u8"
]
},
{
"id": 13,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/af6b603896938dc346fbb16abfc63c12cba54b0ec9d18770a15d347d115f12d5.png?imageMogr2/format/webp",
"pid": "600001809",
"sid": "2000204403",
"programId": "600001809",
"needToken": true,
"mustToken": false,
"title": "CCTV14 少儿",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226193/index.m3u8"
]
},
{
"id": 14,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/2ceee92188ef684efe0d8b90839c4f3ad450d179dc64d59beff417059453af47.png?imageMogr2/format/webp",
"pid": "600001815",
"sid": "2000205003",
"programId": "600001815",
"needToken": true,
"mustToken": false,
"title": "CCTV15 音乐",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225785/index.m3u8"
]
},
{
"id": 15,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/53793fa7bacd3a93ff6dc5d2758418985e1f952a316c335d663b572d8bdcd74d.png?imageMogr2/format/webp",
"pid": "600098637",
"sid": "2012375003",
"programId": "600098637",
"needToken": true,
"mustToken": false,
"title": "CCTV16 奥林匹克",
"videoUrl": [
"http://39.134.24.162/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226921/index.m3u8"
]
},
{
"id": 16,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/ddef563072f8bad2bea5b9e52674cb7b4ed50efb20c26e61994dfbdf05c1e3c0.png?imageMogr2/format/webp",
"pid": "600001810",
"sid": "2000204203",
"programId": "600001810",
"needToken": true,
"mustToken": false,
"title": "CCTV17 农业农村",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226198/index.m3u8"
]
},
{
"id": 17,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/649ad76a90bfef55b05db9fe52e006487280f619089099d5dc971e387fc6eff0.png?imageMogr2/format/webp",
"pid": "600001817",
"sid": "2000204503",
"programId": "600001817",
"needToken": true,
"mustToken": false,
"title": "CCTV5+ 体育赛事",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226221/index.m3u8"
]
},
{
"id": 18,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/3e9d06fd7244d950df5838750f1c6ac3456e172b51caca2c16d2282125b111e8.png?imageMogr2/format/webp",
"pid": "600002264",
"sid": "2000266303",
"programId": "600002264",
"needToken": true,
"mustToken": false,
"title": "CCTV4K 超高清",
"videoUrl": [
""
]
},
{
"id": 19,
"videoIndex": 0,
"channel": "央视频道",
"logo": "",
"pid": "600156816",
"sid": "2020603421",
"programId": "",
"needToken": false,
"mustToken": false,
"title": "CCTV8K 超高清",
"videoUrl": [
""
]
},
{
"id": 20,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/4d549e53e6d0f632d5a633d1945280797b153e588f919221a07faa869812cc89.png?imageMogr2/format/webp",
"pid": "600099658",
"sid": "2012513603",
"programId": "600099658",
"needToken": true,
"mustToken": true,
"title": "风云剧场",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226950/index.m3u8"
]
},
{
"id": 21,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/a556bd7d93ce65e18f243a8892b5604f4faa994a4897315914216a710a706208.png?imageMogr2/format/webp",
"pid": "600099655",
"sid": "2012514403",
"programId": "600099655",
"needToken": true,
"mustToken": true,
"title": "第一剧场",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226959/index.m3u8"
]
},
{
"id": 22,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/5661bd04fecdb6e899f801147a22ab5d3a475bf2b62e30aec2c0023190ebc9b1.png?imageMogr2/format/webp",
"pid": "600099620",
"sid": "2012511203",
"programId": "600099620",
"needToken": true,
"mustToken": true,
"title": "怀旧剧场",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226972/index.m3u8"
]
},
{
"id": 23,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/bb3c6c9e145d698137f5bb64a582021a01b51344b929003630eb769ea65832a9.png?imageMogr2/format/webp",
"pid": "600099637",
"sid": "2012513303",
"programId": "600099637",
"needToken": true,
"mustToken": true,
"title": "世界地理",
"videoUrl": [
""
]
},
{
"id": 24,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/bbf1d024c5228b8dd128b0e3cb1717d173fab4ee84c3a4c8a57b1a215362ca3b.png?imageMogr2/format/webp",
"pid": "600099660",
"sid": "2012514103",
"programId": "600099660",
"needToken": true,
"mustToken": true,
"title": "风云音乐",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226953/index.m3u8"
]
},
{
"id": 25,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/4c6b6a6d3839889f34d33db3c2f80233b26b74d3489b393487635f8704e70796.png?imageMogr2/format/webp",
"pid": "600099649",
"sid": "2012513403",
"programId": "600099649",
"needToken": true,
"mustToken": true,
"title": "兵器科技",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226975/index.m3u8"
]
},
{
"id": 26,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/cd1e2bb52b06a991de168733e5ff0f1d85adc8042d40c8f393f723543e5dd08a.png?imageMogr2/format/webp",
"pid": "600099636",
"sid": "2012514203",
"programId": "600099636",
"needToken": true,
"mustToken": true,
"title": "风云足球",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226984/index.m3u8"
]
},
{
"id": 27,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/cdd1b31ede7a5ad049ed53d9a072422f829e72dd062ed2c19e077fdd01699071.png?imageMogr2/format/webp",
"pid": "600099659",
"sid": "2012512503",
"programId": "600099659",
"needToken": true,
"mustToken": true,
"title": "高尔夫网球",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226978/index.m3u8"
]
},
{
"id": 28,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/fa28955ce8b2539d728bf4c6a13a46ff57ad76eae46627f7bcfb1ed8a613d3fc.png?imageMogr2/format/webp",
"pid": "600099650",
"sid": "2012513903",
"programId": "600099650",
"needToken": true,
"mustToken": true,
"title": "女性时尚",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226969/index.m3u8"
]
},
{
"id": 29,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/14ac5ce40482cacd3d4b37435222bfe86af2b452a2f04ecbfc1d13d76edd7c57.png?imageMogr2/format/webp",
"pid": "600099653",
"sid": "2012513803",
"programId": "600099653",
"needToken": true,
"mustToken": true,
"title": "央视文化精品",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226981/index.m3u8"
]
},
{
"id": 30,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/10e14a92478011aa6c3c8562e62127f3b1908e29fcd78e4b2b24b9e6d3ec2fbc.png?imageMogr2/format/webp",
"pid": "600099652",
"sid": "2012513703",
"programId": "600099652",
"needToken": true,
"mustToken": true,
"title": "央视台球",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226956/index.m3u8"
]
},
{
"id": 31,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/244d72c0eb1615ed7d51c2f5db5a67f306aa3f58c05bc2d34de3aa7e956dc8c9.png?imageMogr2/format/webp",
"pid": "600099656",
"sid": "2012514003",
"programId": "600099656",
"needToken": true,
"mustToken": true,
"title": "电视指南",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888893/224/3221226987/index.m3u8"
]
},
{
"id": 32,
"videoIndex": 0,
"channel": "央视频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/54a6863656fdfd8f803be193ddf22441c5000a108833889816fd2d8911715ce8.png?imageMogr2/format/webp",
"pid": "600099651",
"sid": "2012513503",
"programId": "600099651",
"needToken": true,
"mustToken": true,
"title": "卫生健康",
"videoUrl": [
""
]
},
{
"id": 33,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/9bd372ca292a82ce3aa08772b07efc4af1f85c21d1f268ea33440c49e9a0a488.png?imageMogr2/format/webp",
"pid": "600002483",
"sid": "2000292403",
"programId": "600002483",
"needToken": true,
"mustToken": false,
"title": "东方卫视",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226217/index.m3u8"
]
},
{
"id": 34,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/4120e89d3079d08aa17d382f69a2308ec70839b278367763c34a34666c75cb88.png?imageMogr2/format/webp",
"pid": "600002475",
"sid": "2000296203",
"programId": "600002475",
"needToken": true,
"mustToken": false,
"title": "湖南卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226307/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226211/index.m3u8"
]
},
{
"id": 35,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/7a6be5a2bb1dc53a945c016ff1f525dc4a84c51db371c15c89aa55404b0ba784.png?imageMogr2/format/webp",
"pid": "600002508",
"sid": "2000294503",
"programId": "600002508",
"needToken": true,
"mustToken": false,
"title": "湖北卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226477/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226194/index.m3u8"
]
},
{
"id": 36,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/ac4ed6058a87c101ae7147ebc38905d0cae047fb73fd277ee5049b84f52bda36.png?imageMogr2/format/webp",
"pid": "600002505",
"sid": "2000281303",
"programId": "600002505",
"needToken": true,
"mustToken": false,
"title": "辽宁卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226546/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226201/index.m3u8"
]
},
{
"id": 37,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/380ad685c0c1d5b2c902246b8d2df6d3f9b45e2837abcfe493075bbded597a31.png?imageMogr2/format/webp",
"pid": "600002521",
"sid": "2000295603",
"programId": "600002521",
"needToken": true,
"mustToken": false,
"title": "江苏卫视",
"videoUrl": [
"http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226200/index.m3u8"
]
},
{
"id": 38,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/3c760d0d00463855890e8a1864ea4a6b6dd66b90c29b4ac714a4b17c16519871.png?imageMogr2/format/webp",
"pid": "600002503",
"sid": "2000294103",
"programId": "600002503",
"needToken": true,
"mustToken": false,
"title": "江西卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226344/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225764/index.m3u8"
]
},
{
"id": 39,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/22d403f07a7cf5410b3ad3ddb65a11aa229a32475fac213f5344c9f0ec330ca1.png?imageMogr2/format/webp",
"pid": "600002513",
"sid": "2000294803",
"programId": "600002513",
"needToken": true,
"mustToken": false,
"title": "山东卫视",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226209/index.m3u8"
]
},
{
"id": 40,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/28886880a4dc0f06fb7e0a528a1def0591d61a65870e29176ede0cc92033bbfd.png?imageMogr2/format/webp",
"pid": "600002485",
"sid": "2000292703",
"programId": "600002485",
"needToken": true,
"mustToken": false,
"title": "广东卫视",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226216/index.m3u8"
]
},
{
"id": 41,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/54b7e97cb816bb223fe05f3fc44da2c7820eb66e8550c19d23100f2c414ecc38.png?imageMogr2/format/webp",
"pid": "600002509",
"sid": "2000294203",
"programId": "600002509",
"needToken": true,
"mustToken": false,
"title": "广西卫视",
"videoUrl": [
"http://live.gxrb.com.cn/tv/gxtvlive03/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225770/index.m3u8"
]
},
{
"id": 42,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/657651f411de2673d1770d9a78b44c1265704f7468cc41d4be7f51d630768494.png?imageMogr2/format/webp",
"pid": "600002531",
"sid": "2000297803",
"programId": "600002531",
"needToken": true,
"mustToken": false,
"title": "重庆卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226409/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226202/index.m3u8"
]
},
{
"id": 43,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/74925962148a6d31c85808b6cd4e444c2a54bab393d2c5fc85e960b50e22fa86.png?imageMogr2/format/webp",
"pid": "600002525",
"sid": "2000296103",
"programId": "600002525",
"needToken": true,
"mustToken": false,
"title": "河南卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226480/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225767/index.m3u8"
]
},
{
"id": 44,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/d545becdc81c60197b08c7f47380705e4665ed3fe55efc8b855e486f6e655378.png?imageMogr2/format/webp",
"pid": "600002493",
"sid": "2000293403",
"programId": "600002493",
"needToken": true,
"mustToken": false,
"title": "河北卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226406/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225750/index.m3u8"
]
},
{
"id": 45,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/4eb45f4781d33d872af027dc01c941559aab55667dd99cc5c22bef7037807b13.png?imageMogr2/format/webp",
"pid": "600002490",
"sid": "2000293303",
"programId": "600002490",
"needToken": true,
"mustToken": false,
"title": "贵州卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226474/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225793/index.m3u8"
]
},
{
"id": 46,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/f4f23633c578beea49a3841d88d3490100f029ee349059fa532869db889872c5.png?imageMogr2/format/webp",
"pid": "600002309",
"sid": "2000272103",
"programId": "600002309",
"needToken": true,
"mustToken": false,
"title": "北京卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221225728/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226222/index.m3u8"
]
},
{
"id": 47,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/d8273ae9be698ce2db21f5b886ecac95a73429593f93713c60ed8c12c38bf0d3.png?imageMogr2/format/webp",
"pid": "600002498",
"sid": "2000293903",
"programId": "600002498",
"needToken": true,
"mustToken": false,
"title": "黑龙江卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226327/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226215/index.m3u8"
]
},
{
"id": 48,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/a66c836bd98ba3e41a2e9a570d4b9c50dedc6839e9de333e2e78212ad505f37e.png?imageMogr2/format/webp",
"pid": "600002520",
"sid": "2000295503",
"programId": "600002520",
"needToken": true,
"mustToken": false,
"title": "浙江卫视",
"videoUrl": [
"http://hw-m-l.cztv.com/channels/lantian/channel01/1080p.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226199/index.m3u8"
]
},
{
"id": 49,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/f35fa04b51b1ee4984b03578b65403570868ebca03c6c01e11b097f999a58d9b.png?imageMogr2/format/webp",
"pid": "600002532",
"sid": "2000298003",
"programId": "600002532",
"needToken": true,
"mustToken": false,
"title": "安徽卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226391/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226203/index.m3u8"
]
},
{
"id": 50,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/d59fec04c902e3581c617136d02d4b9b8c4cbe64272781ddd3525e80c823edb7.png?imageMogr2/format/webp",
"pid": "600002481",
"sid": "2000292203",
"programId": "600002481",
"needToken": true,
"mustToken": false,
"title": "深圳卫视",
"videoUrl": [
"http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226205/index.m3u8"
]
},
{
"id": 51,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/3276a414ae0eaa0f116f2045cd913367967d0c7c1e978e8621ac3879436c6ed7.png?imageMogr2/format/webp",
"pid": "600002516",
"sid": "2000295003",
"programId": "600002516",
"needToken": true,
"mustToken": false,
"title": "四川卫视",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/index.m3u8",
"http://39.134.24.166/dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225768/index.m3u8"
]
},
{
"id": 52,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/3208fe6564a293c21b711333fb3edb05bb5b406cff840573c9a8d839680a1579.png?imageMogr2/format/webp",
"pid": "600002484",
"sid": "2000292503",
"programId": "600002484",
"needToken": true,
"mustToken": false,
"title": "东南卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226341/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225766/index.m3u8"
]
},
{
"id": 53,
"videoIndex": 0,
"channel": "地方频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/6e060391fde0469801fc3d84dbf204b4f8d650d251f17d7595a6964c0bb99e81.png?imageMogr2/format/webp",
"pid": "600002506",
"sid": "2000291503",
"programId": "600002506",
"needToken": true,
"mustToken": false,
"title": "海南卫视",
"videoUrl": [
"http://ottrrs.hl.chinamobile.com/PLTV/88888888/224/3221226465/index.m3u8",
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225769/index.m3u8"
]
},
{
"id": 54,
"videoIndex": 0,
"channel": "地方频道",
"logo": "",
"pid": "600152137",
"sid": "2019927003",
"programId": "",
"needToken": true,
"mustToken": false,
"title": "天津卫视",
"videoUrl": [
""
]
},
{
"id": 55,
"videoIndex": 0,
"channel": "地方频道",
"logo": "",
"pid": "600152138",
"sid": "2019927403",
"programId": "",
"needToken": true,
"mustToken": false,
"title": "新疆卫视",
"videoUrl": [
""
]
},
{
"id": 56,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/a72dff758ca1c17cd0ecc8cedc11b893d208f409d5e6302faa0e9d298848abc3.png?imageMogr2/format/webp",
"pid": "600014550",
"sid": "2001656803",
"programId": "600014550",
"needToken": false,
"mustToken": false,
"title": "CGTN",
"videoUrl": [
"http://live.cgtn.com/1000/prog_index.m3u8"
]
},
{
"id": 57,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/a8d0046a47433d952bf6ed17062deb8bd2184ba9aec0f7781df6bf9487a3ffcf.png?imageMogr2/format/webp",
"pid": "600084704",
"sid": "2010153503",
"programId": "600084704",
"needToken": false,
"mustToken": false,
"title": "CGTN 法语频道",
"videoUrl": [
"https://livefr.cgtn.com/1000f/prog_index.m3u8"
]
},
{
"id": 58,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/bf0a820893cbaf20dd0333e27042e1ef9c8806e5b602b6a8c95af399db0bc77a.png?imageMogr2/format/webp",
"pid": "600084758",
"sid": "2010152603",
"programId": "600084758",
"needToken": false,
"mustToken": false,
"title": "CGTN 俄语频道",
"videoUrl": [
"http://liveru.cgtn.com/1000r/prog_index.m3u8"
]
},
{
"id": 59,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202306/2e44e2aa3e7a1cedf07fd0ae59fe69e86a60a2632660a006e3e9e7397b2d107e.png?imageMogr2/format/webp",
"pid": "600084782",
"sid": "2010155203",
"programId": "600084782",
"needToken": false,
"mustToken": false,
"title": "CGTN 阿拉伯语频道",
"videoUrl": [
"http://livear.cgtn.com/1000a/prog_index.m3u8"
]
},
{
"id": 60,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202309/7c337e3dbe64402ec7e4678a619a4a6d95144e42f35161181ff78e143b7cf67a.png?imageMogr2/format/webp",
"pid": "600084744",
"sid": "2010152503",
"programId": "600084744",
"needToken": false,
"mustToken": false,
"title": "CGTN 西班牙语频道",
"videoUrl": [
"http://livees.cgtn.com/500e/prog_index.m3u8",
"http://livees.cgtn.com/1000e/prog_index.m3u8"
]
},
{
"id": 61,
"videoIndex": 0,
"channel": "国际频道",
"logo": "https://resources.yangshipin.cn/assets/oms/image/202309/74d3ac436a7e374879578de1d87a941fbf566d39d5632b027c5097891ed32bd5.png?imageMogr2/format/webp",
"pid": "600084781",
"sid": "2010155403",
"programId": "600084781",
"needToken": false,
"mustToken": false,
"title": "CGTN 纪录频道",
"videoUrl": [
"https://livedoc.cgtn.com/500d/prog_index.m3u8"
]
}
]
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="server_url">http://localhost:8080</string>
</resources>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
+3 -3
View File
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.2.1' apply false
id 'com.android.library' version '8.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.21' apply false
id 'com.android.application' version '8.2.2' apply false
id 'com.android.library' version '8.2.2' apply false
id 'org.jetbrains.kotlin.android' version '1.9.22' apply false
}