request optimize

pull/731/head
Li ZongYing 2 years ago
parent 188431a29f
commit 7057e4a8b4
  1. 5
      README.md
  2. 84
      app/src/main/java/com/lizongying/mytv/Ext.kt
  3. 86
      app/src/main/java/com/lizongying/mytv/MainActivity.kt
  4. 179
      app/src/main/java/com/lizongying/mytv/Request.kt
  5. 53
      app/src/main/java/com/lizongying/mytv/SettingFragment.kt
  6. 14
      app/src/main/java/com/lizongying/mytv/UpdateManager.kt
  7. 7
      app/src/main/java/com/lizongying/mytv/models/TVViewModel.kt
  8. 2
      app/src/main/res/raw/channels.json

@ -20,6 +20,11 @@
* 凤凰卫视增强画质
* 凤凰卫视增加EPG
### v1.6.5(安卓5及以上专用)
* 增加CETV1图标
* 稳定性提升
### v1.6.4(通用)
* 增加CETV1

@ -0,0 +1,84 @@
@file:Suppress("DEPRECATION")
package com.lizongying.mytv
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.content.pm.SigningInfo
import android.os.Build
import android.util.Log
import java.security.MessageDigest
private const val TAG = "Extensions"
private val Context.packageInfo: PackageInfo
get() {
val flag = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
PackageManager.GET_SIGNATURES
} else {
PackageManager.GET_SIGNING_CERTIFICATES
}
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
packageManager.getPackageInfo(packageName, flag)
} else {
packageManager.getPackageInfo(
packageName,
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
)
}
}
/**
* Return the version code of the app which is defined in build.gradle.
* eg:100
*/
val Context.appVersionCode: Long
get() {
val packageInfo = this.packageInfo
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
packageInfo.versionCode.toLong()
}
}
/**
* Return the version name of the app which is defined in build.gradle.
* eg:1.0.0
*/
val Context.appVersionName: String get() = packageInfo.versionName
val Context.appSignature: String
get() {
val packageInfo = this.packageInfo
var sign: Signature? = null
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
val signatures: Array<out Signature>? = packageInfo.signatures
if (signatures != null) {
sign = signatures[0]
}
} else {
val signingInfo: SigningInfo? = packageInfo.signingInfo
if (signingInfo != null) {
sign = signingInfo.apkContentsSigners[0]
}
}
if (sign == null) {
return ""
}
return hashSignature(sign)
}
private fun hashSignature(signature: Signature): String {
return try {
val md = MessageDigest.getInstance("MD5")
md.update(signature.toByteArray())
val digest = md.digest()
digest.let { it -> it.joinToString("") { "%02x".format(it) } }
} catch (e: Exception) {
Log.e(TAG, "Error hashing signature", e)
""
}
}

