Flutter Windows应用:用户无活动20秒后关闭第三方程序并返回播放器
解决方案
1. 记录并控制Chrome进程
Flutter本身无法直接访问外部进程,但可以通过以下两种方式获取Chrome的进程ID(PID)并操作它:
- 启动时记录PID:如果是通过Flutter主动启动Chrome,用
dart:io的Process.start可以直接拿到PID,后续用这个PID终止进程:import 'dart:io'; int? chromePid; Future<void> launchChrome() async { final process = await Process.start('chrome.exe', ['https://your-target-url.com']); chromePid = process.pid; } - 枚举进程获取PID:如果是通过
url_launcher等方式打开Chrome,需要用Windows API枚举系统进程,根据进程名(chrome.exe)或窗口标题匹配目标进程。可以借助win32包调用Windows原生API:import 'package:win32/win32.dart'; int? findChromePid() { final snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot == INVALID_HANDLE_VALUE) return null; final processEntry = PROCESSENTRY32.allocate(); processEntry.dwSize = sizeOf<PROCESSENTRY32>(); if (!Process32First(snapshot, processEntry.addressOf)) { CloseHandle(snapshot); return null; } do { final processName = processEntry.szExeFile.toDartString(); if (processName.toLowerCase() == 'chrome.exe') { final pid = processEntry.th32ProcessID; CloseHandle(snapshot); processEntry.free(); return pid; } } while (Process32Next(snapshot, processEntry.addressOf)); CloseHandle(snapshot); processEntry.free(); return null; }
拿到PID后,调用Windows API的TerminateProcess关闭Chrome:
void terminateChrome(int pid) { final processHandle = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (processHandle != NULL) { TerminateProcess(processHandle, 0); CloseHandle(processHandle); } }
2. 监听系统级用户无活动状态
Flutter没有内置全局用户活动监听,需要调用Windows API的GetLastInputInfo获取系统无活动时长:
import 'package:win32/win32.dart'; int getInactiveSeconds() { final lastInputInfo = LASTINPUTINFO.allocate(); lastInputInfo.cbSize = sizeOf<LASTINPUTINFO>(); GetLastInputInfo(lastInputInfo.addressOf); final inactiveMillis = GetTickCount() - lastInputInfo.dwTime; lastInputInfo.free(); return (inactiveMillis / 1000).floor(); }
然后启动一个定时任务,每隔1秒检查一次无活动时长,达到20秒时执行关闭和切换操作:
import 'dart:async'; Timer? inactivityTimer; void startInactivityMonitor() { inactivityTimer?.cancel(); inactivityTimer = Timer.periodic(const Duration(seconds: 1), (timer) { if (getInactiveSeconds() >= 20) { if (chromePid != null) { terminateChrome(chromePid!); } bringMediaPlayerToFront(); timer.cancel(); } }); }
3. 切换回后台的媒体播放器
同样通过Windows API找到媒体播放器的窗口句柄,调用SetForegroundWindow将其带到前台:
void bringMediaPlayerToFront() { // 替换为你的媒体播放器窗口标题或类名 final mediaPlayerHwnd = FindWindow(NULL, TEXT('My Media Player')); if (mediaPlayerHwnd != NULL) { // 确保窗口不是最小化状态 ShowWindow(mediaPlayerHwnd, SW_RESTORE); SetForegroundWindow(mediaPlayerHwnd); } }
注意事项
- 依赖
win32包:需要在pubspec.yaml中添加win32: ^5.0.0(或最新版本) - 权限问题:
OpenProcess需要足够的权限,确保你的应用以合适的权限运行 - Chrome多进程:Chrome会启动多个子进程,若需要完全关闭所有Chrome实例,需要枚举所有
chrome.exe进程并逐一终止
内容的提问来源于stack exchange,提问作者KlaoBurn
相关产品推荐
相关产品推荐

