fix crash on setting

This commit is contained in:
Li ZongYing 2024-03-29 16:19:27 +08:00
parent 65c4b0cf52
commit fd897f68c0
12 changed files with 119 additions and 43 deletions

View File

@ -1,5 +1,16 @@
## 更新日志 ## 更新日志
### v1.7.2(通用)
* 支持节目列表网格样式和行样式切换,软件重启后生效
* 节目列表样式变更
### v1.7.1安卓5及以上专用
* 解决设置页更新闪退的问题
* 凤凰卫视回归
* 解决368问题
### v1.7.0(通用) ### v1.7.0(通用)
* 网络请求优化 * 网络请求优化

View File

@ -1,17 +1,17 @@
package com.lizongying.mytv package com.lizongying.mytv
import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.leanback.widget.ImageCardView import androidx.leanback.widget.ImageCardView
import androidx.leanback.widget.Presenter import androidx.leanback.widget.Presenter
import androidx.lifecycle.LifecycleOwner
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.lizongying.mytv.models.TVViewModel import com.lizongying.mytv.models.TVViewModel
class CardPresenter( class CardPresenter(
private val owner: LifecycleOwner, private val context: Context,
) : Presenter() { ) : Presenter() {
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
@ -39,6 +39,20 @@ class CardPresenter(
cardView.setBackgroundColor(Color.WHITE) cardView.setBackgroundColor(Color.WHITE)
cardView.setMainImageScaleType(ImageView.ScaleType.CENTER_INSIDE) cardView.setMainImageScaleType(ImageView.ScaleType.CENTER_INSIDE)
// cardView.setOnFocusChangeListener { v, hasFocus ->
// run {
// if (hasFocus) {
// if (v != null) {
// (v as ImageCardView).setInfoAreaBackgroundColor(context.resources.getColor(R.color.focus))
// }
// } else {
// if (v != null) {
// (v as ImageCardView).setInfoAreaBackgroundColor(context.resources.getColor(R.color.ic_launcher_background))
// }
// }
// }
// }
val epg = tvViewModel.epg.value?.filter { it.beginTime < Utils.getDateTimestamp() } val epg = tvViewModel.epg.value?.filter { it.beginTime < Utils.getDateTimestamp() }
if (!epg.isNullOrEmpty()) { if (!epg.isNullOrEmpty()) {
cardView.contentText = epg.last().title cardView.contentText = epg.last().title

View File

@ -5,14 +5,16 @@ import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
class ConfirmationDialogFragment(private val listener: ConfirmationDialogListener) : class ConfirmationFragment(
DialogFragment() { private val listener: ConfirmationListener,
private val message: String
) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { return activity?.let {
val builder = AlertDialog.Builder(it) val builder = AlertDialog.Builder(it)
builder.setTitle("") builder.setTitle("定更新吗?")
.setMessage("确认更新吗?") .setMessage(message)
.setPositiveButton( .setPositiveButton(
"确定" "确定"
) { _, _ -> ) { _, _ ->
@ -23,12 +25,11 @@ class ConfirmationDialogFragment(private val listener: ConfirmationDialogListene
) { _, _ -> ) { _, _ ->
listener.onCancel() listener.onCancel()
} }
// 创建并返回 AlertDialog 对象
builder.create() builder.create()
} ?: throw IllegalStateException("Activity cannot be null") } ?: throw IllegalStateException("Activity cannot be null")
} }
interface ConfirmationDialogListener { interface ConfirmationListener {
fun onConfirm() fun onConfirm()
fun onCancel() fun onCancel()
} }

View File

@ -71,9 +71,7 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
.add(R.id.main_browse_fragment, infoFragment) .add(R.id.main_browse_fragment, infoFragment)
.add(R.id.main_browse_fragment, channelFragment) .add(R.id.main_browse_fragment, channelFragment)
.add(R.id.main_browse_fragment, mainFragment) .add(R.id.main_browse_fragment, mainFragment)
// .add(R.id.main_browse_fragment, errorFragment)
.hide(mainFragment) .hide(mainFragment)
// .hide(errorFragment)
.commit() .commit()
} }
gestureDetector = GestureDetector(this, GestureListener()) gestureDetector = GestureDetector(this, GestureListener())
@ -169,11 +167,15 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
handler.postDelayed(hideMain, delayHideMain) handler.postDelayed(hideMain, delayHideMain)
} }
fun settingActive() { fun settingDelayHide() {
handler.removeCallbacks(hideSetting) handler.removeCallbacks(hideSetting)
handler.postDelayed(hideSetting, delayHideSetting) handler.postDelayed(hideSetting, delayHideSetting)
} }
fun settingNeverHide() {
handler.removeCallbacks(hideSetting)
}
private val hideMain = Runnable { private val hideMain = Runnable {
if (!mainFragment.isHidden) { if (!mainFragment.isHidden) {
supportFragmentManager.beginTransaction().hide(mainFragment).commit() supportFragmentManager.beginTransaction().hide(mainFragment).commit()
@ -268,7 +270,7 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
Log.i(TAG, "settingFragment ${settingFragment.isVisible}") Log.i(TAG, "settingFragment ${settingFragment.isVisible}")
if (!settingFragment.isVisible) { if (!settingFragment.isVisible) {
settingFragment.show(supportFragmentManager, "setting") settingFragment.show(supportFragmentManager, "setting")
settingActive() settingDelayHide()
} else { } else {
handler.removeCallbacks(hideSetting) handler.removeCallbacks(hideSetting)
settingFragment.dismiss() settingFragment.dismiss()
@ -334,6 +336,7 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
} }
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
Log.i(TAG, "keyCode $keyCode, event $event")
when (keyCode) { when (keyCode) {
KeyEvent.KEYCODE_0 -> { KeyEvent.KEYCODE_0 -> {
showChannel("0") showChannel("0")

View File

@ -2,11 +2,13 @@ package com.lizongying.mytv
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.leanback.app.BrowseSupportFragment import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter import androidx.leanback.widget.ArrayObjectAdapter
import androidx.leanback.widget.HeaderItem import androidx.leanback.widget.HeaderItem
import androidx.leanback.widget.ImageCardView
import androidx.leanback.widget.ListRow import androidx.leanback.widget.ListRow
import androidx.leanback.widget.ListRowPresenter import androidx.leanback.widget.ListRowPresenter
import androidx.leanback.widget.ListRowPresenter.SelectItemViewHolderTask import androidx.leanback.widget.ListRowPresenter.SelectItemViewHolderTask
@ -38,6 +40,29 @@ class MainFragment : BrowseSupportFragment() {
headersState = HEADERS_DISABLED headersState = HEADERS_DISABLED
} }
// override fun onCreateView(
// inflater: LayoutInflater,
// container: ViewGroup?,
// savedInstanceState: Bundle?
// ): View? {
// val rootView = super.onCreateView(inflater, container, savedInstanceState)
// rootView?.setOnClickListener {
// Log.i(TAG, "main on click")
// fragmentManager!!.beginTransaction().hide(this).commit()
// }
// mainFragment.view?.setOnClickListener {
// Log.i(TAG, "mainFragment on click")
// fragmentManager!!.beginTransaction().hide(this).commit()
// }
// getRowsSupportFragment().view?.setOnClickListener {
// Log.i(TAG, "getRowsSupportFragment on click")
// fragmentManager!!.beginTransaction().hide(this).commit()
// }
//
//
// return rootView
// }
override fun onStart() { override fun onStart() {
Log.i(TAG, "onStart") Log.i(TAG, "onStart")
super.onStart() super.onStart()
@ -122,7 +147,7 @@ class MainFragment : BrowseSupportFragment() {
private fun loadRows() { private fun loadRows() {
rowsAdapter = ArrayObjectAdapter(ListRowPresenter()) rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
val cardPresenter = CardPresenter(viewLifecycleOwner) val cardPresenter = CardPresenter(context!!)
var idx: Long = 0 var idx: Long = 0
for ((k, v) in TVList.list) { for ((k, v) in TVList.list) {
@ -133,8 +158,6 @@ class MainFragment : BrowseSupportFragment() {
tvViewModel.setItemPosition(idx2) tvViewModel.setItemPosition(idx2)
tvListViewModel.addTVViewModel(tvViewModel) tvListViewModel.addTVViewModel(tvViewModel)
listRowAdapter.add(tvViewModel) listRowAdapter.add(tvViewModel)
updateEPG(tvViewModel)
} }
tvListViewModel.maxNum.add(v.size) tvListViewModel.maxNum.add(v.size)
val header = HeaderItem(idx, k) val header = HeaderItem(idx, k)
@ -209,9 +232,6 @@ class MainFragment : BrowseSupportFragment() {
itemViewHolder: Presenter.ViewHolder?, item: Any?, itemViewHolder: Presenter.ViewHolder?, item: Any?,
rowViewHolder: RowPresenter.ViewHolder, row: Row rowViewHolder: RowPresenter.ViewHolder, row: Row
) { ) {
// if (itemViewHolder !=null) {
// (itemViewHolder.view as ImageCardView).setInfoAreaBackgroundColor(resources.getColor(R.color.focus))
// }
if (item is TVViewModel) { if (item is TVViewModel) {
tvListViewModel.setItemPositionCurrent(item.getTV().id) tvListViewModel.setItemPositionCurrent(item.getTV().id)
(activity as MainActivity).mainActive() (activity as MainActivity).mainActive()
@ -236,8 +256,11 @@ class MainFragment : BrowseSupportFragment() {
} }
fun fragmentReady() { fun fragmentReady() {
// request.fetchPage()
tvListViewModel.getTVViewModel(itemPosition)?.changed() tvListViewModel.getTVViewModel(itemPosition)?.changed()
tvListViewModel.tvListViewModel.value?.forEach { tvViewModel ->
updateEPG(tvViewModel)
}
} }
fun play(itemPosition: Int) { fun play(itemPosition: Int) {

View File

@ -62,6 +62,8 @@ object Request {
private var initRetryTimes = 0 private var initRetryTimes = 0
private var initRetryMaxTimes = 0 private var initRetryMaxTimes = 0
private var openid = "vu0-8lgGV2LW9QjDeucB9H12d_6HQWmTFgqCWg5o-VBQN4"
fun onCreate() { fun onCreate() {
Log.i(TAG, "onCreate") Log.i(TAG, "onCreate")
fetchInfoV2() fetchInfoV2()
@ -264,7 +266,7 @@ object Request {
} }
} }
} else { } else {
Log.e(TAG, "$title status error") Log.e(TAG, "$title status error $data")
if (tvModel.retryTimes < tvModel.retryMaxTimes) { if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++ tvModel.retryTimes++
if (tvModel.getTV().needToken) { if (tvModel.getTV().needToken) {
@ -319,13 +321,13 @@ object Request {
tvModel.needGetToken = false tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0 tvModel.tokenYSPRetryTimes = 0
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109;yspopenid=$openid; vusession=$token"
fetchAuth(tvModel, cookie) fetchAuth(tvModel, cookie)
} else if (response.code() == 304) { } else if (response.code() == 304) {
tvModel.needGetToken = false tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0 tvModel.tokenYSPRetryTimes = 0
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109; yspopenid=$openid; vusession=$token"
fetchVideo(tvModel, cookie) fetchVideo(tvModel, cookie)
} else { } else {
Log.e(TAG, "info status error") Log.e(TAG, "info status error")
@ -358,7 +360,7 @@ object Request {
}) })
} else { } else {
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109;yspopenid=$openid; vusession=$token"
fetchAuth(tvModel, cookie) fetchAuth(tvModel, cookie)
} }
} }
@ -376,13 +378,13 @@ object Request {
tvModel.needGetToken = false tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0 tvModel.tokenYSPRetryTimes = 0
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109; yspopenid=$openid; vusession=$token"
fetchVideo(tvModel, cookie) fetchVideo(tvModel, cookie)
} else if (response.code() == 304) { } else if (response.code() == 304) {
tvModel.needGetToken = false tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0 tvModel.tokenYSPRetryTimes = 0
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109; yspopenid=$openid; vusession=$token"
fetchVideo(tvModel, cookie) fetchVideo(tvModel, cookie)
} else { } else {
Log.e(TAG, "info status error") Log.e(TAG, "info status error")
@ -415,7 +417,7 @@ object Request {
}) })
} else { } else {
val cookie = 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" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109; yspopenid=$openid; vusession=$token"
fetchVideo(tvModel, cookie) fetchVideo(tvModel, cookie)
} }
} }
@ -495,10 +497,14 @@ object Request {
.enqueue(object : Callback<InfoV2> { .enqueue(object : Callback<InfoV2> {
override fun onResponse(call: Call<InfoV2>, response: Response<InfoV2>) { override fun onResponse(call: Call<InfoV2>, response: Response<InfoV2>) {
if (response.isSuccessful) { if (response.isSuccessful) {
val o = response.body()?.o
val t = response.body()?.t val t = response.body()?.t
val f = response.body()?.f val f = response.body()?.f
val e = response.body()?.e val e = response.body()?.e
val c = response.body()?.c val c = response.body()?.c
if (!o.isNullOrEmpty()) {
openid = o
}
if (!t.isNullOrEmpty()) { if (!t.isNullOrEmpty()) {
token = t token = t
Log.i(TAG, "token success $token") Log.i(TAG, "token success $token")

View File

@ -34,7 +34,7 @@ class SettingFragment : DialogFragment() {
isChecked = SP.channelReversal isChecked = SP.channelReversal
setOnCheckedChangeListener { _, isChecked -> setOnCheckedChangeListener { _, isChecked ->
SP.channelReversal = isChecked SP.channelReversal = isChecked
(activity as MainActivity).settingActive() (activity as MainActivity).settingDelayHide()
} }
} }
@ -42,7 +42,7 @@ class SettingFragment : DialogFragment() {
isChecked = SP.channelNum isChecked = SP.channelNum
setOnCheckedChangeListener { _, isChecked -> setOnCheckedChangeListener { _, isChecked ->
SP.channelNum = isChecked SP.channelNum = isChecked
(activity as MainActivity).settingActive() (activity as MainActivity).settingDelayHide()
} }
} }
@ -50,23 +50,34 @@ class SettingFragment : DialogFragment() {
isChecked = SP.bootStartup isChecked = SP.bootStartup
setOnCheckedChangeListener { _, isChecked -> setOnCheckedChangeListener { _, isChecked ->
SP.bootStartup = isChecked SP.bootStartup = isChecked
(activity as MainActivity).settingActive() (activity as MainActivity).settingDelayHide()
} }
} }
updateManager = UpdateManager(context, this, context.appVersionCode) updateManager = UpdateManager(context, this, context.appVersionCode)
binding.checkVersion.setOnClickListener(OnClickListenerCheckVersion(updateManager)) binding.checkVersion.setOnClickListener(
OnClickListenerCheckVersion(
activity as MainActivity,
updateManager
)
)
return binding.root return binding.root
} }
fun setVersionName(versionName: String) { fun setVersionName(versionName: String) {
binding.versionName.text = versionName if (_binding != null) {
binding.versionName.text = versionName
}
} }
internal class OnClickListenerCheckVersion(private val updateManager: UpdateManager) : internal class OnClickListenerCheckVersion(
private val mainActivity: MainActivity,
private val updateManager: UpdateManager
) :
View.OnClickListener { View.OnClickListener {
override fun onClick(view: View?) { override fun onClick(view: View?) {
mainActivity.settingDelayHide()
updateManager.checkAndUpdate() updateManager.checkAndUpdate()
} }
} }

View File

@ -960,7 +960,7 @@ object TVList {
} }
} }
val array = arrayOf("央视", "地方") val array = arrayOf("央视", "地方")
list = list.filterKeys { it in array } // list = list.filterKeys { it in array }
return list return list
} }
} }

View File

@ -30,7 +30,7 @@ class UpdateManager(
private var settingFragment: SettingFragment, private var settingFragment: SettingFragment,
private var versionCode: Long private var versionCode: Long
) : ) :
ConfirmationDialogFragment.ConfirmationDialogListener { ConfirmationFragment.ConfirmationListener {
private var myRequest = MyRequest() private var myRequest = MyRequest()
private var release: ReleaseV2? = null private var release: ReleaseV2? = null
@ -47,12 +47,10 @@ class UpdateManager(
release = myRequest.getRelease() release = myRequest.getRelease()
Log.i(TAG, "versionCode $versionCode ${release?.c}") Log.i(TAG, "versionCode $versionCode ${release?.c}")
if (release?.c != null) { if (release?.c != null) {
if (release?.c!! >= versionCode) { text = if (release?.c!! > versionCode) {
text = "最新版本:${release?.n}" "最新版本:${release?.n}\n${release?.d ?: ""}"
val dialog = ConfirmationDialogFragment(this@UpdateManager)
dialog.show(settingFragment.fragmentManager, "ConfirmationDialogFragment")
} else { } else {
text = "已是最新版本,不需要更新" "已是最新版本,不需要更新"
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
@ -63,10 +61,11 @@ class UpdateManager(
} }
private fun updateUI(text: String) { private fun updateUI(text: String) {
settingFragment.setVersionName(text) val dialog = ConfirmationFragment(this@UpdateManager, text)
dialog.show(settingFragment.fragmentManager, TAG)
} }
fun haveStoragePermission(): Boolean { private fun haveStoragePermission(): Boolean {
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) if (checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
=== PermissionChecker.PERMISSION_GRANTED === PermissionChecker.PERMISSION_GRANTED
@ -102,7 +101,7 @@ class UpdateManager(
Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_DOWNLOADS,
apkFileName apkFileName
) )
request.setTitle("New Version Download") request.setTitle("${settingFragment.resources.getString(R.string.app_name)} ${release.n}")
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setAllowedOverRoaming(false) request.setAllowedOverRoaming(false)
request.setMimeType("application/vnd.android.package-archive") request.setMimeType("application/vnd.android.package-archive")

View File

@ -128,9 +128,12 @@ class ApiClient {
val sslContext = SSLContext.getInstance("SSL") val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom()) sslContext.init(null, trustAllCerts, java.security.SecureRandom())
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8888))
val builder = OkHttpClient.Builder() val builder = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager) .sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
.hostnameVerifier { _, _ -> true } .hostnameVerifier { _, _ -> true }
// .proxy(proxy)
.dns(DnsCache()) .dns(DnsCache())
return enableTls12OnPreLollipop(builder).build() return enableTls12OnPreLollipop(builder).build()

View File

@ -16,6 +16,7 @@ data class Token(
) )
data class InfoV2( data class InfoV2(
val o: String?,
val f: String?, val f: String?,
val t: String?, val t: String?,
val e: Int?, val e: Int?,
@ -25,6 +26,7 @@ data class InfoV2(
data class ReleaseV2( data class ReleaseV2(
val n: String?, val n: String?,
val u: String?, val u: String?,
val d: String?,
val c: Int?, val c: Int?,
) )

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>