Flutter macOS安全书签管理插件macos_secure_bookmarks的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter macOS安全书签管理插件macos_secure_bookmarks的使用

macos_secure_bookmarks

Pub

macos_secure_bookmarks 是一个Flutter插件,用于创建安全书签以保持沙盒应用程序对文件的访问。

使用方法

安全书签简介

请参考苹果官方文档中关于 安全范围书签 的说明。

确保已启用必要的权限:

  • com.apple.security.files.bookmarks.app-scope

创建安全范围书签

// 首先让用户选择一个文件,例如使用文件选择器插件。
showOpenPanel((result, files) {
  if (result != FileChooserResult.ok || files.isEmpty) {
    return;
  }
  
  // 现在创建一个安全范围书签
  final secureBookmarks = SecureBookmarks();
  final bookmark = await secureBookmarks.bookmark(File(_file));
  
  // 现在将书签存储在某个地方以便以后调用
});

解析和访问书签

// 从之前保存的 'bookmark' 字符串解析书签
final resolvedFile = await _secureBookmarks.resolveBookmark(_bookmark);
// resolvedFile 现在是一个文件对象,但在访问它之前,请调用:
await startAccessingSecurityScopedResource(resolvedFile);

// 现在可以读取/写入文件

// 并在稍后放弃访问。
await stopAccessingSecurityScopedResource(resolvedFile);

示例代码

下面是一个完整的示例demo,展示了如何使用macos_secure_bookmarks 插件:

import 'dart:io';
import 'package:file_selector/file_selector.dart';
import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride;
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:logging_appenders/logging_appenders.dart';
import 'package:macos_secure_bookmarks/macos_secure_bookmarks.dart';

final MemoryAppender logMessages = MemoryAppender();
final _logger = Logger('main');

void main() {
  Logger.root.level = Level.ALL;
  PrintAppender().attachToLogger(Logger.root);
  logMessages.attachToLogger(Logger.root);
  _logger.fine('Application launched.');

  // 设置目标平台覆盖
  debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;

  FlutterError.onError = (errorDetails) {
    _logger.shout(
        'Unhandled Flutter framework (${errorDetails.library}) error.',
        errorDetails.exception,
        errorDetails.stack);
    _logger.fine(errorDetails.summary.toString());
  };

  runApp(ExampleApp());
}

class ExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        fontFamily: 'Roboto',
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static final SecureBookmarks _secureBookmarks = SecureBookmarks();
  String _file;
  String _bookmark;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              children: [
                ElevatedButton(
                  child: Text('Select File'),
                  onPressed: () async {
                    _logger.fine('showOpenPanel..');
                    final result = await openFile();
                    _logger.fine('got result: $result');
                    if (result == null || result.path.isEmpty) {
                      return;
                    }
                    setState(() {
                      _file = result.path;
                    });
                    _logger.info('Selected file: $_file');
                  },
                ),
                ElevatedButton(
                  child: Text('Bookmark'),
                  onPressed: () async {
                    final bookmark =
                        await _secureBookmarks.bookmark(File(_file));
                    setState(() {
                      _bookmark = bookmark;
                    });
                    _logger.info('Got bookmark: $bookmark');
                  },
                ),
                ElevatedButton(
                  child: Text('Resolve Bookmark'),
                  onPressed: () async {
                    final resolved =
                        await _secureBookmarks.resolveBookmark(_bookmark);
                    _logger.info('Resolved to $resolved');
                  },
                ),
              ],
            ),
            Expanded(
              child: Container(
                color: Colors.white,
                constraints: BoxConstraints.expand(),
                child: SingleChildScrollView(
                  child: Container(
                    padding: const EdgeInsets.all(16),
                    child: AnimatedBuilder(
                      animation: logMessages.log,
                      builder: (context, _) => Text(
                        logMessages.log.toString(),
                      ),
                    ),
                  ),
                  reverse: true,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class ShortFormatter extends LogRecordFormatter {
  @override
  StringBuffer formatToStringBuffer(LogRecord rec, StringBuffer sb) {
    sb.write(
        '${rec.time.hour}:${rec.time.minute}:${rec.time.second} ${rec.level.name} '
        '${rec.message}');

    if (rec.error != null) {
      sb.write(rec.error);
    }
    final stackTrace = rec.stackTrace ??
        (rec.error is Error ? (rec.error as Error).stackTrace : null);
    if (stackTrace != null) {
      sb.write(stackTrace);
    }
    return sb;
  }
}

class StringBufferWrapper with ChangeNotifier implements ValueNotifier<String> {
  final StringBuffer _buffer = StringBuffer();

  void writeln(String line) {
    _buffer.writeln(line);
    notifyListeners();
  }

  @override
  String toString() => _buffer.toString();

  @override
  String get value => _buffer.toString();

  @override
  set value(String newValue) => _buffer
    ..clear()
    ..write(newValue);
}

class MemoryAppender extends BaseLogAppender {
  MemoryAppender() : super(ShortFormatter());

  final StringBufferWrapper log = StringBufferWrapper();

  @override
  void handle(LogRecord record) {
    log.writeln(formatter.format(record));
  }
}

这个示例程序展示了如何通过用户界面与 macos_secure_bookmarks 插件交互。用户可以选择文件、创建书签,并解析和访问这些书签。此外,还包含了一个简单的日志记录系统,用于跟踪应用程序的操作。


更多关于Flutter macOS安全书签管理插件macos_secure_bookmarks的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter macOS安全书签管理插件macos_secure_bookmarks的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成并使用macos_secure_bookmarks插件来管理macOS安全书签的示例代码。这个插件允许你在macOS上创建、读取、更新和删除安全书签。

前提条件

  1. 确保你已经安装了Flutter和Dart。
  2. 创建一个新的Flutter项目或在现有项目中添加macos_secure_bookmarks插件。

步骤

  1. 添加插件依赖

    在你的pubspec.yaml文件中添加以下依赖:

    dependencies:
      flutter:
        sdk: flutter
      macos_secure_bookmarks: ^latest_version  # 替换为最新版本号
    

    然后运行flutter pub get来安装依赖。

  2. 配置iOS和macOS项目

    确保你的ios/Runnermacos/Runner项目配置正确,以支持该插件。通常,插件安装会自动处理这些配置。

  3. 使用插件

    下面是一个简单的示例,展示如何在macOS上使用macos_secure_bookmarks插件来管理安全书签。

    import 'package:flutter/material.dart';
    import 'package:macos_secure_bookmarks/macos_secure_bookmarks.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('macOS Secure Bookmarks Example'),
            ),
            body: SecureBookmarksExample(),
          ),
        );
      }
    }
    
    class SecureBookmarksExample extends StatefulWidget {
      @override
      _SecureBookmarksExampleState createState() => _SecureBookmarksExampleState();
    }
    
    class _SecureBookmarksExampleState extends State<SecureBookmarksExample> {
      String _result = '';
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text('macOS Secure Bookmarks Example'),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () async {
                  // 创建安全书签
                  String url = 'https://www.example.com';
                  String? bookmarkGuid = await MacosSecureBookmarks.createBookmark(
                    label: 'Example Bookmark',
                    url: url,
                    accessibilityTypes: [
                      MacosSecureBookmarksAccessibilityType.kAXTrustedAppAccessibility,
                    ],
                  );
    
                  setState(() {
                    _result = 'Bookmark created with GUID: $bookmarkGuid';
                  });
                },
                child: Text('Create Bookmark'),
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () async {
                  // 读取安全书签
                  String? bookmarkGuid = 'your-bookmark-guid-here';  // 替换为实际书签GUID
                  MacosSecureBookmarksBookmark? bookmark = await MacosSecureBookmarks.getBookmark(bookmarkGuid);
    
                  setState(() {
                    _result = 'Bookmark: ${bookmark?.toJson()}';
                  });
                },
                child: Text('Get Bookmark'),
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () async {
                  // 删除安全书签
                  String? bookmarkGuid = 'your-bookmark-guid-here';  // 替换为实际书签GUID
                  bool success = await MacosSecureBookmarks.deleteBookmark(bookmarkGuid);
    
                  setState(() {
                    _result = 'Bookmark deleted: $success';
                  });
                },
                child: Text('Delete Bookmark'),
              ),
              SizedBox(height: 16),
              Text(_result),
            ],
          ),
        );
      }
    }
    

注意事项

  1. 权限:确保你的应用具有适当的权限来创建和管理安全书签。你可能需要在Info.plist中添加相应的权限声明。

  2. 错误处理:在生产代码中,添加适当的错误处理逻辑来处理可能的异常和错误情况。

  3. 测试:在macOS设备或模拟器上测试你的应用,以确保一切按预期工作。

这个示例展示了如何使用macos_secure_bookmarks插件进行基本的书签管理操作。根据你的具体需求,你可能需要调整或扩展这些功能。

回到顶部