A real-time image sharing system that allows Flutter mobile apps to send images to Android TV using MQTT protocol. Perfect for displaying photos, presentations, or any visual content from your phone to your TV screen instantly.
- ** Flutter Mobile App**: Capture, select, or upload images and send them to Android TV
- ** Android TV App**: Receives and displays images in real-time on your TV screen
- ** MQTT Communication**: Uses lightweight MQTT protocol for real-time messaging
- ** Pairing System**: Secure device pairing between mobile and TV
- ** Image Management**: Handles multiple images with indexing and control
graph LR
A[ Flutter App] -->|MQTT| B[ MQTT Broker]
B -->|MQTT| C[ Android TV]
A -->|1. Pair Request| B
B -->|1. Pair Request| C
C -->|2. Pair Response| B
B -->|2. Pair Response| A
A -->|3. Image URLs| B
B -->|3. Image URLs| C
C -->|4. Download & Display| C
- Pairing: Mobile app sends pair request to TV
- Authentication: TV responds with confirmation
- Image Transfer: Mobile sends image URLs via MQTT
- Display: TV downloads and displays images
- Control: Mobile can control which image to show
tv-image-receiver/
├── flutter_app/ # Flutter mobile application
│ ├── lib/
│ ├── android/
│ ├── ios/
│ └── pubspec.yaml
├── android_tv/ # Android TV application
│ ├── app/
│ ├── build.gradle
│ └── settings.gradle
├── .env.example # Environment variables template
└── README.md
Before starting, ensure you have the following installed on your development machine:
- Flutter SDK (3.0.0 or higher) - Install Flutter
- Android Studio (or VS Code with Flutter extension)
- Android SDK (API level 21 or higher)
- Java Development Kit (JDK 8 or higher)
- Git - Install Git
- Android TV device or Android TV Emulator
# Clone the project repository
git clone https://github.com/yourusername/tv-image-receiver.git
# Navigate to project directory
cd tv-image-receiver
# Check project structure
ls -lacd flutter_app# Get all required packages
flutter pub get
# Verify Flutter installation
flutter doctor
# Check connected devices
flutter devicesCreate the required configuration files (templates provided in Configuration section):
# Create .env file (copy from template below)
touch .env
# Create Firebase options (copy from template below)
mkdir -p lib
touch lib/firebase_options.dart# Run in debug mode on connected device
flutter run
# Or run in release mode
flutter run --release
# Or build APK for distribution
flutter build apk --release
# Install APK on specific device
flutter install# Build Android APK
flutter build apk --split-per-abi
# Build Android App Bundle (for Play Store)
flutter build appbundle
# Build for iOS (macOS only)
flutter build ios# Go back to root and enter Android TV project
cd ../android_tv# Check Gradle wrapper permissions
chmod +x gradlew
# Clean and build project
./gradlew clean
./gradlew build
# List available build variants
./gradlew tasksOption A: Physical Android TV Device
# Enable ADB debugging on TV (Settings > Device Preferences > About > Build 7 times)
# Enable Developer options > USB/Network debugging
# Connect via USB or find TV IP
adb connect YOUR_TV_IP:5555
# Verify connection
adb devicesOption B: Android TV Emulator
# Create Android TV emulator in Android Studio
# Tools > AVD Manager > Create Virtual Device > TV category
# Or use command line:
avdmanager create avd -n AndroidTV -k "system-images;android-30;google_apis;x86"
emulator -avd AndroidTV# Install debug version directly to connected TV
./gradlew installDebug
# Or build release APK
./gradlew assembleRelease
# Install specific APK file
adb install app/build/outputs/apk/debug/app-debug.apk# Open Android Studio
studio .
# Or on macOS
open -a "Android Studio" .- Open Project: File → Open → Select
android_tvfolder - Sync Project: Click "Sync Now" when prompted
- Connect Device: Ensure Android TV is connected via ADB
- Run App: Click green "Run" button or press Shift+F10
- Select Target: Choose your Android TV device from dropdown
Both apps need to use the same MQTT configuration. Update the settings in:
Flutter App: .env file
Android TV: MainActivity.kt topic variables
# Verify topics match between both apps
grep -r "pair_topic\|pairTopic" .# Start Android TV app first
adb shell am start -n com.example.tvimagereceiver/.MainActivity
# Then start Flutter app
cd ../flutter_app
flutter run# Check if Android TV app is running
adb shell dumpsys activity activities | grep tvimagereceiver
# Check Flutter app logs
flutter logs- Launch Android TV app → Should show "MQTT Connection Active"
- Launch Flutter app → Should show connection status
- Tap "Pair with TV" in Flutter app
- Check Android TV → Should show "Pair request received"
- Send test image → Should appear on TV screen
# Check ADB connection
adb devices
# Monitor Android TV logs
adb logcat | grep MQTT
# Monitor Flutter logs
flutter logs --verbose
# Check network connectivity
ping broker.hivemq.comcd flutter_app
# Build optimized APK
flutter build apk --release --split-per-abi
# Build App Bundle for Play Store
flutter build appbundle --release
# Generated files location:
# build/app/outputs/flutter-apk/app-release.apk
# build/app/outputs/bundle/release/app-release.aabcd android_tv
# Build release APK
./gradlew assembleRelease
# Sign APK (optional, for distribution)
./gradlew bundleRelease
# Generated files location:
# app/build/outputs/apk/release/app-release.apk# Install Flutter app on multiple phones
adb devices
adb -s DEVICE_ID install build/app/outputs/flutter-apk/app-release.apk
# Install TV app on multiple Android TVs
adb connect TV_IP:5555
adb install android_tv/app/build/outputs/apk/release/app-release.apk- Google Play Store (for mobile app)
- Android TV Play Store (for TV app)
- APK Direct Distribution (enterprise/testing)
- Firebase App Distribution (beta testing)
Create a .env file in the flutter_app/ directory:
# MQTT Broker Configuration
MQTT_BROKER=your-mqtt-broker.com
MQTT_HOST=your-mqtt-broker.com
MQTT_PORT=1883
# Topic Configuration
MQTT_TOPIC_PREFIX=tv/
TV_SERIAL=androidtv_001
# Authentication (optional)
MQTT_USERNAME=
MQTT_PASSWORD=
# Image Upload API
IMAGE_UPLOAD_API_URL=https://your-api.com/upload
IMAGE_UPLOAD_API_KEY=your-api-key-here
# Firebase Configuration
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_API_KEY=your-api-keyCreate flutter_app/lib/firebase_options.dart:
// File generated by FlutterFire CLI.
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'your-web-api-key',
appId: 'your-web-app-id',
messagingSenderId: 'your-sender-id',
projectId: 'your-project-id',
authDomain: 'your-project.firebaseapp.com',
storageBucket: 'your-project.appspot.com',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'your-android-api-key',
appId: 'your-android-app-id',
messagingSenderId: 'your-sender-id',
projectId: 'your-project-id',
storageBucket: 'your-project.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'your-ios-api-key',
appId: 'your-ios-app-id',
messagingSenderId: 'your-sender-id',
projectId: 'your-project-id',
storageBucket: 'your-project.appspot.com',
iosClientId: 'your-ios-client-id',
iosBundleId: 'com.yourcompany.yourapp',
);
}** Note**: To generate this file automatically, use FlutterFire CLI:
dart pub global activate flutterfire_cli flutterfire configure
The application uses the following MQTT topic structure:
{MQTT_TOPIC_PREFIX}{TV_SERIAL}/
├── pair # Pairing requests
├── pair_response # Pairing confirmations
├── images # Image URL lists
└── image # Image display control
Example Topics:
tv/androidtv_001/pairtv/androidtv_001/pair_responsetv/androidtv_001/imagestv/androidtv_001/image
- Launch the Flutter app on your phone
- Connect to MQTT broker automatically
- Pair with Android TV by tapping "Pair with TV"
- Select/Capture images to send
- Send images to TV
- Control image display remotely
- Install and launch the TV app
- Wait for pairing request from mobile
- Confirm pairing when prompted
- View images as they arrive
- Navigate through images via mobile control
- Image capture and selection
- Cloud image upload
- Real-time MQTT communication
- Responsive mobile UI
- Device pairing system
- TV-optimized interface
- Full-screen image display
- Automatic image downloading
- Local image caching
- Remote control support
MQTT Connection Failed
- Verify broker URL and port in
.env - Check network connectivity
- Ensure firewall allows MQTT traffic
Pairing Not Working
- Confirm both devices use same topic structure
- Check MQTT broker logs
- Verify TV_SERIAL matches in both apps
Images Not Displaying
- Ensure image URLs are accessible
- Check Android TV internet connection
- Verify storage permissions
Firebase Errors
- Run
flutterfire configureto regenerate config - Check Firebase project settings
- Verify API keys and project ID
- Flutter 3.0.0+
- Dart 2.17.0+
- Android 6.0+ / iOS 12.0+
- Android API 21+ (Android 5.0)
- Android TV / Google TV
- Network connectivity
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- MQTT.org for the messaging protocol
- HiveMQ for free MQTT broker
- Flutter Team for the amazing framework
- Firebase for backend services
Made with for seamless mobile-to-TV communication