# One Player
**A modern Android video player for local media**
[](README.md)
[](.github/docs/README.zh-CN.md)
[](https://developer.android.com)
[](https://kotlinlang.org)
[](https://developer.android.com/compose)
[](https://developer.android.com/media/media3)
> Built with **Kotlin**, **Jetpack Compose**, **Hilt**, and **Media3 / ExoPlayer**.
> Continues from the [original Next Player project](https://github.com/anilbeesetti/nextplayer) with in-app language switching, settings backup & restore, and ASS subtitle effects.
>
> Special thanks to the original [Next Player](https://github.com/anilbeesetti/nextplayer) project and all upstream contributors for the solid foundation and long-term maintenance.
---
## ✨ Highlights
| | Feature | Description |
|:---:|---|---|
| 🎬 | **Smart Library** | Folder / tree / flat views, search, grid & list layouts |
| ▶️ | **Full Playback** | Resume, autoplay, PiP, gestures, per-file track memory |
| 🔤 | **Rich Subtitles** | ASS effects, external subs, encoding & appearance tweaks |
| 🎨 | **Material You** | Dynamic color, in-app language switch, full theming |
| 💾 | **Backup & Restore** | Export / import all settings across devices |
| 🚀 | **CI/CD Ready** | Signing validation and release artifacts |
---
📖 Feature Guide
### Media Library
- Browse videos in folder mode, tree mode, or flat video mode
- Search media from the library screen
- Switch list and grid layouts
- Sort by title, duration, size, date, and related view options
- Exclude selected folders from scanning
- Optionally ignore `.nomedia` and include those directories in scanning
- Refresh and verify media behavior faster with debug-only commands
### Playback
- Play local videos directly from the library or external intents
- Continue playback from the previous position
- Autoplay the next video in the current folder
- Use Picture in Picture mode
- Keep background playback behavior configurable
- Adjust playback speed, long-press speed, zoom, and content scale
- Use seek, brightness, volume, zoom, and double-tap gestures
- Remember per-file selections like audio track and subtitle track
### Subtitle and Audio
- Select built-in audio tracks and subtitle tracks
- Load external subtitle files from the system document picker
- Render ASS subtitles with effect support
- Configure preferred audio language and subtitle language
- Change subtitle font, bold text, text size, background, delay, speed, and text encoding
- Control decoder preferences for audio and video playback behavior
### Personalization and Settings
- Switch app language inside the app
- Use Material 3 and dynamic color theming
- Configure gestures, player controls, orientation, decoder priority, and thumbnails
- Back up app settings and player settings to a file
- Restore settings from a backup file
- Reset settings when needed
### Release and Debugging
- CI produces debug artifacts for branch validation
- Release workflow validates signing secrets before signed builds
📱 User Manual
### 1. First Launch
- Install a debug or release APK
- Grant media access permission when prompted
- If you enable `.nomedia` override, also grant all-files access when Android asks for it
### 2. Browse Your Library
- Open the home screen and choose folder, tree, or video view
- Use search to find files quickly
- Open quick settings from the media screen to change sorting, layout, and view mode
- Hide folders you do not want to see from settings
### 3. Watch Videos
- Tap any video to open the player
- Swipe horizontally to seek
- Swipe vertically to control brightness or volume
- Double tap to trigger the configured skip action
- Pinch to zoom if zoom gestures are enabled
- Use PiP or background play if your settings allow it
### 4. Use Subtitles
- Open subtitle track selection inside the player for embedded tracks
- Use the subtitle picker to load an external subtitle file
- ASS subtitles support effect rendering, not only plain text display
- Fine-tune subtitle appearance and playback behavior from Settings > Subtitle
### 5. Back Up and Restore
- Open Settings > General
- Export current app and player settings to a backup file
- Import the backup later on the same or another device
- Use reset if you want a clean configuration again
### 6. Troubleshooting
- If the library looks incomplete, check folder exclusions and `.nomedia` behavior
- If playback fails, retry after granting media permissions again
- If subtitle appearance looks wrong, verify text encoding and ASS track selection
- If a signed release fails in CI, check the signing validation output first
---
## 🏗️ Project Structure
```text
app/ Application entry points, manifest, release variants
core/common/ Logging, dispatchers, common helpers
core/data/ Repository implementations and mappers
core/database/ Room database, DAO, schema
core/datastore/ DataStore sources and serializers
core/domain/ Use cases
core/media/ Media scanning and playback services
core/model/ Shared models
core/ui/ Shared Compose UI, strings, theme
feature/player/ Player UI and playback flow
feature/settings/ Settings screens and preference logic
feature/videopicker/ Media library browsing, search, quick settings
.github/workflows/ CI, version, and release workflows
```
---
🔧 Build and Validation
### Prerequisites
- Android Studio or Android SDK command-line tools
- JDK `25`
### Common Commands
```bash
./gradlew assembleDebug
./gradlew test
./gradlew ktlintCheck
./gradlew connectedAndroidTest
./gradlew ktlintCheck test assembleDebug --warning-mode=fail
```
🧑💻 Development Tutorial
### Step 1: Clone and Open
```bash
git clone https://github.com/Kindness-Kismet/One-Player.git
cd One-Player
```
Open the project in Android Studio, let Gradle sync, and confirm JDK 25 is selected.
### Step 2: Build a Debug APK
```bash
./gradlew assembleDebug
```
Install one of these outputs:
- `app/build/outputs/apk/debug/app-universal-debug.apk`
- `app/build/outputs/apk/debug/app-arm64-v8a-debug.apk`
- `app/build/outputs/apk/debug/app-x86_64-debug.apk`
### Step 3: Navigate the Codebase
Recommended reading order:
1. `README.md`
2. `app/src/main/java/one/next/player/MainActivity.kt`
3. `feature/videopicker/`
4. `feature/player/`
5. `feature/settings/`
6. `core/` modules for data, media, and shared UI
### Step 4: Add or Change a Feature
A typical flow is:
1. Add or adjust models in `core/model`
2. Update repositories or persistence in `core/data`, `core/database`, or `core/datastore`
3. Add use-case logic in `core/domain` when needed
4. Wire UI in the relevant `feature/*` module
5. Verify strings and localization in `core/ui/src/main/res`
### Step 5: Validate Before Commit
```bash
./gradlew ktlintCheck test assembleDebug --warning-mode=fail
```
If the change touches player behavior, also run the app on a device or emulator and verify actual playback.
### Step 6: Prepare a Release
1. Update `app/build.gradle.kts` with the target version
2. Push a `release/vx.y.z` branch or run the release workflow manually
3. Let CI validate signing and build artifacts
4. Review generated GitHub Release notes