Flutter安全存储插件saf的使用

Flutter安全存储插件saf的使用

saf

Saf

Flutter插件,利用Storage Access Framework (SAF) API来获取文件和文件夹的操作权限。

目前支持的功能

  • 使用操作系统默认的原生文件浏览器
  • 访问隐藏文件夹和文件
  • 访问目录
  • 缓存文件到应用外部文件目录
  • 同步某些目录的文件与缓存文件
  • 不同类型的默认过滤(媒体、图像、视频、音频或任何类型)
  • 支持Android平台

如果您希望在这个包中看到某个功能,请随时提出建议。🎉

示例应用

Android

Demo

使用方法

要使用此插件,在您的pubspec.yaml文件中添加saf作为依赖项。

dependencies:
  saf: ^x.x.x

初始化Saf实例

Saf saf = Saf("~/some/path");

请求目录权限

bool? isGranted = await saf.getDirectoryPermission(isDynamic: false);

if (isGranted != null && isGranted) {
  // 执行一些文件操作
} else {
  // 未能获取权限
}

获取已授予目录的所有路径

bool? directoriesPath = await saf.getPersistedPermissionDirectories();

获取当前目录的所有文件路径

List<String>? paths = await saf.getFilesPath(FileType.media);

缓存当前目录

bool? isCached = await saf.cache();

if (isCached != null && isCached) {
  // 执行一些文件操作
} else {
  // 缓存失败
}

获取当前目录的缓存文件路径

List<String>? cachedFilesPath = await saf.getCachedFilesPath();

清除当前目录的缓存

bool? isClear = await saf.clearCache();

同步当前目录与缓存目录

bool? isSynced = await saf.sync();

释放当前目录的持久化权限

bool? isReleased = await Saf.releasePersistedPermission();

释放所有已授予目录的持久化权限

await Saf.releasePersistedPermissions();

示例代码

import 'dart:io';

import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/material.dart';
import 'package:saf/saf.dart';

/// 在这里手动编辑目录
const directory = "Android/media/matrix/.neo";

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Saf saf;
  var _paths = [];

  [@override](/user/override)
  void initState() {
    Permission.storage.request();
    saf = Saf(directory);
    super.initState();
  }

  loadImage(paths, {String k = ""}) {
    var tempPaths = [];
    for (String path in paths) {
      if (path.endsWith(".jpg")) {
        tempPaths.add(path);
      }
    }
    if (k.isNotEmpty) tempPaths.add(k);
    _paths = tempPaths;
    setState(() {});
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Saf example app'),
        ),
        body: Center(
          child: SingleChildScrollView(
            child: Column(
              children: [
                if (_paths.isNotEmpty)
                  ..._paths.map(
                    (path) => Card(
                      child: Image.file(
                        File(path),
                      ),
                    ),
                  )
              ],
            ),
          ),
        ),
        bottomNavigationBar: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            ElevatedButton(
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.deepPurpleAccent),
              ),
              onPressed: () async {
                Saf.releasePersistedPermissions();
              },
              child: const Text("Release*"),
            ),
            ElevatedButton(
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.blueGrey.shade700),
              ),
              onPressed: () async {
                var cachedFilesPath = await saf.cache();
                if (cachedFilesPath != null) {
                  loadImage(cachedFilesPath);
                }
              },
              child: const Text("Cache"),
            ),
            ElevatedButton(
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.green),
              ),
              onPressed: () async {
                var isSync = await saf.sync();
                if (isSync as bool) {
                  var _paths = await saf.getCachedFilesPath();
                  loadImage(_paths);
                }
              },
              child: const Text("Sync"),
            ),
            ElevatedButton(
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.orange),
              ),
              onPressed: () async {
                var isClear = await saf.clearCache();
                if (isClear != null && isClear) {
                  loadImage([]);
                }
              },
              child: const Text("Clear"),
            ),
          ],
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        floatingActionButton: FloatingActionButton(
          elevation: 30.0,
          backgroundColor: Colors.black,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const [
              Text(
                "GRANT",
                style: TextStyle(fontSize: 13, color: Colors.red),
              ),
              Text(
                "Permission",
                style: TextStyle(fontSize: 7.8, color: Colors.red),
              )
            ],
          ),
          onPressed: () async {
            await saf.getDirectoryPermission(isDynamic: true);
          },
        ),
      ),
    );
  }
}

更多关于Flutter安全存储插件saf的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter安全存储插件saf的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用saf(Secure Access to Files)插件来进行安全存储的示例代码。saf插件允许你以安全的方式在设备上存储和检索文件。

首先,确保你已经在pubspec.yaml文件中添加了saf依赖项:

dependencies:
  flutter:
    sdk: flutter
  saf: ^x.y.z  # 请替换为最新版本号

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

接下来,下面是一个简单的示例,演示如何使用saf插件来存储和读取一个文本文件:

import 'package:flutter/material.dart';
import 'package:saf/saf.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Saf Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SafExampleScreen(),
    );
  }
}

class SafExampleScreen extends StatefulWidget {
  @override
  _SafExampleScreenState createState() => _SafExampleScreenState();
}

class _SafExampleScreenState extends State<SafExampleScreen> {
  final Saf _saf = Saf();
  String _readFileContent = '';

  Future<void> _writeFile() async {
    String filePath = 'example.txt';
    String content = 'Hello, this is a secure file!';

    try {
      await _saf.writeFile(filePath, content);
      print('File written successfully');
    } catch (e) {
      print('Error writing file: $e');
    }
  }

  Future<void> _readFile() async {
    String filePath = 'example.txt';

    try {
      String content = await _saf.readFile(filePath);
      setState(() {
        _readFileContent = content;
      });
      print('File content: $content');
    } catch (e) {
      print('Error reading file: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Saf Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _writeFile,
              child: Text('Write File'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _readFile,
              child: Text('Read File'),
            ),
            SizedBox(height: 20),
            Text('File Content:', style: TextStyle(fontSize: 18)),
            SizedBox(height: 10),
            Text(_readFileContent, style: TextStyle(fontSize: 16)),
          ],
        ),
      ),
    );
  }
}

代码解释

  1. 依赖管理

    • pubspec.yaml文件中添加saf依赖项。
  2. 主应用入口

    • MyApp类作为应用的入口,设置主题并指定主页为SafExampleScreen
  3. 示例屏幕

    • SafExampleScreen是一个有状态的Widget,包含两个按钮,一个用于写入文件,另一个用于读取文件。
    • _writeFile方法用于将内容写入名为example.txt的文件。
    • _readFile方法用于读取example.txt文件的内容,并将其显示在屏幕上。
  4. 按钮操作

    • 两个ElevatedButton分别绑定到_writeFile_readFile方法,用于触发文件写入和读取操作。
  5. UI显示

    • 使用Text组件显示读取到的文件内容。

注意事项

  • 在实际项目中,请确保处理异常和错误情况,以便更好地管理用户体验。
  • 根据需要调整文件路径和内容。
  • saf插件可能在不同平台(iOS和Android)上有不同的行为,请查阅官方文档以确保跨平台兼容性。

这个示例提供了一个基本框架,展示了如何在Flutter应用中使用saf插件进行安全文件存储和读取。

回到顶部