Designed for simplicity and high performance, with first-class support for both Android and Windows.
| Feature | Description |
|---|---|
| β‘ High-Performance Playback | Built on the media_kit engine for smooth and reliable playback of local files and direct links. |
| π¬ Fully Custom UI | A beautiful, custom-built UI with all essential controls: Play/Pause, Seek, Speed, Mute, and Fullscreen. |
| β Persistent Favorites | Automatically save any video you play to a favorites list that persists even after closing the app. |
| π Deep Linking | Launch and control Splay from other applications, scripts, or the command line using a custom splay:// URL scheme. |
| π± Responsive Design | The layout is carefully designed to look great and feel native on both mobile phones and wide desktop screens. |
This player is optimized for high-performance direct file playback.
- β
Works Perfectly:
MP4,MKV,MOV,MPG, and other common video file formats. - β Not Supported: Adaptive streaming protocols like
HLS (.m3u8)andDASH (.mpd)have been intentionally removed to keep the app simple and focused.
You can launch Splay from any other application using the splay:// URL scheme. This allows for powerful integrations and automation.
Format: splay://play?url=ENCODED_VIDEO_URL
Important: The video URL must be URL-Encoded to work correctly with complex links containing special characters (
&,?,=, spaces, etc.). You can use an online tool like urlencoder.org.
adb shell am start -a android.intent.action.VIEW -d "splay://play?url=http%3A%2F%2Fcommondatastorage.googleapis.com%2Fgtv-videos-bucket%2Fsample%2FElephantsDream.mp4" com.spgo.playerβΆοΈ Click to see an example of how to launch Splay from another Flutter app
import 'package:url_launcher/url_launcher.dart';
void launchSplayPlayer() async {
// 1. Your original video URL
String originalUrl = "http://example.com/my video.mp4";
// 2. Encode the URL to make it safe
String encodedUrl = Uri.encodeComponent(originalUrl);
// 3. Create the Splay deep link
Uri splayLink = Uri.parse("splay://play?url=$encodedUrl");
// 4. Launch it!
// This will try to open the Splay app. If not installed, it might open a browser.
if (await canLaunchUrl(splayLink)) {
await launchUrl(splayLink, mode: LaunchMode.externalApplication);
} else {
print("Could not launch Splay. Is it installed on the device?");
}
}This repository follows a minimalist approach and only contains the lib folder and configuration files. You must generate the platform-specific folders (android, windows) yourself.
git clone <your-repository-url>
cd playerRun the flutter create command in the project's root directory. This will create the necessary android and windows folders based on your local Flutter SDK.
flutter create . --platforms=android,windowsSince the platform folders were just generated, you must manually add the required configurations for the plugins to work.
π 1. pubspec.yaml (Confirm Dependencies)
Your pubspec.yaml should look like this to include all necessary packages.
name: player
description: "A new Flutter project."
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
media_kit: ^1.1.10
media_kit_video: ^1.2.4
media_kit_libs_video: ^1.0.4
google_fonts: ^6.2.1
flutter_animate: ^4.5.0
shared_preferences: ^2.2.3
url_launcher: ^6.3.0
rxdart: ^0.27.7
app_links: ^3.4.1
cupertino_icons: ^1.0.8
dev_dependencies:
flutter_test:
sdk: flutter
rename_app: ^1.4.0
flutter_lints: ^4.0.0
msix: ^2.14.0
msix_config:
display_name: Splay
publisher_display_name: Hamza
identity_name: com.spgo.player
msix_version: 1.0.0.0
logo_path: windows/runner/resources/app_icon.ico
protocol_activation: splay
flutter:
uses-material-design: trueπ± 2. Android: android/app/src/main/AndroidManifest.xml
This configuration adds the internet permission and the splay:// URL scheme for Android.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:label="Splay">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="splay" />
<data android:host="*" />
</intent-filter>
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>π± 3. Android: android/app/src/main/kotlin/.../MainActivity.kt
The MainActivity.kt file should be left clean. The app_links package handles everything automatically.
package com.spgo.player // Make sure this matches your package name
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
// No extra code is needed here.
// The app_links package registers itself automatically.
}π» 4. Windows: windows/runner/main.cpp
This configuration is crucial for plugins like url_launcher to work on Windows.
#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>
#include "flutter_window.h"
#include "utils.h"
#include "generated_plugin_registrant.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ PWSTR cmdline, _In_ int show) {
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
CreateAndAttachConsole();
}
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
flutter::DartProject project(L"data");
std::vector<std::string> command_line_arguments =
GetCommandLineArguments();
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.Create(L"Splay", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);
RegisterGeneratedPlugins(window.GetView());
window.Show();
::MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::CoUninitialize();
return EXIT_SUCCESS;
}Now you are ready to build and run the application.
# Get all the Dart packages
flutter pub get
# Run on your connected device (Android)
flutter run
# Run on your desktop (Windows)
flutter run -d windows