Flutter Alone
A robust Flutter plugin to ensure only one instance of your desktop application runs at a time. Supports Windows and macOS.
Features
- Prevents duplicate application instances on Windows & macOS.
- Automatically focuses the original window when a duplicate is launched.
- Customizable alert messages with multi-language support.
- Flexible configuration for mutexes (Windows) and lockfiles (macOS).
- Special handling for debug mode to improve development workflow.
Platform Support
Windows | macOS | Linux |
---|---|---|
✅ | ✅ | 🚧 |
Installation
Add flutter_alone
to your pubspec.yaml
file:
dependencies:
flutter_alone: ^3.2.4
Then, run flutter pub get
.
Platform-Specific Setup
For the plugin to work correctly, some platform-specific setup is required. Please follow the detailed instructions in our Platform Setup Guide.
This guide covers:
- Windows: Resolving conflicts when using the
window_manager
package. - macOS: Handling app reactivation (e.g., clicking the dock icon). This is critical for system tray apps to ensure the window reappears correctly.
Basic Usage
Import the package in your main.dart
file and add the initialization logic before runApp
.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_alone/flutter_alone.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Platform-specific configuration
FlutterAloneConfig? config;
if (Platform.isWindows) {
config = FlutterAloneConfig.forWindows(
windowsConfig: const DefaultWindowsMutexConfig(
packageId: 'com.example.myapp',
appName: 'My App',
),
messageConfig: const EnMessageConfig(),
);
} else if (Platform.isMacOS) {
config = FlutterAloneConfig.forMacOS(
macOSConfig: const MacOSConfig(
lockFileName: 'my_app.lock',
),
messageConfig: const EnMessageConfig(),
);
}
// Check for duplicate instance
if (config != null && !await FlutterAlone.instance.checkAndRun(config: config)) {
// Exit if another instance is running
exit(0);
}
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void dispose() {
// IMPORTANT: Release resources on exit
FlutterAlone.instance.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Hello, World!'),
),
),
);
}
}
Advanced Configuration
For more detailed options, such as custom mutexes, messages, and debug settings, please see our Advanced Configuration Guide.
FAQ
Q: Why do I need different native window titles with window_manager
?
A: It prevents the Windows FindWindow()
API from failing. See the Platform Setup Guide for a full explanation.
Q: Does the user see the native window title?
A: No. The user only sees the final title set by window_manager
.
Q: What if I don't use window_manager
?
A: You can ignore the window_manager
setup guide.
Contributing
Contributions are welcome! Please feel free to submit pull requests or create issues.