Skip to content

Commit 3e5df0a

Browse files
committed
support program list
1 parent 8893242 commit 3e5df0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+828
-348
lines changed

.github/workflows/build.yml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ jobs:
2222
distribution: 'temurin'
2323
cache: 'gradle'
2424

25+
- name: Run build with Gradle wrapper
26+
run: ./gradlew clean && ./gradlew assembleRelease
27+
28+
- name: Sign app APK
29+
id: sign_app
30+
uses: r0adkll/sign-android-release@v1
31+
with:
32+
releaseDirectory: app/build/outputs/apk/release
33+
alias: ${{ secrets.ALIAS }}
34+
signingKeyBase64: ${{ secrets.KEYSTORE }}
35+
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
36+
keyPassword: ${{ secrets.ALIAS_PASSWORD }}
37+
env:
38+
# override default build-tools version (29.0.3) -- optional
39+
BUILD_TOOLS_VERSION: "34.0.0"
40+
2541
- name: Get History
2642
id: get_history
2743
run: |
@@ -41,27 +57,11 @@ jobs:
4157
prerelease: false
4258
body_path: history.md
4359

44-
- name: Run build with Gradle wrapper
45-
run: ./gradlew clean && ./gradlew assembleRelease
46-
47-
- name: Sign app APK
48-
id: sign_app
49-
uses: r0adkll/sign-android-release@v1
50-
with:
51-
releaseDirectory: app/build/outputs/apk/release
52-
alias: ${{ secrets.ALIAS }}
53-
signingKeyBase64: ${{ secrets.KEYSTORE }}
54-
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
55-
keyPassword: ${{ secrets.ALIAS_PASSWORD }}
56-
env:
57-
# override default build-tools version (29.0.3) -- optional
58-
BUILD_TOOLS_VERSION: "34.0.0"
59-
6060
- name: Set Asset Name
6161
id: set_asset_name
6262
run: |
6363
VERSION_WITHOUT_V=$(echo '${{ github.ref_name }}' | sed 's/^v//')
64-
echo "asset_name=my-tv-0.${VERSION_WITHOUT_V}.apk" >> $GITHUB_ENV
64+
echo "asset_name=my-tv-0_${VERSION_WITHOUT_V}.apk" >> $GITHUB_ENV
6565
6666
- name: Upload Release Asset
6767
uses: actions/upload-release-asset@v1

HISTORY.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
## 更新日誌
22

3+
### v1.3.9.7-kitkat
4+
5+
* 遙控器左鍵/觸屏長按打開節目單
6+
7+
### v1.3.9.7
8+
9+
* 修復無法退出的問題
10+
* 優化tvg-chno
11+
12+
### v1.3.9.6
13+
14+
* 遙控器左鍵/觸屏長按打開節目單
15+
16+
### v1.3.9.3
17+
18+
* 支持m3u設置tvg-chno
19+
20+
### v1.3.9.2
21+
22+
* 優化手機上遠程配置
23+
24+
### v1.3.9.0
25+
26+
* 支持socks代理
27+
* 支持m3u設置headers
28+
329
### v1.3.8.17-kitkat
430

531
* 優化LOGO緩存

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 李宗英
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ gen-version:
88

99
#make gen v=1.2.3
1010
gen:
11-
echo $(v) | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print "{\"version_code\": " ($$1*16777216)+($$2*65536)+($$3*256)+$$4 ", \"version_name\": \"" "v$(v)" "\"}"}' > version.json
11+
echo $(v) | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print "{\"version_code\": " ($$1*16777216)+($$2*65536)+($$3*256)+$$4 ", \"version_name\": \"" "v$(v)" "\", \"apk_name\": \"" "my-tv-0_$(v).apk" "\", \"apk_url\": \"" "https://mirror.ghproxy.com/github.com/lizongying/my-tv-0/releases/download/v$(v)/my-tv-0_$(v).apk" "\"}"}' > version.json
1212

1313
channels:
1414
gua64 -f -e files/channels.json -o app/src/main/res/raw/channels.txt

README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
## 使用
88

9-
* 遙控器左鍵/觸屏單擊打開視頻列表
9+
* 遙控器中鍵/觸屏單擊打開視頻列表
1010
* 遙控器右鍵/觸屏雙擊打開配置
11+
* 遙控器左鍵/觸屏長按打開節目單
1112
* 遙控器返回鍵關閉視頻列表/配置
1213
* 在聚焦視頻標題的時候,右鍵收藏/取消收藏
1314
* 打開配置后,選擇遠程配置,掃描二維碼可以配置視頻源等。也可以直接遠程配置地址 http://0.0.0.0:34567
@@ -17,9 +18,9 @@
1718
注意:
1819

1920
* 遇到問題可以先考慮重啟/恢復默認/清除數據/重新安裝等方式自助解決
20-
* 如果APP運行在手機上,建議在其他設備上進行遠程配置
2121
* 視頻源可以設置為本地文件,格式如:file:///mnt/sdcard/tmp/channels.m3u
2222
/channels.m3u
23+
* 目前設置代理後,需要重啟生效。代理屬於全局代理,也就是視頻請求及其他請求都會使用代理。
2324

