Flutter在MacOS上如何获取已安装软件列表

在Flutter开发MacOS应用时,如何获取当前系统已安装的软件列表?需要调用什么原生API或第三方库来实现这个功能?能否提供具体的代码示例?需要注意哪些权限或沙盒限制?

2 回复

Flutter无法直接获取MacOS已安装软件列表。可通过process_run包调用系统命令实现:

import 'package:process_run/process_run.dart';

void getInstalledApps() async {
  var result = await run('ls', ['/Applications']);
  print(result.stdout);
}

此方法仅显示/Applications目录下的应用。

更多关于Flutter在MacOS上如何获取已安装软件列表的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中获取 macOS 上已安装软件列表需要结合平台通道(Platform Channels)调用原生 macOS API。由于 Flutter 本身不提供直接访问系统应用列表的方法,你需要编写 Swift 代码来获取信息并通过通道传递给 Flutter。

以下是实现步骤和示例代码:

1. 创建 Flutter 平台通道

在 Flutter 端设置方法通道:

import 'package:flutter/services.dart';

class MacAppList {
  static const MethodChannel _channel = MethodChannel('mac_app_list');

  static Future<List<String>> getInstalledApps() async {
    try {
      final List<dynamic> apps = await _channel.invokeMethod('getInstalledApps');
      return apps.cast<String>();
    } on PlatformException catch (e) {
      print("Failed to get apps: '${e.message}'.");
      return [];
    }
  }
}

2. 实现 macOS 原生代码

在 Xcode 中打开 macOS Runner,编辑 MainFlutterWindow.swift

import Cocoa
import FlutterMacOS

class MainFlutterWindow: NSWindow {
  override func awakeFromNib() {
    let controller = FlutterViewController()
    let channel = FlutterMethodChannel(
      name: "mac_app_list",
      binaryMessenger: controller.engine.binaryMessenger
    )
    
    channel.setMethodCallHandler { call, result in
      if call.method == "getInstalledApps" {
        self.getInstalledApps(result: result)
      } else {
        result(FlutterMethodNotImplemented)
      }
    }
    
    super.awakeFromNib()
  }
  
  private func getInstalledApps(result: FlutterResult) {
    let fileManager = FileManager.default
    let applicationURLs = fileManager.urls(
      for: .applicationDirectory,
      in: .localDomainMask
    )
    
    var appNames: [String] = []
    for url in applicationURLs {
      do {
        let appURLs = try fileManager.contentsOfDirectory(
          at: url,
          includingPropertiesForKeys: nil
        )
        for appURL in appURLs {
          if appURL.pathExtension == "app" {
            appNames.append(appURL.deletingPathExtension().lastPathComponent)
          }
        }
      } catch {
        result(FlutterError(code: "ERROR", message: error.localizedDescription, details: nil))
        return
      }
    }
    result(appNames)
  }
}

3. 使用示例

在 Flutter 中调用:

void main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder<List<String>>(
          future: MacAppList.getInstalledApps(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data!.length,
                itemBuilder: (context, index) {
                  return ListTile(title: Text(snapshot.data![index]));
                },
              );
            } else {
              return CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }
}

注意事项:

  1. 权限限制:此方法只能获取 /Applications 目录下的应用,沙箱应用或用户目录下的应用可能无法检测到
  2. 应用名称:返回的是应用包名(不含 .app 扩展名)
  3. 性能考虑:首次扫描可能需要一些时间,建议在后台执行

如果需要更完整的应用信息(如版本号、安装路径等),需要扩展 Swift 代码来读取应用的 Info.plist 文件。

回到顶部