@ -1,10 +1,5 @@
package com.lizongying.mytv
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.content.pm.SigningInfo
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@ -16,23 +11,17 @@ import android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
import android.view.WindowManager
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.lizongying.mytv.models.TVViewModel
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.security.MessageDigest
class MainActivity : FragmentActivity(), Request.RequestListener {
private var ready = 0
private var playerFragment = PlayerFragment()
private var mainFragment = MainFragment()
private var infoFragment = InfoFragment()
private var channelFragment = ChannelFragment()
private lateinit var settingFragment: SettingFragment
private val playerFragment = PlayerFragment()
private val mainFragment = MainFragment()
private val infoFragment = InfoFragment()
private val channelFragment = ChannelFragment()
private val settingFragment = SettingFragment()
private var doubleBackToExitPressedOnce = false
@ -64,20 +53,6 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
.commit()
}
gestureDetector = GestureDetector(this, GestureListener())
val packageInfo = getPackageInfo()
val versionName = packageInfo.versionName
val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
packageInfo.versionCode.toLong()
}
settingFragment = SettingFragment(
versionName,
versionCode,
SP.channelReversal,
SP.channelNum,
SP.bootStartup
)
}
fun showInfoFragment(tvViewModel: TVViewModel) {
@ -448,56 +423,7 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
return super.onKeyDown(keyCode, event)
}
private fun getPackageInfo(): PackageInfo {
val flag = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
PackageManager.GET_SIGNATURES
} else {
PackageManager.GET_SIGNING_CERTIFICATES
}
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
packageManager.getPackageInfo(packageName, flag)
} else {
packageManager.getPackageInfo(
packageName,
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
)
}
}
private fun getAppSignature(): String {
val packageInfo = getPackageInfo()
var sign: Signature? = null
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
val signatures: Array<out Signature>? = packageInfo.signatures
if (signatures != null) {
sign = signatures[0]
}
} else {
val signingInfo: SigningInfo? = packageInfo.signingInfo
if (signingInfo != null) {
sign = signingInfo.apkContentsSigners[0]
}
}
if (sign == null) {
return ""
}
return hashSignature(sign)
}
private fun hashSignature(signature: Signature): String {
return try {
val md = MessageDigest.getInstance("MD5")
md.update(signature.toByteArray())
val digest = md.digest()
digest.let { it -> it.joinToString("") { "%02x".format(it) } }
} catch (e: Exception) {
Log.e(TAG, "Error hashing signature", e)
""
}
}
private fun getAppSignature() = this.appSignature
override fun onStart() {
Log.i(TAG, "onStart")

@ -56,6 +56,9 @@ object Request {
private var listener: RequestListener? = null
private var initRetryTimes = 0
private var initRetryMaxTimes = 1
fun onCreate() {
Log.i(TAG, "onCreate")
fetchInfoV2()
@ -66,11 +69,22 @@ object Request {
handler.removeCallbacks(tokenRunnable)
}
var call: Call<LiveInfo>? = null
private var call: Call<LiveInfo>? = null
private var callAuth: Call<Auth>? = null
private var callInfo: Call<Info>? = null
private var fAuth: Call<FAuth>? = null
private var callPage: Call<pageModel.Response>? = null
private fun fetchAuth(tvModel: TVViewModel, cookie: String) {
private fun cancelCall() {
call?.cancel()
callAuth?.cancel()
callInfo?.cancel()
fAuth?.cancel()
callPage?.cancel()
}
private fun fetchAuth(tvModel: TVViewModel, cookie: String) {
cancelCall()
val title = tvModel.title.value
@ -146,9 +160,9 @@ object Request {
})
}
fun fetchVideo(tvModel: TVViewModel, cookie: String) {
Log.i(TAG, "fetchVideo with cookie")
call?.cancel()
private fun fetchVideo(tvModel: TVViewModel, cookie: String) {
cancelCall()
if (::btraceRunnable.isInitialized) {
handler.removeCallbacks(btraceRunnable)
}
@ -284,37 +298,23 @@ object Request {
})
}
fun fetchAuth(tvModel: TVViewModel) {
private fun fetchAuth(tvModel: TVViewModel) {
cancelCall()
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; appid=1400421205; yspappid=519748109;yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchAuth(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
if (tvModel.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
fetchAuth(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109"
fetchAuth(tvModel, cookie)
}
}
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
callInfo = yspTokenService.getInfo("")
callInfo?.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; appid=1400421205; yspappid=519748109;yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
fetchAuth(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
if (tvModel.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
fetchVideo(tvModel)
fetchAuth(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
@ -323,7 +323,22 @@ object Request {
}
}
}
})
}
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; appid=1400421205; yspappid=519748109"
fetchAuth(tvModel, cookie)
}
}
}
})
} else {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109;yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
@ -331,35 +346,21 @@ object Request {
}
}
fun fetchVideo(tvModel: TVViewModel) {
private fun fetchVideo(tvModel: TVViewModel) {
cancelCall()
Log.d(TAG, "fetchVideo")
if (token == "") {
yspTokenService.getInfo("")
.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful && response.body()?.data?.token != null) {
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; appid=1400421205; 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; appid=1400421205; yspappid=519748109"
fetchVideo(tvModel, cookie)
}
}
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
callInfo = yspTokenService.getInfo("")
callInfo?.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful && response.body()?.data?.token != null) {
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; appid=1400421205; 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)
@ -371,7 +372,22 @@ object Request {
}
}
}
})
}
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; appid=1400421205; yspappid=519748109"
fetchVideo(tvModel, cookie)
}
}
}
})
} else {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109; yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
@ -379,11 +395,8 @@ object Request {
}
}
private var fAuth: Call<FAuth>? = null
fun fetchFAuth(tvModel: TVViewModel) {
call?.cancel()
callAuth?.cancel()
fAuth?.cancel()
private fun fetchFAuth(tvModel: TVViewModel) {
cancelCall()
val title = tvModel.title.value
@ -400,11 +413,11 @@ object Request {
// Log.d(TAG, "$title url $url")
tvModel.addVideoUrl(url)
tvModel.allReady()
tvModel.tokenRetryTimes = 0
tvModel.tokenFHRetryTimes = 0
} else {
Log.e(TAG, "auth status error ${response.code()}")
if (tvModel.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
if (tvModel.tokenFHRetryTimes < tvModel.tokenFHRetryMaxTimes) {
tvModel.tokenFHRetryTimes++
fetchFAuth(tvModel)
}
}
@ -412,8 +425,8 @@ object Request {
override fun onFailure(call: Call<FAuth>, t: Throwable) {
Log.e(TAG, "auth request error $t")
if (tvModel.tokenRetryTimes < tvModel.tokenRetryMaxTimes) {
tvModel.tokenRetryTimes++
if (tvModel.tokenFHRetryTimes < tvModel.tokenFHRetryMaxTimes) {
tvModel.tokenFHRetryTimes++
fetchFAuth(tvModel)
}
}
@ -421,7 +434,6 @@ object Request {
}
fun fetchData(tvModel: TVViewModel) {
Log.i(TAG, "fetchData")
if (tvModel.getTV().channel == "港澳台") {
fetchFAuth(tvModel)
return
@ -446,7 +458,7 @@ object Request {
class TokenRunnable : Runnable {
override fun run() {
fetchToken()
// fetchToken()
}
}
@ -489,14 +501,20 @@ object Request {
Utils.setBetween(c * 1000L)
Log.i(TAG, "current time $c")
}
listener?.onRequestFinished()
} else {
Log.e(TAG, "token status error")
handler.postDelayed(
tokenRunnable,
30 * 60 * 1000
)
if (initRetryTimes < initRetryMaxTimes) {
initRetryTimes++
fetchInfoV2()
} else {
listener?.onRequestFinished()
}
}
listener?.onRequestFinished()
}
override fun onFailure(call: Call<InfoV2>, t: Throwable) {
@ -505,7 +523,13 @@ object Request {
tokenRunnable,
30 * 60 * 1000
)
listener?.onRequestFinished()
if (initRetryTimes < initRetryMaxTimes) {
initRetryTimes++
fetchInfoV2()
} else {
listener?.onRequestFinished()
}
}
})
}
@ -601,7 +625,8 @@ object Request {
}
fun fetchPage() {
yspProtoService.getPage().enqueue(object : Callback<pageModel.Response> {
callPage = yspProtoService.getPage()
callPage?.enqueue(object : Callback<pageModel.Response> {
override fun onResponse(
call: Call<pageModel.Response>,
response: Response<pageModel.Response>

@ -8,14 +8,7 @@ import androidx.fragment.app.DialogFragment
import com.lizongying.mytv.databinding.DialogBinding
class SettingFragment(
private val versionName: String,
private val versionCode: Long,
private val channelReversal: Boolean,
private val channelNum: Boolean,
private val bootStartup: Boolean,
) :
DialogFragment() {
class SettingFragment : DialogFragment() {
private var _binding: DialogBinding? = null
private val binding get() = _binding!!
@ -32,33 +25,37 @@ class SettingFragment(
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val context = requireContext() // It‘s safe to get context here.
_binding = DialogBinding.inflate(inflater, container, false)
_binding?.version?.text =
"当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/"
val switchChannelReversal = _binding?.switchChannelReversal
switchChannelReversal?.isChecked = channelReversal
switchChannelReversal?.setOnCheckedChangeListener { _, isChecked ->
SP.channelReversal = isChecked
(activity as MainActivity).settingActive()
binding.version.text =
"当前版本: ${context.appVersionName}\n获取最新: https://github.com/lizongying/my-tv/releases/"
binding.switchChannelReversal.run {
isChecked = SP.channelReversal
setOnCheckedChangeListener { _, isChecked ->
SP.channelReversal = isChecked
(activity as MainActivity).settingActive()
}
}
val switchChannelNum = _binding?.switchChannelNum
switchChannelNum?.isChecked = channelNum
switchChannelNum?.setOnCheckedChangeListener { _, isChecked ->
SP.channelNum = isChecked
(activity as MainActivity).settingActive()
binding.switchChannelNum.run {
isChecked = SP.channelNum
setOnCheckedChangeListener { _, isChecked ->
SP.channelNum = isChecked
(activity as MainActivity).settingActive()
}
}
val switchBootStartup = _binding?.switchBootStartup
switchBootStartup?.isChecked = bootStartup
switchBootStartup?.setOnCheckedChangeListener { _, isChecked ->
SP.bootStartup = isChecked
(activity as MainActivity).settingActive()
binding.switchBootStartup.run {
isChecked = SP.bootStartup
setOnCheckedChangeListener { _, isChecked ->
SP.bootStartup = isChecked
(activity as MainActivity).settingActive()
}
}
updateManager = UpdateManager(context, this, versionCode)
_binding?.checkVersion?.setOnClickListener(OnClickListenerCheckVersion(updateManager))
updateManager = UpdateManager(context, this, context.appVersionCode)
binding.checkVersion.setOnClickListener(OnClickListenerCheckVersion(updateManager))
return binding.root
}

@ -23,7 +23,7 @@ import java.io.File
class UpdateManager(
private var context: Context?,
private var context: Context,
private var settingFragment: SettingFragment,
private var versionCode: Long
) :
@ -67,7 +67,7 @@ class UpdateManager(
val apkFileName = "my-tv-${release.data.versionName}.apk"
Log.i(TAG, "apkFileName $apkFileName")
val downloadManager =
context!!.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = Request(Uri.parse(release.data.downloadUrl))
Log.i(TAG, "url ${Uri.parse(release.data.downloadUrl)}")
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkFileName)
@ -77,22 +77,22 @@ class UpdateManager(
// 获取下载任务的引用
val downloadReference = downloadManager.enqueue(request)
downloadReceiver = DownloadReceiver(context!!, apkFileName, downloadReference)
downloadReceiver = DownloadReceiver(context, apkFileName, downloadReference)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context!!.registerReceiver(
context.registerReceiver(
downloadReceiver,
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
Context.RECEIVER_NOT_EXPORTED,
)
} else {
context!!.registerReceiver(
context.registerReceiver(
downloadReceiver,
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
)
}
getDownloadProgress(context!!, downloadReference) { progress ->
getDownloadProgress(context, downloadReference) { progress ->
println("Download progress: $progress%")
}
}
@ -182,7 +182,7 @@ class UpdateManager(
fun destroy() {
if (downloadReceiver != null) {
context!!.unregisterReceiver(downloadReceiver)
context.unregisterReceiver(downloadReceiver)
Log.i(TAG, "destroy downloadReceiver")
}
}

@ -22,10 +22,11 @@ class TVViewModel(private var tv: TV) : ViewModel() {
private var itemPosition: Int = 0
var retryTimes = 0
var tokenRetryTimes = 0
var retryMaxTimes = 8
var tokenRetryMaxTimes = 2
var programUpdateTime: Long = 0
var tokenRetryTimes = 0
var tokenRetryMaxTimes = 0
var tokenFHRetryTimes = 0
var tokenFHRetryMaxTimes = 2
private val _errInfo = MutableLiveData<String>()
val errInfo: LiveData<String>

@ -130,7 +130,7 @@
"programId": "600004078",
"needToken": true,
"mustToken": false,
"title": "CCTV9 录",
"title": "CCTV9 录",
"videoUrl": [
"http://dbiptv.sn.chinamobile.com/PLTV/88888890/224/3221226197/index.m3u8"
]

Loading…
Cancel
Save