Compare commits

..
5 Commits
Author SHA1 Message Date
Li ZongYing 7b7db88422 test sign 2023-12-18 13:23:55 +08:00
Li ZongYing 4e3123019d remove guid store 2023-12-18 12:47:21 +08:00
Li ZongYing 9191d58513 backup source 2023-12-18 10:12:52 +08:00
Li ZongYing 434915fd3d keep screen on 2023-12-16 15:09:09 +08:00
Li ZongYing d8fffbb402 optimize ysp 2023-12-16 08:19:02 +08:00
17 changed files with 140 additions and 75 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
distribution: 'temurin' distribution: 'temurin'
- name: Run build with Gradle wrapper - name: Run build with Gradle wrapper
run: ./gradlew assembleRelease run: ./gradlew assembleRelease -PIS_SO_BUILD=false
- name: Sign app APK - name: Sign app APK
id: sign_app id: sign_app
+1 -1
View File
@@ -3,4 +3,4 @@
/cmake_install.cmake /cmake_install.cmake
/CMakeFiles/ /CMakeFiles/
/Makefile /Makefile
/src/main/cpp/native-lib.c /src/main/cpp/native.c
+8 -8
View File
@@ -15,17 +15,17 @@ if (IS_SO_BUILD)
# and CMake builds them for you. When you build your app, Gradle # and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK. # automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library. add_library( # Specifies the name of the library.
native-lib native
# Sets the library as a shared library. # Sets the library as a shared library.
SHARED SHARED
# Provides a relative path to your source file(s). # Provides a relative path to your source file(s).
src/main/cpp/native-lib.c) src/main/cpp/native.c)
# 设置编译输出路径 # 设置编译输出路径
set_target_properties( set_target_properties(
native-lib native
PROPERTIES PROPERTIES
LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY
${CMAKE_SOURCE_DIR}/src/main/cpp/${ANDROID_ABI} ${CMAKE_SOURCE_DIR}/src/main/cpp/${ANDROID_ABI}
@@ -36,18 +36,18 @@ else ()
SHARED SHARED
src/main/cpp/nothing.c) src/main/cpp/nothing.c)
add_library(native-lib add_library(native
SHARED SHARED
IMPORTED) IMPORTED)
set_target_properties( # Specifies the target library. set_target_properties( # Specifies the target library.
native-lib native
# Specifies the parameter you want to define. # Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import. # Provides the path to the library you want to import.
${CMAKE_SOURCE_DIR}/src/main/cpp/${ANDROID_ABI}/libnative-lib.so) ${CMAKE_SOURCE_DIR}/src/main/cpp/${ANDROID_ABI}/libnative.so)
endif () endif ()
add_library(libssl add_library(libssl
@@ -87,7 +87,7 @@ find_library( # Defines the name of the path variable that stores the
if (IS_SO_BUILD) if (IS_SO_BUILD)
# Links your native library against one or more other native libraries. # Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library. target_link_libraries( # Specifies the target library.
native-lib native
libssl libssl
libcrypto libcrypto
${log-lib}) ${log-lib})
@@ -96,6 +96,6 @@ else ()
nothing nothing
libssl libssl
libcrypto libcrypto
native-lib native
${log-lib}) ${log-lib})
endif () endif ()
+2 -3
View File
@@ -24,8 +24,7 @@ android {
// For ndk-build, instead use the ndkBuild block. // For ndk-build, instead use the ndkBuild block.
cmake { cmake {
// arguments "-DIS_SO_BUILD=${project.hasProperty('IS_SO_BUILD') ? project.IS_SO_BUILD : false}" arguments "-DIS_SO_BUILD=${project.hasProperty('IS_SO_BUILD') ? project.IS_SO_BUILD : true}"
arguments "-DIS_SO_BUILD=${false}"
abiFilters "armeabi-v7a", "arm64-v8a" abiFilters "armeabi-v7a", "arm64-v8a"
} }
@@ -104,7 +103,7 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"
implementation 'androidx.core:core-ktx:1.11.0-beta02' implementation 'androidx.core:core-ktx:1.11.0-beta02'
implementation 'androidx.leanback:leanback:1.0.0' implementation 'androidx.leanback:leanback:1.2.0-alpha02'
implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC")
+1
View File
@@ -14,6 +14,7 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.MyTV"> android:theme="@style/Theme.MyTV">
<activity <activity
android:keepScreenOn="true"
android:name=".MainActivity" android:name=".MainActivity"
android:banner="@drawable/tv" android:banner="@drawable/tv"
android:exported="true" android:exported="true"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -11,7 +11,7 @@ class Encryptor {
companion object { companion object {
init { init {
System.loadLibrary("native-lib") System.loadLibrary("native")
} }
} }
} }
@@ -11,6 +11,7 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
import android.view.WindowManager
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
@@ -32,6 +33,8 @@ class MainActivity : FragmentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (savedInstanceState == null) { if (savedInstanceState == null) {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.main_browse_fragment, playbackFragment) .add(R.id.main_browse_fragment, playbackFragment)
@@ -40,6 +43,8 @@ class MainActivity : FragmentActivity() {
.hide(infoFragment) .hide(infoFragment)
.commit() .commit()
} }
Log.i(TAG, "Signature ${getAppSignature()}")
} }
fun switchInfoFragment(tv: TV) { fun switchInfoFragment(tv: TV) {
@@ -36,6 +36,16 @@ class MainFragment : BrowseSupportFragment() {
private var sharedPref: SharedPreferences? = null private var sharedPref: SharedPreferences? = null
// override fun onCreateView(
// inflater: LayoutInflater,
// container: ViewGroup?,
// savedInstanceState: Bundle?
// ): View? {
// super.onCreate()
// // 使用自定义的布局文件
// return inflater.inflate(R.layout.custom_browse_fragment, container, false)
// }
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@@ -51,11 +61,12 @@ class MainFragment : BrowseSupportFragment() {
} }
tvListViewModel.getListLiveData().value?.forEach { tvViewModel -> tvListViewModel.getListLiveData().value?.forEach { tvViewModel ->
tvViewModel.videoUrl.observe(viewLifecycleOwner) { _ -> tvViewModel.videoIndex.observe(viewLifecycleOwner) { videoIndex ->
// Log.i(TAG, "tv ${tvViewModel.getTV()}") if (tvViewModel.getIsFirstTime()) {
if (tvViewModel.updateByYSP()) { tvViewModel.isFirstTime(false)
} else {
val tv = tvViewModel.getTV() val tv = tvViewModel.getTV()
if (tv.id == itemPosition) { if (tvViewModel.id.value == itemPosition) {
(activity as? MainActivity)?.play(tv) (activity as? MainActivity)?.play(tv)
// (activity as? MainActivity)?.switchInfoFragment(tv) // (activity as? MainActivity)?.switchInfoFragment(tv)
} }
@@ -66,7 +77,6 @@ class MainFragment : BrowseSupportFragment() {
private fun setupUIElements() { private fun setupUIElements() {
brandColor = ContextCompat.getColor(context!!, R.color.fastlane_background) brandColor = ContextCompat.getColor(context!!, R.color.fastlane_background)
// headersState = HEADERS_DISABLED
} }
private fun updateRows(tv: TV) { private fun updateRows(tv: TV) {
@@ -111,6 +121,12 @@ class MainFragment : BrowseSupportFragment() {
adapter = rowsAdapter adapter = rowsAdapter
itemPosition = sharedPref?.getInt("position", 0)!! itemPosition = sharedPref?.getInt("position", 0)!!
if (itemPosition >= tvListViewModel.size()) {
itemPosition = 0
savePosition(0)
}
val tv = list2[itemPosition].item
val tvModel = tvListViewModel.getTVModel(itemPosition) val tvModel = tvListViewModel.getTVModel(itemPosition)
if (tvModel?.ysp() != null) { if (tvModel?.ysp() != null) {
@@ -118,10 +134,15 @@ class MainFragment : BrowseSupportFragment() {
tvModel.let { request?.fetchData(it) } tvModel.let { request?.fetchData(it) }
} }
} else { } else {
(activity as? MainActivity)?.play(list2[itemPosition].item) (activity as? MainActivity)?.play(tv)
// (activity as? MainActivity)?.switchInfoFragment(list2[itemPosition].item) // (activity as? MainActivity)?.switchInfoFragment(tv)
} }
Toast.makeText(
activity,
tv.title,
Toast.LENGTH_SHORT
).show()
(activity as? MainActivity)?.switchMainFragment() (activity as? MainActivity)?.switchMainFragment()
} }
@@ -150,6 +171,7 @@ class MainFragment : BrowseSupportFragment() {
val tvModel = tvListViewModel.getTVModel(itemPosition) val tvModel = tvListViewModel.getTVModel(itemPosition)
if (tvModel?.ysp() != null) { if (tvModel?.ysp() != null) {
Log.i(TAG, "${tvModel.title} to get ysp")
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
tvModel.let { request?.fetchData(it) } tvModel.let { request?.fetchData(it) }
} }
@@ -181,6 +203,7 @@ class MainFragment : BrowseSupportFragment() {
val tvModel = tvListViewModel.getTVModel(itemPosition) val tvModel = tvListViewModel.getTVModel(itemPosition)
if (tvModel?.ysp() != null) { if (tvModel?.ysp() != null) {
Log.i(TAG, "${tvModel.title} to get ysp")
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
tvModel.let { request?.fetchData(it) } tvModel.let { request?.fetchData(it) }
} }
@@ -249,6 +272,7 @@ class MainFragment : BrowseSupportFragment() {
val tvModel = tvListViewModel.getTVModel(itemPosition) val tvModel = tvListViewModel.getTVModel(itemPosition)
if (tvModel?.ysp() != null) { if (tvModel?.ysp() != null) {
Log.i(TAG, "${tvModel.title} to get ysp")
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
tvModel.let { request?.fetchData(it) } tvModel.let { request?.fetchData(it) }
} }
@@ -37,17 +37,17 @@ class Request(var context: Context) {
"CCTV10" to "CCTV10 科教", "CCTV10" to "CCTV10 科教",
"CCTV11" to "CCTV11 戏曲", "CCTV11" to "CCTV11 戏曲",
"CCTV12" to "CCTV12 社会与法", "CCTV12" to "CCTV12 社会与法",
// "CCTV13" to "CCTV13", "CCTV13" to "CCTV13 新闻",
"CCTV14" to "CCTV14 少儿", "CCTV14" to "CCTV14 少儿",
"CCTV15" to "CCTV15 音乐", "CCTV15" to "CCTV15 音乐",
"CCTV16-HD" to "CCTV16 奥林匹克", "CCTV16-HD" to "CCTV16 奥林匹克",
"CCTV17" to "CCTV17 农业农村", "CCTV17" to "CCTV17 农业农村",
"CGTN" to "CGTN", "CGTN" to "CGTN",
"CGTN外语纪录频道" to "CGTN 纪录频道",
"CGTN法语频道" to "CGTN 法语频道", "CGTN法语频道" to "CGTN 法语频道",
"CGTN俄语频道" to "CGTN 俄语频道", "CGTN俄语频道" to "CGTN 俄语频道",
"CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道", "CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道",
"CGTN西班牙语频道" to "CGTN 西班牙语频道", "CGTN西班牙语频道" to "CGTN 西班牙语频道",
// "CGTN外语纪录频道" to "CGTN外语纪录频道",
"东方卫视" to "东方卫视", "东方卫视" to "东方卫视",
"湖南卫视" to "湖南卫视", "湖南卫视" to "湖南卫视",
@@ -82,6 +82,7 @@ class Request(var context: Context) {
fun fetchData(tvModel: TVViewModel) { fun fetchData(tvModel: TVViewModel) {
val data = ysp?.switch(tvModel) val data = ysp?.switch(tvModel)
val title = tvModel.getTV().title
val request = data?.let { LiveInfoRequest(it) } val request = data?.let { LiveInfoRequest(it) }
request?.let { yspApiService?.getLiveInfo(it) } request?.let { yspApiService?.getLiveInfo(it) }
@@ -98,24 +99,33 @@ class Request(var context: Context) {
val decodedString = String(decodedBytes) val decodedString = String(decodedBytes)
val regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""") val regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
val matchResult = regex.find(decodedString) val matchResult = regex.find(decodedString)
var keyBytes = byteArrayOf()
var ivBytes = byteArrayOf()
if (matchResult != null) { if (matchResult != null) {
val (key, iv) = matchResult.destructured val (key, iv) = matchResult.destructured
keyBytes = Base64.decode(key, Base64.DEFAULT) val keyBytes = Base64.decode(key, Base64.DEFAULT)
ivBytes = Base64.decode(iv, Base64.DEFAULT) val ivBytes = Base64.decode(iv, Base64.DEFAULT)
} val url = liveInfo.data.playurl + "&revoi=" + encryptTripleDES(
tvModel.updateVideoUrlByYSP( keyBytes + byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
liveInfo.data.playurl + "&revoi=" + encryptTripleDES(
keyBytes,
ivBytes ivBytes
) ).uppercase()
) Log.i(TAG, "$title url $url")
tvModel.addVideoUrl(url)
} else {
Log.e(TAG, "$title key error")
tvModel.firstSource()
}
} else {
Log.e(TAG, "$title url error $request")
tvModel.firstSource()
} }
} else {
Log.e(TAG, "$title status error")
tvModel.firstSource()
} }
} }
override fun onFailure(call: Call<LiveInfo>, t: Throwable) { override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
Log.e(TAG, "${tvModel.getTV().title} request error")
tvModel.firstSource()
} }
}) })
} }
@@ -177,15 +187,15 @@ class Request(var context: Context) {
} }
private fun encryptTripleDES(key: ByteArray, iv: ByteArray): String { private fun encryptTripleDES(key: ByteArray, iv: ByteArray): String {
val plaintext = var plaintext =
"""{"mver":"1","subver":"1.2","host":"www.yangshipin.cn/#/tv/home?pid=","referer":"","canvas":"YSPANGLE(Apple,AppleM1Pro,OpenGL4.1)"}""" """{"mver":"1","subver":"1.2","host":"www.yangshipin.cn/#/tv/home?pid=","referer":"","canvas":"YSPANGLE(Apple,AppleM1Pro,OpenGL4.1)"}"""
return try { return try {
val keySpec = SecretKeySpec(key, "DESede") val keySpec = SecretKeySpec(key, "DESede")
val ivSpec = IvParameterSpec(iv) val ivSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("DESede/CBC/PKCS7Padding") val cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
val encryptedBytes = cipher.doFinal(plaintext.toByteArray()) val encryptedBytes = cipher.doFinal(plaintext.toByteArray())
encryptedBytes.let { it -> it.joinToString("") { "%02x".format(it) } } return encryptedBytes.let { it -> it.joinToString("") { "%02x".format(it) } }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
"" ""
+16 -21
View File
@@ -1,7 +1,5 @@
package com.lizongying.mytv package com.lizongying.mytv
import android.util.Log
object TVList { object TVList {
val list: Map<String, Map<String, TV>> by lazy { val list: Map<String, Map<String, TV>> by lazy {
setupTV() setupTV()
@@ -17,34 +15,31 @@ CCTV1 综合,http://tvpull.dxhmt.cn/tv/11481-4.m3u8,https://resources.yangshipin
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 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 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://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= CCTV5 体育,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226395/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/0a6a7138952675983a3d854df7688557b286d59aa06166edae51506f9204d655.png?imageMogr2/format/webp,600001818,2000205103
CCTV4 中文国际欧洲,http://hlsbkmgsplive.miguvideo.com/migu/kailu/20200324/cctv4ouhd/51/index.m3u8?&encrypt= CCTV5+ 体育赛事,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226221/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/649ad76a90bfef55b05db9fe52e006487280f619089099d5dc971e387fc6eff0.png?imageMogr2/format/webp,600001817,2000204503
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 CCTV6 电影,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226393/index.m3u8
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 CCTV7 国防军事,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226192/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/b29af94e295ebdf646cefb68122c429b9cd921f498ca20d2d8070252536f9ff9.png?imageMogr2/format/webp,600004092,2000510003
CCTV6 电影,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv6hd/3000/index.m3u8?&encrypt= CCTV8 电视剧,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226391/index.m3u8
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 CCTV9 记录,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226197/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/2ed1b4deeca179d5db806bb941790f82eb92a1b7299c1c38fe027f95a5caee5e.png?imageMogr2/format/webp,600004078,2000499403
CCTV8 电视剧,http://hlsbkmgsplive.miguvideo.com/wd_r2/ocn/cctv8hd/3000/index.m3u8?&encrypt= CCTV10 科教,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226189/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/aa6157ec65188cd41826e5a2f088c3d6d153205f5f6428258d12c59999e221aa.png?imageMogr2/format/webp,600001805,2000203503
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 CCTV11 戏曲,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226240/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/ed12ed7c7a1034dae4350011fe039284c5d5a836506b28c9e32e3c75299625c0.png?imageMogr2/format/webp,600001806,2000204103
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 CCTV12 社会与法,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226190/index.m3u8, https://resources.yangshipin.cn/assets/oms/image/202306/484083cffaa40df7e659565e8cb4d1cc740158a185512114167aa21fa0c59240.png?imageMogr2/format/webp,600001807,2000202603
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 CCTV13 新闻,https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8
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 CCTV14 少儿,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226193/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/af6b603896938dc346fbb16abfc63c12cba54b0ec9d18770a15d347d115f12d5.png?imageMogr2/format/webp,600001809,2000204403
CCTV13 新闻,https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8;http://hlsbkmgsplive.miguvideo.com/envivo_x/2018/SD/cctv13/2000/index.m3u8?&encrypt= CCTV15 音乐,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221225785/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/2ceee92188ef684efe0d8b90839c4f3ad450d179dc64d59beff417059453af47.png?imageMogr2/format/webp,600001815,2000205003
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 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 CCTV17 农业农村,http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226198/index.m3u8,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,,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 新闻频道,http://live.cgtn.com/1000/prog_index.m3u8
CGTN 纪录频道,https://livedoc.cgtn.com/500d/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 法语频道,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://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://livees.cgtn.com/500e/prog_index.m3u8;http://livees.cgtn.com/1000e/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://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 书画频道,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://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226217/index.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/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/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/3221226477/index.m3u8,https://resources.yangshipin.cn/assets/oms/image/202306/7a6be5a2bb1dc53a945c016ff1f525dc4a84c51db371c15c89aa55404b0ba784.png?imageMogr2/format/webp,600002508,2000294503
@@ -68,7 +68,7 @@ class YSP(var context: Context) {
cnlid = tvModel.getTV().sid cnlid = tvModel.getTV().sid
defn = "fhd" defn = "fhd"
guid = getGuid() // guid = getGuid()
randStr = getRand() randStr = getRand()
timeStr = getTimeStr() timeStr = getTimeStr()
@@ -80,7 +80,6 @@ class YSP(var context: Context) {
encryptor!!.encrypt(cnlid, timeStr, appVer, guid, platform) encryptor!!.encrypt(cnlid, timeStr, appVer, guid, platform)
signature = getSignature() 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":"$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 { private fun getTimeStr(): String {
@@ -100,8 +99,8 @@ class YSP(var context: Context) {
} }
private fun getGuid(): String { private fun getGuid(): String {
// var guid = sharedPref?.getString("guid", "").toString() var guid = sharedPref?.getString("guid", "")
if (guid == "") { if (guid == null || guid.length < 18) {
guid = generateGuid() guid = generateGuid()
with(sharedPref!!.edit()) { with(sharedPref!!.edit()) {
putString("guid", guid) putString("guid", guid)
@@ -1,6 +1,5 @@
package com.lizongying.mytv.models package com.lizongying.mytv.models
import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.lizongying.mytv.TV import com.lizongying.mytv.TV
@@ -41,4 +40,8 @@ class TVListViewModel : ViewModel() {
fun getTVModel(id: Int): TVViewModel? { fun getTVModel(id: Int): TVViewModel? {
return tvModelListLiveData.value?.get(id) return tvModelListLiveData.value?.get(id)
} }
fun size(): Int {
return tvListLiveData.value!!.size
}
} }
@@ -1,5 +1,6 @@
package com.lizongying.mytv.models package com.lizongying.mytv.models
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -8,7 +9,7 @@ import com.lizongying.mytv.TV
class TVViewModel(private var tv: TV) : ViewModel() { class TVViewModel(private var tv: TV) : ViewModel() {
private var mapping = mapOf( private var mapping = mapOf(
"CCTV4K" to "CCTV4K", "CCTV4K" to "CCTV4K",
// "CCTV1" to "CCTV1 综合", "CCTV1" to "CCTV1 综合",
"CCTV2" to "CCTV2 财经", "CCTV2" to "CCTV2 财经",
"CCTV4" to "CCTV4 中文国际", "CCTV4" to "CCTV4 中文国际",
"CCTV5" to "CCTV5 体育", "CCTV5" to "CCTV5 体育",
@@ -18,17 +19,17 @@ class TVViewModel(private var tv: TV) : ViewModel() {
"CCTV10" to "CCTV10 科教", "CCTV10" to "CCTV10 科教",
"CCTV11" to "CCTV11 戏曲", "CCTV11" to "CCTV11 戏曲",
"CCTV12" to "CCTV12 社会与法", "CCTV12" to "CCTV12 社会与法",
// "CCTV13" to "CCTV13", "CCTV13" to "CCTV13 新闻",
"CCTV14" to "CCTV14 少儿", "CCTV14" to "CCTV14 少儿",
"CCTV15" to "CCTV15 音乐", "CCTV15" to "CCTV15 音乐",
"CCTV16-HD" to "CCTV16 奥林匹克", "CCTV16-HD" to "CCTV16 奥林匹克",
"CCTV17" to "CCTV17 农业农村", "CCTV17" to "CCTV17 农业农村",
"CGTN" to "CGTN", "CGTN" to "CGTN",
"CGTN外语纪录频道" to "CGTN 纪录频道",
"CGTN法语频道" to "CGTN 法语频道", "CGTN法语频道" to "CGTN 法语频道",
"CGTN俄语频道" to "CGTN 俄语频道", "CGTN俄语频道" to "CGTN 俄语频道",
"CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道", "CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道",
"CGTN西班牙语频道" to "CGTN 西班牙语频道", "CGTN西班牙语频道" to "CGTN 西班牙语频道",
// "CGTN外语纪录频道" to "CGTN外语纪录频道",
"东方卫视" to "东方卫视", "东方卫视" to "东方卫视",
"湖南卫视" to "湖南卫视", "湖南卫视" to "湖南卫视",
@@ -53,12 +54,24 @@ class TVViewModel(private var tv: TV) : ViewModel() {
"海南卫视" to "海南卫视", "海南卫视" to "海南卫视",
).entries.associate { (key, value) -> value to key } ).entries.associate { (key, value) -> value to key }
private var updateByYSP = false private var isFirstTime = true
private val _id = MutableLiveData<Int>()
val id: LiveData<Int>
get() = _id
private val _title = MutableLiveData<String>()
val title: LiveData<String>
get() = _title
private val _videoUrl = MutableLiveData<List<String>>() private val _videoUrl = MutableLiveData<List<String>>()
val videoUrl: LiveData<List<String>> val videoUrl: LiveData<List<String>>
get() = _videoUrl get() = _videoUrl
private val _videoIndex = MutableLiveData<Int>()
val videoIndex: LiveData<Int>
get() = _videoIndex
private val _pid = MutableLiveData<String>() private val _pid = MutableLiveData<String>()
val pid: LiveData<String> val pid: LiveData<String>
get() = _pid get() = _pid
@@ -79,25 +92,37 @@ class TVViewModel(private var tv: TV) : ViewModel() {
_backgroundImage.value = url _backgroundImage.value = url
} }
private fun updateVideoUrl(url: String) { fun addVideoUrl(url: String) {
tv.videoUrl = listOf(url) tv.videoUrl = tv.videoUrl + listOf(url)
tv.videoIndex = 0 tv.videoIndex = tv.videoUrl.lastIndex
_videoUrl.value = listOf(url) _videoUrl.value = tv.videoUrl
_videoIndex.value = tv.videoIndex
} }
fun updateVideoUrlByYSP(url: String) { fun firstSource() {
updateByYSP = true if (tv.videoUrl.isNotEmpty()) {
updateVideoUrl(url) tv.videoIndex = 0
_videoIndex.value = 0
} else {
Log.e(TAG, "no first")
}
} }
init { init {
_id.value = tv.id
_title.value = tv.title
_videoUrl.value = tv.videoUrl _videoUrl.value = tv.videoUrl
_videoIndex.value = tv.videoIndex
_pid.value = tv.pid _pid.value = tv.pid
_sid.value = tv.sid _sid.value = tv.sid
} }
fun updateByYSP(): Boolean { fun getIsFirstTime(): Boolean {
return updateByYSP return isFirstTime
}
fun isFirstTime(firstTime: Boolean) {
isFirstTime = firstTime
} }
fun update(t: TV) { fun update(t: TV) {
@@ -114,4 +139,8 @@ class TVViewModel(private var tv: TV) : ViewModel() {
} }
return mapping[tv.title] return mapping[tv.title]
} }
companion object {
private const val TAG = "TVViewModel"
}
} }