Flutter系统弹窗管理插件system_alert_window的使用
Flutter系统弹窗管理插件system_alert_window的使用
插件简介
system_alert_window
是一个Flutter插件,用于显示类似Truecaller的覆盖窗口,可以覆盖在所有其他应用程序之上,并带有回调事件。对于Android Go或Android 11及以上版本,此插件会显示通知气泡;而在其他Android版本中,则会显示覆盖窗口。
Android平台配置
权限声明
为了正常使用system_alert_window
,需要在AndroidManifest.xml
文件中添加如下权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
版本适配说明
- Android 10及以下, Android GO (API 27):使用’draw on top’权限并作为覆盖窗口显示。
- Android 11及以上:根据
SystemWindowPrefMode
的不同设置,可能会以气泡形式展示或者直接覆盖其他应用。 - Android GO (API 29):用户需手动从开发者选项启用气泡功能。
iOS平台支持
目前iOS端仅能作为通知中心的通知显示,该部分功能尚需社区贡献代码完善。
使用示例
下面是一个完整的示例程序,演示了如何请求权限、创建和控制覆盖窗口以及与之交互。
示例代码
main.dart
import 'dart:async';
import 'dart:developer';
import 'dart:isolate';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:share_plus/share_plus.dart';
import 'package:system_alert_window/system_alert_window.dart';
import 'custom_overlay.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
@pragma("vm:entry-point")
void overlayMain() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: CustomOverlay(),
),
);
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
bool _isShowingWindow = false;
bool _isUpdatedWindow = false;
SystemWindowPrefMode prefMode = SystemWindowPrefMode.OVERLAY;
static const String _mainAppPort = 'MainApp';
final _receivePort = ReceivePort();
SendPort? homePort;
String? latestMessageFromOverlay;
@override
void initState() {
super.initState();
_initPlatformState();
_requestPermissions();
if (homePort != null) return;
final res = IsolateNameServer.registerPortWithName(
_receivePort.sendPort,
_mainAppPort,
);
log("$res: OVERLAY");
_receivePort.listen((message) {
log("message from OVERLAY: $message");
});
}
@override
void dispose() {
super.dispose();
}
Future<void> _initPlatformState() async {
await SystemAlertWindow.enableLogs(true);
String? platformVersion;
try {
platformVersion = await SystemAlertWindow.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
if (!mounted) return;
if (platformVersion != null)
setState(() {
_platformVersion = platformVersion!;
});
}
Future<void> _requestPermissions() async {
await SystemAlertWindow.requestPermissions(prefMode: prefMode);
}
void _showOverlayWindow() async {
if (!_isShowingWindow) {
await SystemAlertWindow.sendMessageToOverlay('show system window');
SystemAlertWindow.showSystemWindow(
height: 200,
width: MediaQuery.of(context).size.width.floor(),
gravity: SystemWindowGravity.CENTER,
prefMode: prefMode,
isFlagFocusable: false);
setState(() {
_isShowingWindow = true;
});
} else if (!_isUpdatedWindow) {
await SystemAlertWindow.sendMessageToOverlay('update system window');
SystemAlertWindow.updateSystemWindow(
height: 200,
width: MediaQuery.of(context).size.width.floor(),
gravity: SystemWindowGravity.CENTER,
prefMode: prefMode,
isFlagFocusable: true,
isDisableClicks: true);
setState(() {
_isUpdatedWindow = true;
SystemAlertWindow.sendMessageToOverlay(_isUpdatedWindow.toString());
});
} else {
setState(() {
_isShowingWindow = false;
_isUpdatedWindow = false;
SystemAlertWindow.sendMessageToOverlay(_isUpdatedWindow.toString());
});
SystemAlertWindow.closeSystemWindow(prefMode: prefMode);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('System Alert Window Example App \n with flutterview'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_platformVersion\n'),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: MaterialButton(
onPressed: _showOverlayWindow,
textColor: Colors.white,
child: !_isShowingWindow
? Text("Show system alert window")
: !_isUpdatedWindow
? Text("Update system alert window")
: Text("Close system alert window"),
color: Colors.deepOrange,
padding: const EdgeInsets.symmetric(vertical: 8.0),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: MaterialButton(
onPressed: () => SystemAlertWindow.sendMessageToOverlay("message from main"),
textColor: Colors.white,
child: Text("send message to overlay"),
color: Colors.deepOrange,
padding: const EdgeInsets.symmetric(vertical: 8.0),
),
),
TextButton(
onPressed: () async {
String? logFilePath = await SystemAlertWindow.getLogFile;
if (logFilePath != null && logFilePath.isNotEmpty) {
Share.shareFiles([logFilePath]);
} else {
print("Path is empty");
}
},
child: Text("Share Log file"))
],
),
),
),
);
}
}
custom_overlay.dart
import 'package:flutter/material.dart';
import 'package:system_alert_window/system_alert_window.dart';
class CustomOverlay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.transparent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("This is a custom overlay"),
ElevatedButton(
onPressed: () {
SystemAlertWindow.sendMessageToOverlay("Button clicked in overlay");
},
child: Text("Click me"),
),
],
),
);
}
}
以上代码展示了如何使用system_alert_window
插件来实现跨应用的覆盖窗口显示,并且包含了基本的操作如显示、更新、关闭窗口以及发送消息给覆盖窗口等功能。希望这对您有所帮助!
更多关于Flutter系统弹窗管理插件system_alert_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter系统弹窗管理插件system_alert_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用system_alert_window
插件来管理系统弹窗的一个示例代码案例。这个插件允许你在Android设备上显示一个悬浮在系统其他应用之上的窗口。请注意,由于这个特性涉及到系统级权限,因此在实现时需要考虑权限请求和处理。
首先,确保在你的pubspec.yaml
文件中添加system_alert_window
依赖:
dependencies:
flutter:
sdk: flutter
system_alert_window: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来是具体的实现步骤:
-
请求权限:在Android上,显示系统弹窗需要
SYSTEM_ALERT_WINDOW
权限。这个权限在Android 6.0(API级别23)及以上版本需要用户手动授予。 -
创建和显示弹窗:使用
system_alert_window
插件来创建并显示弹窗。
以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:system_alert_window/system_alert_window.dart';
import 'dart:ui' as ui;
import 'package:permission_handler/permission_handler.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('System Alert Window Example'),
),
body: Center(
child: ElevatedButton(
onPressed: _showSystemAlert,
child: Text('Show System Alert'),
),
),
),
);
}
Future<void> _showSystemAlert() async {
if (Platform.isAndroid) {
// 请求 SYSTEM_ALERT_WINDOW 权限
var status = await Permission.systemAlertWindow.status;
if (!status.isGranted) {
var result = await Permission.systemAlertWindow.request();
if (!result.isGranted) {
return; // 用户拒绝了权限请求
}
}
// 创建 SystemAlertWindowController
final window = SystemAlertWindowController(
// 设置窗口大小(这里设置为全屏,你可以根据需要调整)
size: MediaQuery.of(context).size,
// 设置窗口的背景颜色
backgroundColor: Colors.transparent,
// 窗口的标题栏(可选)
title: 'System Alert',
// 窗口内容
child: Container(
color: Colors.black54.withOpacity(0.7),
alignment: Alignment.center,
child: Text(
'This is a system alert window!',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
// 点击窗口外部时是否关闭窗口
shouldDismissOnTapOutside: true,
);
// 显示窗口
await window.show();
// 这里可以添加一些逻辑来处理窗口的关闭,比如用户点击了某个按钮
// window.close();
} else {
// 目前只支持Android
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('System alert windows are only supported on Android.')),
);
}
}
}
注意事项:
- 在实际项目中,请确保处理所有可能的权限请求结果,包括用户拒绝的情况。
- 上面的代码示例中使用了
permission_handler
插件来处理权限请求。你需要在pubspec.yaml
中添加这个依赖,并运行flutter pub get
来安装它。 - 由于
SYSTEM_ALERT_WINDOW
权限的敏感性,一些设备或Android版本可能会限制或阻止这个权限的授予,特别是在没有用户明确指示的情况下自动请求。
希望这个示例能帮助你理解如何在Flutter中使用system_alert_window
插件来管理系统弹窗。如果有进一步的问题,欢迎继续提问!