# 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 | |--------------|--------|------------| | ![Channels](screenshots/channels.png) | ![Player](screenshots/player.png) | ![Categories](screenshots/categories.png) | | Search | Favorites | Settings | |--------|-----------|----------| | ![Search](screenshots/search.png) | ![Favorites](screenshots/favorites.png) | ![Settings](screenshots/settings.png) | ## 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 :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 ``` ### 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.