Android TV 影视聚合应用,基于 takagen99/Box(TVBox 分支)二次开发的个人改版。
本仓库在 takagen99/Box 的最新代码之上(上游基线:258a5fe 系统播放器增加音轨选择)做了 4 次提交,主要围绕直播台标(Logo)自定义、桌面模式、开机自动进直播,并修复了一批稳定性问题。
- 上游仓库:https://github.com/takagen99/Box(
upstream) - 本仓库:https://github.com/XavierMu/Box(
origin)
| 提交 | 主题 | 涉及文件 |
|---|---|---|
b4a050e |
增加 Logo 配置,增加桌面模式 | 19 个文件,+369/−7 |
35cbc9a |
调整按钮,修复崩溃,优化分类返回逻辑 | 5 个文件,+57/−55 |
005af31 |
启动进直播逻辑优化 | 3 个文件,+51/−3 |
6e565a4 |
HOME 意图更为常驻,桌面模式开关仅负责返回屏蔽 | 4 个文件,+3/−43 |
与上游相比累计 19 个文件、+407 / −35。
原版直播页的台标直接取 EPG 数据里返回的 logo,来源不可控、经常缺图。改版增加了按频道名套用模板地址的能力。
配置入口(两条路,等价)
- 应用内:首页 → 设置 → 配置地址(
ApiDialog)→ 第 4 行「请输入直播Logo地址」 - 浏览器:应用内置的远程配置页(首页设置里显示的那个
http://<IP>:<端口>/地址)→「接口」页 → 新增的「4. 请输入直播Logo地址」
规则
- 地址支持
{name}占位符,会被当前频道名替换(URLEncoder编码后拼接),例如:https://live.404003.xyz/LOGO/{name}.png - 留空时使用内置默认模板
https://live.404003.xyz/LOGO/{name}.png - 不包含
{name}的地址会当作固定图片使用 - 模板图加载失败时,自动回退到 EPG 数据里提供的 logo;两者都失败则显示
img_logo_placeholder占位图 - 与直播源/EPG 地址一样,输入过的地址会进历史列表(最多 20 条),可从「历史」按钮里回选或删除
实现位置
| 环节 | 文件 |
|---|---|
配置项 LOGO_URL / LOGO_HISTORY |
app/src/main/java/com/github/tvbox/osc/util/HawkConfig.java |
| 应用内输入框 + Logo 历史 | app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiDialog.java、app/src/main/res/layout/dialog_api.xml |
| 远程网页配置 | app/src/main/res/raw/index.html、app/src/main/res/raw/script.js |
| 网页动作分发 | app/src/main/java/com/github/tvbox/osc/server/InputRequestProcess.java(case "logo") |
| 事件定义与转发 | app/src/main/java/com/github/tvbox/osc/event/RefreshEvent.java(TYPE_LOGO_URL_CHANGE)、server/ControlManager.java、server/DataReceiver.java |
| 台标加载与兜底 | app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java → getTvLogo() |
把应用变成一台**「开机即桌面」的电视盒子**:可以直接被系统选作默认桌面(Launcher),回到首页后按返回键不再退出应用。
两个独立的部分(重点,别混了)
- HOME 身份始终启用:
AndroidManifest.xml中的activity-alias.LauncherAlias(target 为HomeActivity)声明了android.intent.category.HOME+DEFAULT,并且不带android:enabled限制 —— 也就是说装好应用后,系统「主屏幕应用」列表里始终能看到它,可随时设为默认桌面。 - 设置里的「桌面模式」开关(
HawkConfig.DESKTOP_MODE,默认关闭)只控制首页返回键,不再控制 HOME 组件是否启用:- 关闭(默认):行为与原版一致,首页按两次返回键退出应用
- 开启:在「首页」按返回键被吞掉(不退出应用);在分类页按返回键仍按原逻辑回退到首页第一个分类,加载中/VOD 删除模式等分支行为不变
早期版本(
b4a050e)曾用开关去setComponentEnabledSetting()动态启停LauncherAlias,并在启用时主动拉起系统 HOME 选择框;6e565a4起已移除该逻辑,改为 HOME 身份常驻,避免重装/清数据后组件状态与开关不一致。
入口:首页 → 设置 → 「桌面模式」(中英文字符串 mn_desktop_mode)
原版 HOME_DEFAULT_SHOW(设置里的「启动时进直播」)是数据一就绪就立刻跳转,导致首页根本来不及操作。改版改为延迟进入 + 随时可取消:
- 首页数据与 jar 都就绪后,起一个 5 秒(
AUTO_LIVE_DELAY_MS = 5000)倒计时,同时 Toast 提示「5秒内无操作,将自动进入电视直播(按任意键取消)」 - 倒计时期间任意按键(
dispatchKeyEvent)、任意触摸/点击(dispatchTouchEvent)、页面离开(onPause)都会取消本次自动进入 - 每次启动只处理一次:已调度 / 已被打断 / 走
useCache重载流程时都不会再次触发 - 开关关闭时完全不触发,行为与原版为零差异
实现位置:app/src/main/java/com/github/tvbox/osc/ui/activity/HomeActivity.java(scheduleAutoLive() / cancelAutoLive() / mAutoLiveRunnable);提示文案 hm_auto_live(中/英)。
| 问题 | 现象 | 修复 |
|---|---|---|
| EPG 时间字段为空/格式异常 | Epginfo 解析 start/end 得到 null,随后 SimpleDateFormat.format(null) 抛 NPE 崩溃 |
解析失败时回退到节目日期,见 bean/Epginfo.java |
| EPG 接口返回非预期 JSON | 只 catch JSONException,其他异常(如 ClassCastException、NullPointerException)会把直播页带崩 |
改为捕获 Exception,见 LivePlayActivity.getEpg() |
| Glide 回调里再次发起加载 | 台标兜底逻辑在 RequestListener.onLoadFailed() 里 Glide.with(...).into(...),触发 IllegalArgumentException: You cannot start a load for a destroyed activity 类崩溃 |
改用官方推荐的 RequestBuilder#error() 串联兜底请求,见 LivePlayActivity.getTvLogo() |
| 服务器地址空指针 | ControlManager.getAddress() 在 mServer 尚未创建时被调用 → NPE |
增加 mServer == null 判空,返回空串 |
| 频道名为空 | 台标模板拼接 null |
channelName 判空后置空串 |
- 配置地址对话框(
dialog_api.xml):新增第 4 行 Logo 输入 + 历史按钮,总高度由vs_460增至vs_480,各行由wrap_content改为layout_weight撑满,输入框上下 padding 由vs_10收紧到vs_6,保证 5 行(数据源 / 直播源 / EPG / Logo / socks 代理)在弹窗内完整显示、不滚动 - 桌面模式设置项(
fragment_model.xml+layout-v21/fragment_model.xml):在「启动时进直播」下方新增一行开关,复用现有shape_setting_model_focus焦点样式,左右两列布局与原设置项一致 - 分类页返回逻辑:桌面模式下只屏蔽首页返回,分类页返回仍然回到首页第一个分类(原版是整个
onBackPressed直接return,分类页也退不回来)
applicationId由上游的com.github.tvbox.osc.tk改为com.github.tvbox.osc.mx(hisense 变体同步为com.github.hisense.osc.mx),避免与上游/原版签名冲突、可与之共存安装release构建改用 debug 签名(signingConfig signingConfigs.debug),方便自行出包直接安装,无需额外配置 keystore
注意:debug 签名不适合对外分发;如需正式发布,请改用自己的 keystore 配置。
环境
- JDK 11+(Gradle 7.5 / AGP 7.4.2)
- Android SDK:
compileSdk 34、minSdk 21、targetSdk 28 local.properties中配置sdk.dir
变体维度:abi(armeabi / arm64)× brand(generic / hisense)× mode(normal / python)
常见构建命令
# 通用 armeabi-v7a + Java 版 release(本仓库常用产物)
./gradlew assembleArmeabiGenericNormalRelease
# 通用 arm64 + Java 版 release
./gradlew assembleArm64GenericNormalRelease
# 带 Python 支持的版本
./gradlew assembleArm64GenericPythonRelease产物路径:app/build/outputs/apk/<变体>/release/,文件名规则为 TVBox_<buildType>-<abi>-<brand>-<mode>.apk(normal 显示为 java),例如:
app/build/outputs/apk/armeabiGenericNormal/release/TVBox_release-armeabi-generic-java.apk
安装后在首页 → 设置里配置数据源(接口地址)、直播源、EPG、直播 Logo,即可使用。
git remote add upstream https://github.com/takagen99/Box.git # 已配置可跳过
git fetch upstream
git merge upstream/main本改版刻意把改动控制在一个很小的集合里(19 个文件、不新增依赖、不改播放内核),冲突面基本集中在 HomeActivity、ApiDialog、dialog_api.xml、fragment_model.xml、strings.xml 这几处。
| 想改什么 | 去哪里 |
|---|---|
| 默认设置项(播放器、首页、DNS 等) | app/src/main/java/com/github/tvbox/osc/base/App.java → initParams() |
| Logo 默认模板地址 | LivePlayActivity.getTvLogo() 中的 https://live.404003.xyz/LOGO/{name}.png |
| 自动进直播延迟时长 | HomeActivity.AUTO_LIVE_DELAY_MS(默认 5000 ms) |
| 桌面模式 HOME 入口 | app/src/main/AndroidManifest.xml 的 <activity-alias android:name=".LauncherAlias"> |
| 桌面模式返回键行为 | HomeActivity.onBackPressed() |
| 远程配置页端口 | app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java → serverPort(默认 9978,占用则自增) |
=== Source Code - Editing the app default settings ===
app/src/main/java/com/github/tvbox/osc/base/App.java
private void initParams() {
// 首页选项
putDefault(HawkConfig.HOME_SHOW_SOURCE, true); // 数据源显示: true=开启, false=关闭
putDefault(HawkConfig.HOME_SEARCH_POSITION, false); // 按钮位置-搜索: true=上方, false=下方
putDefault(HawkConfig.HOME_MENU_POSITION, true); // 按钮位置-设置: true=上方, false=下方
putDefault(HawkConfig.HOME_REC, 1); // 推荐: 0=豆瓣热播, 1=站点推荐, 2=观看历史
putDefault(HawkConfig.HOME_NUM, 4); // 历史条数: 0=20条, 1=40条, 2=60条, 3=80条, 4=100条
// 播放器选项
putDefault(HawkConfig.SHOW_PREVIEW, true); // 窗口预览
putDefault(HawkConfig.PLAY_SCALE, 0); // 画面缩放
putDefault(HawkConfig.BACKGROUND_PLAY_TYPE, 0); // 后台:0=关闭, 1=开启, 2=画中画
putDefault(HawkConfig.PLAY_TYPE, 1); // 播放器: 0=系统, 1=IJK, 2=Exo, 3=MX, 4=Reex, 5=Kodi
putDefault(HawkConfig.IJK_CODEC, "硬解码"); // IJK 解码: 软解码 / 硬解码
// 系统选项
putDefault(HawkConfig.HOME_LOCALE, 0); // 语言: 0=中文, 1=英文
putDefault(HawkConfig.THEME_SELECT, 0); // 主题: 0=奈飞, 1=哆啦, 2=百事, ...
putDefault(HawkConfig.SEARCH_VIEW, 1); // 搜索展示: 0=文字列表, 1=缩略图
putDefault(HawkConfig.PARSE_WEBVIEW, true); // 嗅探 Webview: true=系统自带, false=XWalkView
putDefault(HawkConfig.DOH_URL, 0); // 安全DNS: 0=关闭, 1=腾讯, 2=阿里, ...
}putDefault() 只在键不存在时写入,因此升级安装不会覆盖用户已有的设置。
- 上游项目:takagen99/Box,以及更早的 TVBox 开源生态作者
- 本项目遵循 GNU AGPL-3.0(见 LICENSE),二次分发请同样开源
本仓库仅用于个人学习与技术研究,应用本身不提供任何影视内容,所有数据源均由用户自行配置。