557 lines
16 KiB
Markdown
557 lines
16 KiB
Markdown
# IPTV Player
|
|
|
|
A modern, feature-rich Android IPTV streaming application built with Jetpack Compose and Media3 ExoPlayer. This app allows users to stream live TV channels from M3U/M3U8 playlists with a beautiful Material Design 3 interface.
|
|
|
|
## Features
|
|
|
|
### Core Features
|
|
- **IPTV Streaming**: Stream live TV channels from M3U/M3U8 playlists
|
|
- **Channel Categories**: Automatic grouping of channels by category (Sports, News, Movies, Kids, etc.)
|
|
- **Search Functionality**: Real-time search with debouncing for quick channel discovery
|
|
- **Favorites Management**: Mark channels as favorites for quick access
|
|
- **Offline Caching**: 24-hour channel cache for offline browsing
|
|
- **Pull-to-Refresh**: Swipe down to refresh channel list
|
|
|
|
### Player Features
|
|
- **Media3 ExoPlayer**: Modern, extensible media player with HLS/DASH support
|
|
- **Fullscreen Mode**: Immersive landscape playback with gesture controls
|
|
- **Audio Focus Management**: Proper audio focus handling with ducking support
|
|
- **Multiple Audio Tracks**: Support for multi-language audio streams
|
|
- **Video Quality Selection**: Auto and manual quality selection
|
|
- **Subtitle Support**: Multi-language subtitle track selection
|
|
- **Picture-in-Picture**: Background playback support (Android O+)
|
|
|
|
### UI/UX Features
|
|
- **Material Design 3**: Modern, responsive UI with dynamic theming
|
|
- **Jetpack Compose**: Declarative UI with smooth animations
|
|
- **Responsive Grid Layout**: Adaptive channel grid (2 columns)
|
|
- **Category Filter Chips**: Horizontal scrolling category selection
|
|
- **Loading States**: Skeleton screens and progress indicators
|
|
- **Error Handling**: User-friendly error messages with retry options
|
|
|
|
### TV Support
|
|
- **Android TV Compatible**: Leanback launcher support
|
|
- **D-Pad Navigation**: Full remote control support
|
|
- **TV-Optimized UI**: Large, focusable UI elements
|
|
|
|
## Screenshots
|
|
|
|
> **Note**: Add your screenshots to the `screenshots/` directory and update the paths below.
|
|
|
|
| Channels List | Player | Categories |
|
|
|--------------|--------|------------|
|
|
|  |  |  |
|
|
|
|
| Search | Favorites | Settings |
|
|
|--------|-----------|----------|
|
|
|  |  |  |
|
|
|
|
## Prerequisites
|
|
|
|
Before building the project, ensure you have the following installed:
|
|
|
|
### Required
|
|
- **Android Studio Hedgehog (2023.1.1)** or later
|
|
- **JDK 17** or later
|
|
- **Android SDK** with the following:
|
|
- SDK Platform API 34 (Android 14)
|
|
- Build-Tools 34.0.0
|
|
- Android SDK Command-line Tools
|
|
|
|
### Optional
|
|
- **Git** for version control
|
|
- **Android Device** or **Emulator** running Android 7.0 (API 24) or higher
|
|
|
|
## Installation
|
|
|
|
### 1. Clone the Repository
|
|
|
|
```bash
|
|
git clone https://github.com/yourusername/iptv-app.git
|
|
cd iptv-app
|
|
```
|
|
|
|
### 2. Open in Android Studio
|
|
|
|
1. Launch Android Studio
|
|
2. Select "Open an existing Android Studio project"
|
|
3. Navigate to the cloned directory and click "OK"
|
|
4. Wait for Gradle sync to complete
|
|
|
|
### 3. Build the Project
|
|
|
|
```bash
|
|
# Build debug APK
|
|
./gradlew assembleDebug
|
|
|
|
# Build release APK (requires signing configuration)
|
|
./gradlew assembleRelease
|
|
```
|
|
|
|
### 4. Run on Device
|
|
|
|
```bash
|
|
# Connect your Android device or start an emulator
|
|
# Run the app
|
|
./gradlew installDebug
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Changing the M3U Playlist URL
|
|
|
|
The default M3U URL can be configured in the following locations:
|
|
|
|
#### Option 1: Build Configuration (Recommended)
|
|
|
|
Edit `app/build.gradle.kts` and add a build config field:
|
|
|
|
```kotlin
|
|
android {
|
|
defaultConfig {
|
|
buildConfigField("String", "DEFAULT_M3U_URL", "\"https://your-playlist-url.com/playlist.m3u\"")
|
|
}
|
|
}
|
|
```
|
|
|
|
Then access it in code:
|
|
```kotlin
|
|
val m3uUrl = BuildConfig.DEFAULT_M3U_URL
|
|
```
|
|
|
|
#### Option 2: Constants File
|
|
|
|
Create or edit `app/src/main/java/com/iptv/app/Constants.kt`:
|
|
|
|
```kotlin
|
|
package com.iptv.app
|
|
|
|
object Constants {
|
|
const val DEFAULT_M3U_URL = "https://your-playlist-url.com/playlist.m3u"
|
|
|
|
// Optional: Multiple playlist support
|
|
val PLAYLISTS = mapOf(
|
|
"Default" to "https://example.com/playlist1.m3u",
|
|
"Sports" to "https://example.com/sports.m3u",
|
|
"News" to "https://example.com/news.m3u"
|
|
)
|
|
}
|
|
```
|
|
|
|
#### Option 3: Settings UI (User-Configurable)
|
|
|
|
The app supports runtime playlist URL changes through the Settings screen. Users can:
|
|
1. Open Settings
|
|
2. Tap "Playlist URL"
|
|
3. Enter a new M3U/M3U8 URL
|
|
4. Tap "Save" to apply changes
|
|
|
|
### Supported Playlist Formats
|
|
|
|
The app supports standard M3U/M3U8 playlist formats:
|
|
|
|
```m3u
|
|
#EXTM3U
|
|
|
|
#EXTINF:-1 tvg-id="channel1" tvg-logo="http://logo.png" group-title="News",CNN
|
|
http://stream-url.com/cnn.m3u8
|
|
|
|
#EXTINF:-1 tvg-id="channel2" tvg-logo="http://logo.png" group-title="Sports",ESPN
|
|
http://stream-url.com/espn.m3u8
|
|
```
|
|
|
|
**Supported Attributes:**
|
|
- `tvg-id`: Channel identifier
|
|
- `tvg-logo`: Channel logo URL
|
|
- `group-title`: Category/group name
|
|
- `tvg-language`: Channel language
|
|
- `tvg-country`: Channel country
|
|
|
|
## Architecture Overview
|
|
|
|
### MVVM Architecture
|
|
|
|
The app follows the Model-View-ViewModel (MVVM) architecture pattern:
|
|
|
|
```
|
|
UI Layer (Compose Screens)
|
|
|
|
|
v
|
|
ViewModel Layer (State Management)
|
|
|
|
|
v
|
|
Repository Layer (Data Operations)
|
|
|
|
|
v
|
|
Data Layer (Models, Parsers, Network)
|
|
```
|
|
|
|
### Repository Pattern
|
|
|
|
The `ChannelRepository` acts as a single source of truth for channel data:
|
|
|
|
- **Data Fetching**: Fetches from network with Retrofit/OkHttp
|
|
- **Caching**: Local cache with 24-hour expiration
|
|
- **Favorites**: Persistent storage with SharedPreferences
|
|
- **Search**: Debounced search with Flow operators
|
|
- **Filtering**: Category-based filtering
|
|
|
|
### Media3 ExoPlayer Integration
|
|
|
|
The `PlayerManager` class provides:
|
|
|
|
- **Player Lifecycle**: Proper creation and disposal
|
|
- **Audio Focus**: System audio focus handling
|
|
- **Track Selection**: Quality and audio track switching
|
|
- **State Management**: Playback state observation
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
IPTVApp/
|
|
├── app/
|
|
│ ├── src/main/java/com/iptv/app/
|
|
│ │ ├── data/
|
|
│ │ │ ├── model/
|
|
│ │ │ │ ├── Channel.kt # Channel data class
|
|
│ │ │ │ └── Category.kt # Category data class
|
|
│ │ │ └── repository/
|
|
│ │ │ └── ChannelRepository.kt # Data repository
|
|
│ │ ├── ui/
|
|
│ │ │ ├── components/ # Reusable UI components
|
|
│ │ │ │ ├── ChannelCard.kt
|
|
│ │ │ │ ├── CategoryChip.kt
|
|
│ │ │ │ ├── VideoPlayer.kt
|
|
│ │ │ │ └── PlayerControls.kt
|
|
│ │ │ ├── screens/ # Screen composables
|
|
│ │ │ │ ├── ChannelsScreen.kt
|
|
│ │ │ │ └── PlayerScreen.kt
|
|
│ │ │ ├── theme/ # Material 3 theme
|
|
│ │ │ │ ├── Color.kt
|
|
│ │ │ │ ├── Type.kt
|
|
│ │ │ │ └── Theme.kt
|
|
│ │ │ └── viewmodel/ # ViewModels
|
|
│ │ │ ├── ChannelsViewModel.kt
|
|
│ │ │ └── PlayerViewModel.kt
|
|
│ │ └── utils/
|
|
│ │ ├── M3UParser.kt # M3U playlist parser
|
|
│ │ └── PlayerManager.kt # ExoPlayer wrapper
|
|
│ ├── src/main/res/
|
|
│ │ ├── values/
|
|
│ │ │ ├── strings.xml # App strings
|
|
│ │ │ ├── colors.xml # Color resources
|
|
│ │ │ └── themes.xml # Theme resources
|
|
│ │ └── xml/
|
|
│ │ └── network_security_config.xml
|
|
│ └── build.gradle.kts # App-level build config
|
|
├── build.gradle.kts # Project-level build config
|
|
├── settings.gradle.kts # Project settings
|
|
└── gradle.properties # Gradle properties
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
### Core Android
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `core-ktx` | 1.12.0 | Kotlin extensions |
|
|
| `lifecycle-runtime-ktx` | 2.6.2 | Lifecycle awareness |
|
|
| `activity-compose` | 1.8.1 | Compose activity |
|
|
|
|
### Jetpack Compose
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `compose-bom` | 2023.10.01 | Bill of Materials |
|
|
| `material3` | - | Material Design 3 |
|
|
| `material-icons-extended` | - | Extended icons |
|
|
| `lifecycle-viewmodel-compose` | 2.6.2 | ViewModel integration |
|
|
| `navigation-compose` | 2.7.5 | Navigation |
|
|
|
|
### Media Playback
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `media3-exoplayer` | 1.2.0 | Core player |
|
|
| `media3-exoplayer-hls` | 1.2.0 | HLS streaming |
|
|
| `media3-exoplayer-dash` | 1.2.0 | DASH streaming |
|
|
| `media3-ui` | 1.2.0 | Player UI |
|
|
| `media3-session` | 1.2.0 | Media session |
|
|
|
|
### Networking
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `retrofit` | 2.9.0 | HTTP client |
|
|
| `okhttp` | 4.12.0 | HTTP engine |
|
|
| `logging-interceptor` | 4.12.0 | Request logging |
|
|
|
|
### Image Loading
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `coil-compose` | 2.5.0 | Image loading |
|
|
|
|
### Coroutines
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `kotlinx-coroutines-android` | 1.7.3 | Async operations |
|
|
|
|
### JSON Parsing
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `gson` | 2.10.1 | JSON serialization |
|
|
|
|
### Testing
|
|
| Dependency | Version | Purpose |
|
|
|------------|---------|---------|
|
|
| `junit` | 4.13.2 | Unit testing |
|
|
| `espresso-core` | 3.5.1 | UI testing |
|
|
| `compose-ui-test-junit4` | - | Compose testing |
|
|
|
|
## Building the APK
|
|
|
|
### Debug APK
|
|
|
|
```bash
|
|
# Build debug APK
|
|
./gradlew assembleDebug
|
|
|
|
# Output location:
|
|
# app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
### Release APK
|
|
|
|
1. **Create a signing keystore** (if not exists):
|
|
|
|
```bash
|
|
keytool -genkey -v -keystore iptv-release.keystore -alias iptv -keyalg RSA -keysize 2048 -validity 10000
|
|
```
|
|
|
|
2. **Configure signing** in `app/build.gradle.kts`:
|
|
|
|
```kotlin
|
|
android {
|
|
signingConfigs {
|
|
create("release") {
|
|
storeFile = file("iptv-release.keystore")
|
|
storePassword = System.getenv("STORE_PASSWORD") ?: "your-password"
|
|
keyAlias = "iptv"
|
|
keyPassword = System.getenv("KEY_PASSWORD") ?: "your-password"
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
isMinifyEnabled = true
|
|
isShrinkResources = true
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro"
|
|
)
|
|
signingConfig = signingConfigs.getByName("release")
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
3. **Build release APK**:
|
|
|
|
```bash
|
|
# Build release APK
|
|
./gradlew assembleRelease
|
|
|
|
# Output location:
|
|
# app/build/outputs/apk/release/app-release.apk
|
|
```
|
|
|
|
### App Bundle (Google Play)
|
|
|
|
```bash
|
|
# Build AAB for Google Play
|
|
./gradlew bundleRelease
|
|
|
|
# Output location:
|
|
# app/build/outputs/bundle/release/app-release.aab
|
|
```
|
|
|
|
## Installing on Android Device
|
|
|
|
### Method 1: Android Studio
|
|
|
|
1. Connect your Android device via USB
|
|
2. Enable USB debugging in Developer Options
|
|
3. Click "Run" (green play button) in Android Studio
|
|
4. Select your device from the deployment target dialog
|
|
|
|
### Method 2: ADB (Android Debug Bridge)
|
|
|
|
```bash
|
|
# Install debug APK
|
|
adb install app/build/outputs/apk/debug/app-debug.apk
|
|
|
|
# Install release APK
|
|
adb install app/build/outputs/apk/release/app-release.apk
|
|
|
|
# Install with replacement (if already installed)
|
|
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
### Method 3: Direct Download
|
|
|
|
1. Transfer the APK file to your device
|
|
2. Open a file manager on your device
|
|
3. Navigate to the APK file location
|
|
4. Tap the APK to install
|
|
5. Allow installation from unknown sources if prompted
|
|
|
|
### Method 4: Wireless ADB
|
|
|
|
```bash
|
|
# Connect to device over WiFi
|
|
adb tcpip 5555
|
|
adb connect <device-ip-address>:5555
|
|
|
|
# Install APK
|
|
adb install app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Build Issues
|
|
|
|
#### Gradle Sync Failed
|
|
```
|
|
Solution: File -> Invalidate Caches / Restart -> Invalidate and Restart
|
|
```
|
|
|
|
#### Out of Memory Error
|
|
Add to `gradle.properties`:
|
|
```properties
|
|
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m
|
|
org.gradle.parallel=true
|
|
org.gradle.caching=true
|
|
```
|
|
|
|
#### Kotlin Version Mismatch
|
|
Ensure Kotlin version matches in `build.gradle.kts`:
|
|
```kotlin
|
|
plugins {
|
|
id("org.jetbrains.kotlin.android") version "1.9.20"
|
|
}
|
|
```
|
|
|
|
### Runtime Issues
|
|
|
|
#### App Crashes on Launch
|
|
- Check that `INTERNET` permission is in `AndroidManifest.xml`
|
|
- Verify minimum SDK version (API 24+)
|
|
- Check for ProGuard obfuscation issues
|
|
|
|
#### Channels Not Loading
|
|
- Verify the M3U URL is accessible
|
|
- Check network connectivity
|
|
- Review logcat for parsing errors: `adb logcat | grep M3UParser`
|
|
|
|
#### Video Not Playing
|
|
- Ensure stream URL is valid and accessible
|
|
- Check if stream format is supported (HLS, DASH, Progressive)
|
|
- Verify codec support on device
|
|
- Check logcat for ExoPlayer errors
|
|
|
|
#### Audio Issues
|
|
- Check audio focus is being requested properly
|
|
- Verify audio track selection in PlayerManager
|
|
- Test with different audio formats
|
|
|
|
### Streaming Issues
|
|
|
|
#### Buffering Problems
|
|
```kotlin
|
|
// Increase buffer size in PlayerManager
|
|
val player = ExoPlayer.Builder(context)
|
|
.setLoadControl(
|
|
DefaultLoadControl.Builder()
|
|
.setBufferDurationsMs(
|
|
5000, // minBufferMs
|
|
50000, // maxBufferMs
|
|
1000, // bufferForPlaybackMs
|
|
5000 // bufferForPlaybackAfterRebufferMs
|
|
)
|
|
.build()
|
|
)
|
|
.build()
|
|
```
|
|
|
|
#### SSL/Certificate Errors
|
|
Update `network_security_config.xml`:
|
|
```xml
|
|
<network-security-config>
|
|
<base-config cleartextTrafficPermitted="true">
|
|
<trust-anchors>
|
|
<certificates src="system"/>
|
|
</trust-anchors>
|
|
</base-config>
|
|
</network-security-config>
|
|
```
|
|
|
|
### Development Tips
|
|
|
|
#### Enable Debug Logging
|
|
```kotlin
|
|
// In PlayerManager
|
|
exoPlayer.addAnalyticsListener(EventLogger())
|
|
```
|
|
|
|
#### View Compose Layout Bounds
|
|
Enable in Developer Options:
|
|
```
|
|
Settings -> Developer Options -> Show layout bounds
|
|
```
|
|
|
|
#### Profile Performance
|
|
Use Android Studio Profiler:
|
|
```
|
|
View -> Tool Windows -> Profiler
|
|
```
|
|
|
|
## License
|
|
|
|
```
|
|
Copyright 2024 IPTV Player
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
```
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please follow these steps:
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
5. Open a Pull Request
|
|
|
|
## Acknowledgments
|
|
|
|
- [ExoPlayer](https://github.com/google/ExoPlayer) - Media player library
|
|
- [Jetpack Compose](https://developer.android.com/jetpack/compose) - UI toolkit
|
|
- [Material Design 3](https://m3.material.io/) - Design system
|
|
- [IPTV Org](https://github.com/iptv-org) - Public IPTV playlists
|
|
|
|
## Support
|
|
|
|
For issues, questions, or feature requests, please open an issue on GitHub.
|
|
|
|
---
|
|
|
|
**Disclaimer**: This application is for educational purposes. Users are responsible for complying with local laws and regulations regarding IPTV streaming. The developers do not provide any IPTV content or playlists.
|