Flutter单实例控制插件flutter_single_instance的使用
Flutter Single Instance
A simple way to check if your application is already running.
Platform | Support |
---|---|
Android | ⚠️ |
iOS | ⚠️ |
Web | ⚠️ |
macOS | ✅ |
Windows | ✅ |
Linux | ✅ |
✅ - Confirmed working.
⚠️ - Always reports as first instance.
Installation
Add flutter_single_instance
as a dependency in your pubspec.yaml
file.
flutter pub add flutter_single_instance
macOS
Disable sandboxing and enable networking in macos/Runner/DebugProfile.entitlements
and macos/Runner/Release.entitlements
files.
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
com.apple.security.app-sandbox
: Set to false to allow access to the filesystem.com.apple.security.network.server
: Set to true to allow the app to act as a server and listen for incoming focus requests.com.apple.security.network.client
: Set to true to allow the app to act as a client and send focus requests to the server (i.e., the main instance).
Usage
A simple usage example:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_single_instance/flutter_single_instance.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await windowManager.ensureInitialized();
if (await FlutterSingleInstance().isFirstInstance()) {
runApp(const MyApp());
} else {
print("App is already running");
final err = await FlutterSingleInstance().focus();
if (err != null) {
print("Error focusing running instance: $err");
}
exit(0);
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Web and Other Unsupported Platforms
You can safely use this package in web and other unsupported platforms. It will always return true
for the isFirstInstance
method.
Limitations
- Currently, this package does not provide a way to bring the existing instance to the front. If you have any ideas on how to achieve this, please open an issue or a pull request. (This limitation has been resolved in version 1.2.0.)
Example
For a complete example, you can refer to the example/lib/main.dart file in the repository.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_single_instance/flutter_single_instance.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await windowManager.ensureInitialized();
if (await FlutterSingleInstance().isFirstInstance()) {
runApp(const MyApp());
} else {
print("App is already running");
final err = await FlutterSingleInstance().focus();
if (err != null) {
print("Error focusing running instance: $err");
}
exit(0);
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
This example demonstrates how to use the flutter_single_instance
package to ensure that only one instance of your Flutter application runs at a time. If another instance is detected, it will attempt to bring the existing instance to the front and then exit.
更多关于Flutter单实例控制插件flutter_single_instance的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter单实例控制插件flutter_single_instance的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,flutter_single_instance
插件用于确保应用在同一设备上只能有一个实例运行。这对于避免数据冲突和用户体验问题非常有用。以下是如何在Flutter项目中使用 flutter_single_instance
插件的一个示例代码案例。
步骤 1: 添加依赖
首先,在你的 pubspec.yaml
文件中添加 flutter_single_instance
依赖:
dependencies:
flutter:
sdk: flutter
flutter_single_instance: ^x.y.z # 替换为最新版本号
然后运行 flutter pub get
来获取依赖。
步骤 2: 导入并使用插件
在你的主文件(通常是 main.dart
)中,导入并使用 flutter_single_instance
插件。以下是一个完整的示例:
import 'package:flutter/material.dart';
import 'package:flutter_single_instance/flutter_single_instance.dart';
void main() async {
// 检查是否为单实例
bool isSingleInstance = await FlutterSingleInstance.checkSingleInstance();
if (isSingleInstance) {
runApp(MyApp());
} else {
// 如果不是单实例,可以选择退出应用或显示提示
exit(0);
// 或者显示一个提示对话框(这里为了简单直接退出)
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Single Instance Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You are running the single instance of this app.',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
解释
-
检查单实例:在
main
函数中,使用FlutterSingleInstance.checkSingleInstance()
方法来检查当前应用是否为单实例运行。这个方法是异步的,因此需要使用await
关键字。 -
运行应用或退出:如果应用是单实例,则继续运行
MyApp
。如果不是单实例,则可以选择退出应用(这里使用了exit(0)
)。你也可以选择显示一个对话框给用户提示。
注意事项
- 在某些平台上(特别是Android),你可能需要在
AndroidManifest.xml
中添加一些配置来确保单实例行为,但flutter_single_instance
插件通常已经处理了这些平台特定的细节。 - 确保在每次应用启动时都进行单实例检查,以避免潜在的并发实例问题。
通过上述代码示例,你可以在Flutter应用中有效地实现单实例控制。