my-tv/app/src/main/java/com/lizongying/mytv/MainActivity.kt

529 lines
15 KiB
Kotlin
Raw Normal View History

2023-12-04 19:36:29 +08:00
package com.lizongying.mytv
2024-01-16 19:04:43 +08:00
import android.content.Context
import android.content.SharedPreferences
2023-12-15 13:04:32 +08:00
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.content.pm.SigningInfo
import android.os.Build
2023-12-04 19:36:29 +08:00
import android.os.Bundle
import android.os.Handler
import android.os.Looper
2023-12-15 13:04:32 +08:00
import android.util.Log
2023-12-22 00:02:57 +08:00
import android.view.GestureDetector
2023-12-04 19:36:29 +08:00
import android.view.KeyEvent
2023-12-22 00:02:57 +08:00
import android.view.MotionEvent
2023-12-26 11:21:03 +08:00
import android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
2023-12-16 15:09:09 +08:00
import android.view.WindowManager
2023-12-04 19:36:29 +08:00
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
2024-02-11 10:42:00 +08:00
import androidx.lifecycle.lifecycleScope
2023-12-20 14:55:39 +08:00
import com.lizongying.mytv.models.TVViewModel
2024-02-11 10:42:00 +08:00
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
2023-12-15 13:04:32 +08:00
import java.security.MessageDigest
2023-12-04 19:36:29 +08:00
class MainActivity : FragmentActivity() {
2023-12-27 16:26:05 +08:00
var playerFragment = PlayerFragment()
2023-12-04 19:36:29 +08:00
private val mainFragment = MainFragment()
2023-12-15 13:04:32 +08:00
private val infoFragment = InfoFragment()
2024-01-18 21:42:06 +08:00
private val channelFragment = ChannelFragment()
2024-01-19 13:49:43 +08:00
private lateinit var settingFragment: SettingFragment
2023-12-04 19:36:29 +08:00
private var doubleBackToExitPressedOnce = false
2023-12-22 00:02:57 +08:00
private lateinit var gestureDetector: GestureDetector
2024-01-10 18:01:25 +08:00
private val handler = Handler()
2024-02-01 17:04:02 +08:00
private val delayHideMain: Long = 5000
private val delayHideSetting: Long = 10000
2024-01-10 18:01:25 +08:00
2024-01-28 16:00:33 +08:00
lateinit var sharedPref: SharedPreferences
2024-01-16 19:04:43 +08:00
private var channelReversal = false
2024-01-18 21:42:06 +08:00
private var channelNum = true
private var versionName = ""
2024-01-16 19:04:43 +08:00
2024-02-11 10:42:00 +08:00
init {
lifecycleScope.launch(Dispatchers.IO) {
val utilsJob = async(start = CoroutineStart.LAZY) { Utils.init() }
utilsJob.start()
utilsJob.await()
}
}
2023-12-04 19:36:29 +08:00
override fun onCreate(savedInstanceState: Bundle?) {
2024-02-01 17:04:02 +08:00
Log.i(TAG, "onCreate")
2023-12-04 19:36:29 +08:00
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
2023-12-22 00:02:57 +08:00
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
2023-12-26 11:21:03 +08:00
window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_HIDE_NAVIGATION
2023-12-16 15:09:09 +08:00
2023-12-04 19:36:29 +08:00
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
2023-12-26 11:21:03 +08:00
.add(R.id.main_browse_fragment, playerFragment)
2023-12-15 13:04:32 +08:00
.add(R.id.main_browse_fragment, infoFragment)
2024-01-18 21:42:06 +08:00
.add(R.id.main_browse_fragment, channelFragment)
2023-12-28 20:30:12 +08:00
.add(R.id.main_browse_fragment, mainFragment)
2024-01-19 13:49:43 +08:00
.hide(mainFragment)
2023-12-04 19:36:29 +08:00
.commit()
}
2023-12-22 00:02:57 +08:00
gestureDetector = GestureDetector(this, GestureListener())
2024-01-16 19:04:43 +08:00
sharedPref = getPreferences(Context.MODE_PRIVATE)
2024-01-18 21:42:06 +08:00
channelReversal = sharedPref.getBoolean(CHANNEL_REVERSAL, channelReversal)
channelNum = sharedPref.getBoolean(CHANNEL_NUM, channelNum)
versionName = getPackageInfo().versionName
2024-01-19 13:49:43 +08:00
settingFragment = SettingFragment(versionName, channelReversal, channelNum)
2023-12-04 19:36:29 +08:00
}
2023-12-27 23:53:03 +08:00
fun showInfoFragment(tvViewModel: TVViewModel) {
2023-12-28 20:30:12 +08:00
infoFragment.show(tvViewModel)
2024-01-18 21:42:06 +08:00
if (channelNum) {
channelFragment.show(tvViewModel)
}
2023-12-15 13:04:32 +08:00
}
2024-01-19 13:49:43 +08:00
private fun showChannel(channel: String) {
if (!mainFragment.isHidden) {
return
}
if (settingFragment.isVisible) {
return
}
if (channelNum) {
channelFragment.show(channel)
}
}
2023-12-20 14:55:39 +08:00
fun play(tvViewModel: TVViewModel) {
2023-12-26 11:21:03 +08:00
playerFragment.play(tvViewModel)
2023-12-27 18:17:13 +08:00
mainFragment.view?.requestFocus()
2023-12-04 19:36:29 +08:00
}
2024-01-18 21:42:06 +08:00
fun play(itemPosition: Int) {
mainFragment.play(itemPosition)
}
2023-12-04 19:36:29 +08:00
fun prev() {
mainFragment.prev()
}
fun next() {
mainFragment.next()
}
2023-12-27 16:26:05 +08:00
private fun prevSource() {
2024-01-18 21:42:06 +08:00
// mainFragment.prevSource()
2023-12-06 23:51:17 +08:00
}
2023-12-27 16:26:05 +08:00
private fun nextSource() {
2024-01-18 21:42:06 +08:00
// mainFragment.nextSource()
2023-12-06 23:51:17 +08:00
}
2023-12-04 19:36:29 +08:00
fun switchMainFragment() {
val transaction = supportFragmentManager.beginTransaction()
if (mainFragment.isHidden) {
transaction.show(mainFragment)
2024-01-10 18:01:25 +08:00
keepRunnable()
2023-12-04 19:36:29 +08:00
} else {
transaction.hide(mainFragment)
}
transaction.commit()
}
2024-01-10 18:01:25 +08:00
fun keepRunnable() {
2024-02-01 17:04:02 +08:00
handler.removeCallbacks(hideMain)
handler.postDelayed(hideMain, delayHideMain)
2024-01-10 18:01:25 +08:00
}
2024-02-01 17:04:02 +08:00
private val hideMain = Runnable {
2024-01-17 10:19:50 +08:00
if (!mainFragment.isHidden) {
supportFragmentManager.beginTransaction().hide(mainFragment).commit()
}
2024-01-10 18:01:25 +08:00
}
2023-12-27 16:26:05 +08:00
private fun mainFragmentIsHidden(): Boolean {
2023-12-04 19:36:29 +08:00
return mainFragment.isHidden
}
2023-12-06 23:51:17 +08:00
private fun hideMainFragment() {
2023-12-04 19:36:29 +08:00
if (!mainFragment.isHidden) {
supportFragmentManager.beginTransaction()
.hide(mainFragment)
.commit()
}
}
2024-01-01 22:36:03 +08:00
fun fragmentReady() {
mainFragment.fragmentReady()
}
2023-12-22 00:02:57 +08:00
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event != null) {
gestureDetector.onTouchEvent(event)
}
return super.onTouchEvent(event)
}
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
2023-12-26 11:21:03 +08:00
Log.i(TAG, "onSingleTapConfirmed")
2023-12-25 19:23:45 +08:00
switchMainFragment()
2023-12-22 00:02:57 +08:00
return true
}
override fun onFling(
2024-02-05 06:12:01 +08:00
e1: MotionEvent?,
2023-12-22 00:02:57 +08:00
e2: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
2023-12-27 16:26:05 +08:00
if (velocityY > 0) {
2023-12-22 00:02:57 +08:00
if (mainFragment.isHidden) {
prev()
} else {
2023-12-27 16:26:05 +08:00
// if (mainFragment.selectedPosition == 0) {
// mainFragment.setSelectedPosition(
// mainFragment.tvListViewModel.maxNum.size - 1,
// false
// )
// }
2023-12-22 00:02:57 +08:00
}
}
2023-12-27 16:26:05 +08:00
if (velocityY < 0) {
2023-12-22 00:02:57 +08:00
if (mainFragment.isHidden) {
next()
} else {
2023-12-27 16:26:05 +08:00
// if (mainFragment.selectedPosition == mainFragment.tvListViewModel.maxNum.size - 1) {
//// mainFragment.setSelectedPosition(0, false)
// hideMainFragment()
// return false
// }
2023-12-22 00:02:57 +08:00
}
}
return super.onFling(e1, e2, velocityX, velocityY)
}
}
2024-01-16 19:04:43 +08:00
fun saveChannelReversal(channelReversal: Boolean) {
with(sharedPref.edit()) {
putBoolean(CHANNEL_REVERSAL, channelReversal)
apply()
}
this.channelReversal = channelReversal
}
2024-01-18 21:42:06 +08:00
fun saveChannelNum(channelNum: Boolean) {
with(sharedPref.edit()) {
putBoolean(CHANNEL_NUM, channelNum)
apply()
}
this.channelNum = channelNum
}
2024-02-01 17:04:02 +08:00
private fun showSetting() {
2024-01-16 19:04:43 +08:00
if (!mainFragment.isHidden) {
return
}
2024-01-11 19:33:31 +08:00
2024-01-19 13:49:43 +08:00
Log.i(TAG, "settingFragment ${settingFragment.isVisible}")
if (!settingFragment.isVisible) {
settingFragment.show(supportFragmentManager, "setting")
2024-02-01 17:04:02 +08:00
handler.removeCallbacks(hideSetting)
handler.postDelayed(hideSetting, delayHideSetting)
2024-01-18 21:42:06 +08:00
} else {
2024-02-01 17:04:02 +08:00
handler.removeCallbacks(hideSetting)
2024-01-19 13:49:43 +08:00
settingFragment.dismiss()
2024-01-18 21:42:06 +08:00
}
}
2024-02-01 17:04:02 +08:00
private val hideSetting = Runnable {
2024-01-19 13:49:43 +08:00
if (settingFragment.isVisible) {
settingFragment.dismiss()
2024-01-18 21:42:06 +08:00
}
2024-01-11 19:33:31 +08:00
}
private fun channelUp() {
if (mainFragment.isHidden) {
2024-01-16 19:04:43 +08:00
if (channelReversal) {
next()
return
}
prev()
} else {
// if (mainFragment.selectedPosition == 0) {
// mainFragment.setSelectedPosition(
// mainFragment.tvListViewModel.maxNum.size - 1,
// false
// )
// }
}
}
2023-12-05 13:58:13 +08:00
private fun channelDown() {
if (mainFragment.isHidden) {
2024-01-16 19:04:43 +08:00
if (channelReversal) {
prev()
return
}
next()
} else {
// if (mainFragment.selectedPosition == mainFragment.tvListViewModel.maxNum.size - 1) {
//// mainFragment.setSelectedPosition(0, false)
// hideMainFragment()
// return false
// }
}
}
private fun back() {
if (!mainFragmentIsHidden()) {
hideMainFragment()
return
}
2023-12-04 19:36:29 +08:00
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
doubleBackToExitPressedOnce = true
Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show()
Handler(Looper.getMainLooper()).postDelayed({
doubleBackToExitPressedOnce = false
}, 2000)
}
2023-12-04 19:36:29 +08:00
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
2024-01-18 21:42:06 +08:00
KeyEvent.KEYCODE_0 -> {
showChannel("0")
return true
}
KeyEvent.KEYCODE_1 -> {
showChannel("1")
return true
}
KeyEvent.KEYCODE_2 -> {
showChannel("2")
return true
}
KeyEvent.KEYCODE_3 -> {
showChannel("3")
return true
}
KeyEvent.KEYCODE_4 -> {
showChannel("4")
return true
}
KeyEvent.KEYCODE_5 -> {
showChannel("5")
return true
}
KeyEvent.KEYCODE_6 -> {
showChannel("6")
return true
}
KeyEvent.KEYCODE_7 -> {
showChannel("7")
return true
}
KeyEvent.KEYCODE_8 -> {
showChannel("8")
return true
}
KeyEvent.KEYCODE_9 -> {
showChannel("9")
return true
}
2024-01-16 19:04:43 +08:00
KeyEvent.KEYCODE_ESCAPE -> {
back()
return true
}
KeyEvent.KEYCODE_BACK -> {
back()
2023-12-04 19:36:29 +08:00
return true
}
2024-01-16 19:04:43 +08:00
KeyEvent.KEYCODE_BOOKMARK -> {
2024-02-01 17:04:02 +08:00
showSetting()
2024-01-16 19:04:43 +08:00
return true
}
KeyEvent.KEYCODE_UNKNOWN -> {
2024-02-01 17:04:02 +08:00
showSetting()
2024-01-11 19:33:31 +08:00
return true
}
KeyEvent.KEYCODE_HELP -> {
2024-02-01 17:04:02 +08:00
showSetting()
return true
}
2024-01-16 19:04:43 +08:00
KeyEvent.KEYCODE_SETTINGS -> {
2024-02-01 17:04:02 +08:00
showSetting()
2024-01-16 19:04:43 +08:00
return true
}
2023-12-04 19:36:29 +08:00
KeyEvent.KEYCODE_MENU -> {
2024-02-01 17:04:02 +08:00
showSetting()
2023-12-04 19:36:29 +08:00
return true
}
2024-01-14 10:15:45 +08:00
KeyEvent.KEYCODE_ENTER -> {
switchMainFragment()
}
2023-12-04 19:36:29 +08:00
KeyEvent.KEYCODE_DPAD_CENTER -> {
switchMainFragment()
}
KeyEvent.KEYCODE_DPAD_UP -> {
channelUp()
2023-12-04 19:36:29 +08:00
}
KeyEvent.KEYCODE_CHANNEL_UP -> {
channelUp()
}
2024-01-16 19:04:43 +08:00
KeyEvent.KEYCODE_DPAD_DOWN -> {
channelDown()
}
KeyEvent.KEYCODE_CHANNEL_DOWN -> {
channelDown()
2023-12-04 19:36:29 +08:00
}
KeyEvent.KEYCODE_DPAD_LEFT -> {
2023-12-29 10:44:58 +08:00
// if (mainFragment.isHidden) {
// prevSource()
// } else {
//// if (mainFragment.tvListViewModel.getTVViewModelCurrent()
//// ?.getItemPosition() == 0
//// ) {
////// mainFragment.toLastPosition()
//// hideMainFragment()
//// }
// }
2023-12-04 19:36:29 +08:00
}
KeyEvent.KEYCODE_DPAD_RIGHT -> {
2023-12-29 10:44:58 +08:00
// if (mainFragment.isHidden) {
// nextSource()
// } else {
//// if (mainFragment.tvListViewModel.getTVViewModelCurrent()
//// ?.getItemPosition() == mainFragment.tvListViewModel.maxNum[mainFragment.selectedPosition] - 1
//// ) {
//// mainFragment.toFirstPosition()
//// }
// }
2023-12-04 19:36:29 +08:00
}
}
return super.onKeyDown(keyCode, event)
}
2023-12-15 13:04:32 +08:00
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 {
2024-01-28 16:00:33 +08:00
val md = MessageDigest.getInstance("MD5")
2023-12-15 13:04:32 +08:00
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)
""
}
}
2024-02-01 17:04:02 +08:00
override fun onStart() {
Log.i(TAG, "onStart")
super.onStart()
}
override fun onResume() {
Log.i(TAG, "onResume")
super.onResume()
2024-02-05 06:12:01 +08:00
if (!mainFragment.isHidden){
handler.postDelayed(hideMain, delayHideMain)
}
2024-02-01 17:04:02 +08:00
}
override fun onPause() {
Log.i(TAG, "onPause")
super.onPause()
handler.removeCallbacks(hideMain)
}
2023-12-04 19:36:29 +08:00
companion object {
private const val TAG = "MainActivity"
2024-01-16 19:04:43 +08:00
private const val CHANNEL_REVERSAL = "channel_reversal"
2024-01-18 21:42:06 +08:00
private const val CHANNEL_NUM = "channel_num"
2023-12-04 19:36:29 +08:00
}
}