Skip to content

Commit

Permalink
support txt & m3u
Browse files Browse the repository at this point in the history
  • Loading branch information
lizongying committed Apr 15, 2024
1 parent 7fc85b2 commit 1ff24cc
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 25 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@

## 更新日志

### v1.0.7

* 支持rtsp直播
* 支持循环播放
* 支持txt/m3u视频源

### v1.0.6

* 修复视频可能无声音的问题
Expand Down Expand Up @@ -88,11 +94,8 @@ adb install my-tv-0.apk

* 音量不同
* 收藏夹
* 自定义源
* 节目增加预告
* 频道列表优化
* 更新的视频源不会覆盖已有的节目源
* 更新后自动播放
* 节目列表焦点消失的问题

## 赞赏
Expand Down
4 changes: 4 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ dependencies {
// For HLS playback support with ExoPlayer
implementation("androidx.media3:media3-exoplayer-hls:$media3Version")

implementation("androidx.media3:media3-exoplayer-rtsp:$media3Version")

implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.leanback:leanback:1.0.0")
implementation("com.github.bumptech.glide:glide:4.11.0")
Expand All @@ -94,4 +96,6 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC")

implementation(files("libs/lib-decoder-ffmpeg-release.aar"))

implementation("io.github.lizongying:gua64:1.4.3")
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Expand Down
46 changes: 26 additions & 20 deletions app/src/main/java/com/lizongying/mytv0/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import android.view.WindowManager
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import com.lizongying.mytv0.models.TVList
import kotlin.math.abs


class MainActivity : FragmentActivity() {
Expand Down Expand Up @@ -147,25 +146,23 @@ class MainActivity : FragmentActivity() {
return super.onFling(e1, e2, velocityX, velocityY)
}

override fun onScroll(
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
// 计算手势滑动的方向和距离
val deltaY = e1?.y?.let { e2.y.minus(it) } ?: 0f
val deltaX = e1?.x?.let { e2.x.minus(it) } ?: 0f

// 如果是垂直滑动
if (abs(deltaY) > abs(deltaX)) {
if ((e1?.x ?: 0f) > windowManager.defaultDisplay.width * 2 / 3) {
adjustVolume(deltaY) // 调整音量
}
}

return super.onScroll(e1, e2, distanceX, distanceY)
}
// override fun onScroll(
// e1: MotionEvent?,
// e2: MotionEvent,
// distanceX: Float,
// distanceY: Float
// ): Boolean {
// val deltaY = e1?.y?.let { e2.y.minus(it) } ?: 0f
// val deltaX = e1?.x?.let { e2.x.minus(it) } ?: 0f
//
// if (abs(deltaY) > abs(deltaX)) {
// if ((e1?.x ?: 0f) > windowManager.defaultDisplay.width * 2 / 3) {
// adjustVolume(deltaY)
// }
// }
//
// return super.onScroll(e1, e2, distanceX, distanceY)
// }

private fun adjustVolume(deltaY: Float) {
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
Expand Down Expand Up @@ -200,7 +197,16 @@ class MainActivity : FragmentActivity() {
// // 可以添加一个toast来显示当前亮度
// Toast.makeText(context, "Brightness: $brightness", Toast.LENGTH_SHORT).show()
// }
}

fun onPlayEnd() {
val tvModel = TVList.getTVModelCurrent()
if (SP.repeatInfo) {
infoFragment.show(tvModel)
if (SP.channelNum) {
channelFragment.show(tvModel)
}
}
}

fun play(position: Int) {
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/com/lizongying/mytv0/PlayerFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.Player.REPEAT_MODE_ALL
import androidx.media3.common.VideoSize
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DataSource
Expand All @@ -24,6 +25,7 @@ import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil
import com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION
import com.google.android.exoplayer2.SimpleExoPlayer
import com.lizongying.mytv0.databinding.PlayerBinding
import com.lizongying.mytv0.models.TVModel
Expand All @@ -41,6 +43,13 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback {

private lateinit var surfaceView: SurfaceView

private lateinit var mainActivity: MainActivity

override fun onActivityCreated(savedInstanceState: Bundle?) {
mainActivity = activity as MainActivity
super.onActivityCreated(savedInstanceState)
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
Expand Down Expand Up @@ -71,6 +80,7 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback {
.build()
}
playerView.player = player
player?.repeatMode = REPEAT_MODE_ALL
player?.playWhenReady = true
player?.addListener(object : Player.Listener {
override fun onVideoSizeChanged(videoSize: VideoSize) {
Expand All @@ -87,6 +97,28 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback {
}
}

override fun onIsPlayingChanged(isPlaying: Boolean) {
Log.i(TAG, "isPlaying $isPlaying")
super.onIsPlayingChanged(isPlaying)
}

override fun onPlaybackStateChanged(playbackState: Int) {
Log.i(TAG, "playbackState $playbackState")
super.onPlaybackStateChanged(playbackState)
}


override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
newPosition: Player.PositionInfo,
reason: Int
) {
if (reason == DISCONTINUITY_REASON_PERIOD_TRANSITION) {
mainActivity.onPlayEnd()
}
super.onPositionDiscontinuity(oldPosition, newPosition, reason)
}

override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
tvModel?.setReady()
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/lizongying/mytv0/SP.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ object SP {

private const val KEY_POSITION_SUB = "position_sub"

private const val KEY_REPEAT_INFO = "repeat_info"

private lateinit var sp: SharedPreferences

/**
Expand Down Expand Up @@ -56,4 +58,8 @@ object SP {
var positionSub: Int
get() = sp.getInt(KEY_POSITION_SUB, 0)
set(value) = sp.edit().putInt(KEY_POSITION_SUB, value).apply()

var repeatInfo: Boolean
get() = sp.getBoolean(KEY_REPEAT_INFO, true)
set(value) = sp.edit().putBoolean(KEY_REPEAT_INFO, value).apply()
}
7 changes: 7 additions & 0 deletions app/src/main/java/com/lizongying/mytv0/SettingFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ class SettingFragment : Fragment() {
(activity as MainActivity).settingActive()
}

val switchRepeatInfo = _binding?.switchRepeatInfo
switchRepeatInfo?.isChecked = SP.repeatInfo
switchRepeatInfo?.setOnCheckedChangeListener { _, isChecked ->
SP.repeatInfo = isChecked
(activity as MainActivity).settingActive()
}

val updateManager = UpdateManager(context, this, context.appVersionCode)
binding.checkVersion.setOnClickListener {
OnClickListenerCheckVersion(updateManager)
Expand Down
99 changes: 97 additions & 2 deletions app/src/main/java/com/lizongying/mytv0/models/TVList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData
import com.google.gson.JsonSyntaxException
import com.lizongying.mytv0.R
import com.lizongying.mytv0.showToast
import io.github.lizongying.Gua
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -98,8 +99,98 @@ object TVList {
}

private fun str2List(str: String) {
val type = object : com.google.gson.reflect.TypeToken<List<TV>>() {}.type
list = com.google.gson.Gson().fromJson(str, type)
var string = str
val g = Gua()
if (g.verify(str)) {
string = g.decode(str)
}
if (string.isBlank()) {
return
}
Log.i("string", string)
Log.i("string first", "${string[0]}")
when (string[0]) {
'[' -> {
Log.i("", "1111111")
val type = object : com.google.gson.reflect.TypeToken<List<TV>>() {}.type
list = com.google.gson.Gson().fromJson(string, type)
}

'#' -> {
Log.i("", "2222222")
val lines = string.lines()

Log.i("lines", "$lines")
val nameRegex = Regex("""tvg-name="([^"]+)"""")
val logRegex = Regex("""tvg-logo="([^"]+)"""")
val groupRegex = Regex("""group-title="([^"]+)"""")

val l = mutableListOf<TV>()
for ((index, line) in lines.withIndex()) {
val trimmedLine = line.trim()
if (trimmedLine.startsWith("#EXTINF")) {
val info = trimmedLine.split(",")
Log.i("info", "$info")

val title = info.last()
val name = nameRegex.find(info.first())?.groupValues?.get(1)
val group = groupRegex.find(info.first())?.groupValues?.get(1)
val logo = logRegex.find(info.first())?.groupValues?.get(1)
val uris =
if (index + 1 < lines.size) listOf(lines[index + 1]) else emptyList()
Log.i("info", "$title $name $group $logo $uris")
val tv = TV(
0,
name!!,
title,
"",
logo!!,
"",
uris,
mapOf(),
group!!,
listOf(),
)

l.add(tv)
}
}
list = l
}

else -> {
Log.i("", "333333")
val lines = string.lines()
var group = ""
val l = mutableListOf<TV>()
for (line in lines) {
val trimmedLine = line.trim()
if (trimmedLine.isNotEmpty()) {
if (trimmedLine.contains("#genre#")) {
group = trimmedLine.split(',', limit = 2)[0].trim()
} else {
val arr = trimmedLine.split(',').map { it.trim() }
val tv = TV(
0,
"",
arr.first(),
"",
"",
"",
arr.drop(1),
mapOf(),
group,
listOf(),
)

l.add(tv)
}
}
}
list = l
}
}

Log.i("TVList", "$list")

listModel = list.map { tv ->
Expand Down Expand Up @@ -130,6 +221,10 @@ object TVList {
}
}

fun getTVModelCurrent(): TVModel {
return getTVModel(position.value!!)
}

fun getTVModel(idx: Int): TVModel {
return listModel[idx]
}
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/layout/setting.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,11 @@
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Switch
android:id="@+id/switch_repeat_info"
android:text="@string/title_repeat_info"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
<string name="appreciate">赞赏</string>
<string name="channels">配置地址</string>
<string name="confirm">确认</string>
<string name="title_repeat_info">循环播放时显示信息</string>
</resources>

0 comments on commit 1ff24cc

Please sign in to comment.