2425
目前支持的配置格式:
2526

@@ -30,18 +31,21 @@
3031
```
3132
* m3u
3233
```
33-
#EXTM3U
34-
#EXTINF:-1 tvg-name="標準標題" tvg-logo="图标" group-title="組名",標題
34+
#EXTM3U x-tvg-url=""
35+
#EXTINF:-1 tvg-id="" tvg-chno="" tvg-name="標準標題" tvg-logo="图标" group-title="組名",標題
36+
#EXTVLCOPT:http-user-agent=
37+
#EXTVLCOPT:http-referrer=
3538
視頻地址
3639
```
3740
* json
3841
```json
3942
[
4043
{
4144
"group": "組名",
42-
"logo": "图标",
4345
"name": "標準標題",
4446
"title": "標題",
47+
"logo": "图标",
48+
"number": "頻道號",
4549
"uris": [
4650
"視頻地址"
4751
],
@@ -81,12 +85,13 @@ adb install my-tv-0.apk
8185
## TODO
8286

8387
* 支持回看
84-
* 詳細EPG
8588
* 淺色菜單
86-
* 無效的頻道?
87-
* 如果上次播放頻道不在收藏?
88-
* 當list為空,顯示group/空group不顯示?
89-
* 遠程配置使用webView
89+
90+
## 常見問題
91+
92+
* 為什麼遠程配置視頻源文本後,再次打開應用後又恢復到原來的配置?
93+
94+
如果“應用啟動后更新視頻源”開啟後,且存在視頻源地址,則會自動更新,可能會覆蓋已保存的視頻源文本。
9095

9196
## 讚賞
9297

app/build.gradle.kts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ dependencies {
7979
implementation(libs.media3.exoplayer.hls)
8080
implementation(libs.media3.exoplayer.dash)
8181
implementation(libs.media3.exoplayer.rtsp)
82-
//implementation(libs.media3.datasource.okhttp)
82+
// implementation(libs.media3.datasource.okhttp)
8383
implementation(libs.media3.datasource.rtmp)
8484

8585
implementation(libs.nanohttpd)
@@ -89,8 +89,6 @@ dependencies {
8989

9090
implementation(libs.gson)
9191
implementation(libs.okhttp)
92-
implementation(libs.converter.gson)
93-
implementation(libs.retrofit)
9492

9593
implementation(libs.core.ktx)
9694
implementation(libs.coroutines)

app/src/main/java/com/lizongying/mytv0/ChannelFragment.kt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.lizongying.mytv0
33
import MainViewModel
44
import android.os.Bundle
55
import android.os.Handler
6+
import android.util.Log
67
import android.view.LayoutInflater
78
import android.view.View
89
import android.view.ViewGroup
@@ -59,13 +60,18 @@ class ChannelFragment : Fragment() {
5960
fun show(tvViewModel: TVModel) {
6061
handler.removeCallbacks(hideRunnable)
6162
handler.removeCallbacks(playRunnable)
62-
binding.content.text = (tvViewModel.tv.id.plus(1)).toString()
63+
if (_binding != null) {
64+
binding.content.text =
65+
if (tvViewModel.tv.number == -1) (tvViewModel.tv.id.plus(1)).toString() else tvViewModel.tv.number.toString()
66+
}
6367
view?.visibility = View.VISIBLE
6468
handler.postDelayed(hideRunnable, delay)
6569
}
6670

6771
fun show(channel: String) {
68-
if (viewModel.groupModel.getCurrent()!!.tv.id > 10 && viewModel.groupModel.getCurrent()!!.tv.id == this.channel - 1) {
72+
Log.d(TAG, "input $channel")
73+
val tv = viewModel.groupModel.getCurrent()!!.tv
74+
if (tv.id > 10 && tv.id == this.channel - 1) {
6975
this.channel = 0
7076
channelCount = 0
7177
}
@@ -76,9 +82,10 @@ class ChannelFragment : Fragment() {
7682
this.channel = "${this.channel}$channel".toInt()
7783
handler.removeCallbacks(hideRunnable)
7884
handler.removeCallbacks(playRunnable)
85+
Log.d(TAG, "channelCount $channelCount")
86+
binding.content.text = this.channel.toString()
87+
view?.visibility = View.VISIBLE
7988
if (channelCount < 3) {
80-
binding.content.text = this.channel.toString()
81-
view?.visibility = View.VISIBLE
8289
handler.postDelayed(playRunnable, delay)
8390
} else {
8491
handler.postDelayed(playRunnable, 0)
@@ -108,8 +115,16 @@ class ChannelFragment : Fragment() {
108115
channelCount = 0
109116
}
110117

118+
fun hideSelf() {
119+
handler.postDelayed(hideRunnable, 0)
120+
}
121+
111122
private val playRunnable = Runnable {
112-
(activity as MainActivity).play(channel - 1)
123+
var c = channel - 1
124+
viewModel.listModel.find { it.tv.number == channel }?.let {
125+
c = it.tv.id
126+
}
127+
(activity as MainActivity).play(c)
113128
handler.postDelayed(hideRunnable, delay)
114129
}
115130

app/src/main/java/com/lizongying/mytv0/Ext.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,5 @@ fun Int.showToast(duration: Int = Toast.LENGTH_SHORT) {
9999
fun String.md5(): String {
100100
val md = MessageDigest.getInstance("MD5")
101101
val digest = md.digest(this.toByteArray())
102-
return digest.joinToString("") { String.format("%02x", it) }
102+
return digest.joinToString("") { "%02x".format(it) }
103103
}

app/src/main/java/com/lizongying/mytv0/ImageHelper.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.content.Context
44
import android.graphics.Bitmap
55
import android.graphics.drawable.BitmapDrawable
66
import android.util.Log
7-
import android.widget.ImageView
87
import com.bumptech.glide.Glide
98
import com.lizongying.mytv0.requests.HttpClient
109
import kotlinx.coroutines.Dispatchers
@@ -38,11 +37,11 @@ class ImageHelper(private val context: Context) {
3837
HttpClient.okHttpClient.newCall(request).execute().use { response ->
3938
if (!response.isSuccessful) return@withContext false
4039
response.bodyAlias()?.byteStream()?.copyTo(file.outputStream())
41-
Log.i(TAG, "downloadImage success $url")
4240
true
4341
}
4442
} catch (e: Exception) {
45-
Log.e(TAG, "downloadImage", e)
43+
// Log.e(TAG, "downloadImage error $url", e)
44+
Log.e(TAG, "downloadImage error $url")
4645
false
4746
}
4847
}
@@ -54,7 +53,7 @@ class ImageHelper(private val context: Context) {
5453
) {
5554
val file = files[key]
5655
if (file != null) {
57-
Log.i(TAG, "image exists ${file.absolutePath}")
56+
Log.d(TAG, "image exists ${file.absolutePath}")
5857
return
5958
}
6059

@@ -66,21 +65,21 @@ class ImageHelper(private val context: Context) {
6665
val file = File(cacheDir, "$LOGO/$key")
6766
if (downloadImage(url, file)) {
6867
files[file.name] = file
69-
Log.i(TAG, "image download success ${file.absolutePath}")
68+
Log.d(TAG, "downloadImage success $url ${file.absolutePath}")
7069
break
7170
}
7271
}
7372
}
7473

7574
fun loadImage(
7675
key: String,
77-
imageView: ImageView,
76+
imageView: androidx.appcompat.widget.AppCompatImageView,
7877
bitmap: Bitmap,
7978
url: String,
8079
) {
8180
val file = files[key]
8281
if (file != null) {
83-
Log.i(TAG, "image exists ${file.absolutePath}")
82+
Log.i(TAG, "$key image exists ${file.absolutePath}")
8483
Glide.with(context)
8584
.load(file)
8685
.fitCenter()
@@ -89,11 +88,13 @@ class ImageHelper(private val context: Context) {
8988
}
9089

9190
if (url.isEmpty()) {
91+
Log.i(TAG, "$key image bitmap")
9292
Glide.with(context)
9393
.load(bitmap)
9494
.fitCenter()
9595
.into(imageView)
9696
} else {
97+
Log.i(TAG, "$key image $url")
9798
Glide.with(context)
9899
.load(url)
99100
.placeholder(BitmapDrawable(context.resources, bitmap))

app/src/main/java/com/lizongying/mytv0/InfoFragment.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,22 @@ class InfoFragment : Fragment() {
7777
return
7878
}
7979

80+
val tv = tvModel.tv
81+
8082
val context = requireContext()
8183
val application = context.applicationContext as MyTVApplication
8284
val imageHelper = application.imageHelper
8385

84-
binding.title.text = tvModel.tv.title
86+
binding.title.text = tv.title
8587

86-
when (tvModel.tv.title) {
88+
when (tv.title) {
8789
else -> {
8890
val width = 300
8991
val height = 180
9092
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
9193
val canvas = Canvas(bitmap)
9294

93-
val channelNum = tvModel.tv.id + 1
95+
val channelNum = if (tv.number == -1) tv.id.plus(1) else tv.number
9496
var size = 150f
9597
if (channelNum > 99) {
9698
size = 100f
@@ -107,13 +109,8 @@ class InfoFragment : Fragment() {
107109
val y = height / 2f - (paint.descent() + paint.ascent()) / 2
108110
canvas.drawText(channelNum.toString(), x, y, paint)
109111

110-
val url = tvModel.tv.logo
111-
var name = tvModel.tv.name
112-
if (name.isEmpty()) {
113-
name = tvModel.tv.title
114-
}
115-
116-
imageHelper.loadImage(name, binding.logo, bitmap, url)
112+
val name = if (tv.name.isNotEmpty()) { tv.name } else { tv.title }
113+
imageHelper.loadImage(name, binding.logo, bitmap, tv.logo)
117114
}
118115
}
119116

0 commit comments

Comments
 (0)