MT MTBOX GitHub

Android · GPL-3.0 · secondary-developed from FongMi/TV

MTBOXAndroid video & local-music toolbox

Secondary-developed from the open-source FongMi/TV project (GPL-3.0). Package com.matou.mtbox, version 6.6.19. The whole package — baseline, patches, music engine and build scripts — is open source. Local decoding, works offline, no cloud account.

Version 6.6.19 GPL-3.0 com.matou.mtbox Android 7.0+ No content sources
build.ps1
# 1) resource ids shift, so regenerate R.java every round
powershell -File javainject\genr.ps1 -Apk app.apk

# 2) compile + inject + sign (apktool runs twice)
powershell -File javainject\build.ps1 -Tag music

→ mtbox-music-signed.apk
About

What it is

Two halves

The decompiled baseline (FongMi/TV 5.6.1 → com.matou.mtbox 6.6.19) plus every smali patch, with apktool run twice to pin the resource ids down.

The music engine is injected

Thirteen hand-written Java files through javac and d8 produce a classes4.dex, dropped into work_fong/unknown and copied verbatim into the APK — no smali round-trip.

A transparent audio path

Equalizer and BassBoost only. LoudnessEnhancer stays off, setPlaybackParams is never called at 1.0×, and lossless sources stay on the native path.

Features

What it does

Everything below ships in the published package.

01

Covers non-HarmonyOS devices

A separate Android package next to TTBOX, so the Android projector or the old tablet in the house can play too.

02

Self-held signing key

Signed with a keystore I keep myself, verifiable before install, never re-signed by a third party.

03

Local import, straight to playback

No cloud account, no sign-in. Import local media and it plays; the network can be off entirely.

04

Open source under GPL-3.0

The whole package — music engine and build scripts included — is on GitHub, and the FongMi/TV baseline is GPL-3.0 as well.

05

Transparent audio path

Equalizer and BassBoost only; LoudnessEnhancer is never enabled, setPlaybackParams is untouched at 1.0×, and lossless sources play through the native path.

Screens

In the interface

MTBOX local music, track list
Local music · track list
MTBOX lyric panel, word-synced
Lyrics panel · word-synced
MTBOX theme and playback
Theme and playback
Architecture

How the package is assembled

Two halves — the decompiled baseline plus the injected music engine — with apktool run twice to pin the resource ids down.

The work_fong baseline

FongMi/TV 5.6.1 decompiled, package renamed to com.matou.mtbox, version bumped to 6.6.19 (versionCode 60619).

smali patches

Unified theming, the version display, fullscreen rotation and the security hardening all live in smali, each one with a written-up plan.

The javainject music engine

Thirteen hand-written Java files through javac and d8 produce a classes4.dex, dropped into work_fong/unknown and copied verbatim into the APK by apktool.

R.java regeneration

genr.ps1 assembles the resource id table from public.xml and an aapt2 dump. Touch res/ and every id shifts, which is why the build runs twice.

The unknown directory

apktool copies everything under work_fong/unknown into the APK as-is, and ART loads classes 1 through 4.dex together.

Signing

apksigner signs v2/v3 and verifies; the keystore stays with me and out of the repository.

Build

Building it locally

Four steps, and the order matters.

  1. 01

    Generate R.java

    powershell -File javainject/genr.ps1 -Apk <freshly built .apk>. Resource ids shift, so this runs on every round.

  2. 02

    Set the signing passwords

    Export MTBOX_KS_PASS and MTBOX_KEY_PASS. You generate your own keystore.

  3. 03

    Package

    powershell -File javainject/build.ps1 -Tag music. apktool runs twice — do not skip pass 1.

  4. 04

    Verify

    apksigner verify passes and the ids in R.java line up (tabSongs, musicList and the rest) — that is what success looks like.

Questions

FAQ

Why does apktool have to run twice?
Touch res/ and aapt2 re-sorts the whole @+id table, while R.id is a compile-time constant. Pass 1 captures the resource table and regenerates R.java; pass 2 packages the same res. Only then do the two passes agree on the ids. Skip pass 1 and findViewById returns somebody else's view — or null — and the app dies on the spot.
Why not write the music engine in smali?
Thirteen hand-written Java files go through javac and d8 into a classes4.dex, which goes straight into work_fong/unknown — apktool copies that directory into the APK verbatim. It saves a whole round of smali compilation and never touches a register.
Does the sound effect chain distort anything?
The chain is Equalizer plus BassBoost only; LoudnessEnhancer is disabled — it is a dynamic loudness processor, not a gain, and it clips full-scale lossless sources. The original preset is all-zero EQ plus zero bass, which is completely transparent.
Can the lock screen and the car be controlled?
Hardware media keys work: headset and car skip, play and pause are forwarded into the container. The lock-screen and control-centre media cards do not appear — they depend on the system querying the MediaSession, and container isolation blocks that. No fix exists at the app layer.
Why are no sources bundled?
Deliberately. Every external subscription is configured by the user; the project ships no content sources and no online parsing URLs.
Credits

Upstream

  • FongMi/TV —— the baseline this project is built on, GPL-3.0
  • mpv —— playback core, GPL-2.0-or-later
  • FFmpeg —— codecs, LGPL / GPL