Android_小白 2024-09-17 00:51 采纳率: 0%
浏览 16

手机的共有目录,flutter怎么获取

flutter 如何将文件保存到手机的公有目录下,flutter path_provider 获取的路径无法获取到以下的路径
Android 的功能目录 有以下
音乐:/storage/emulated/0/Music
闹钟:/storage/emulated/0/Alarms
播客:/storage/emulated/0/Podcasts
通知:/storage/emulated/0/Notifications
图片:/storage/emulated/0/Pictures
电影:/storage/emulated/0/Movies
下载:/storage/emulated/0/Download
媒体:/storage/emulated/0/DCIM
文档:/storage/emulated/0/Documents
获取方式:Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) 音乐的共有目录。

测试,在flutter中通过Android原生Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) 获取的路径,在flutter中写入时会报错无权限,问题是flutter已经动态授权了。

请问有何办法解决?或者有哪个flutter库可以解决?

  • 写回答

1条回答 默认 最新

  • 越重天 Java领域新星创作者 2024-09-17 12:16
    关注

    在Flutter中,如果你想将文件保存到手机的公有目录(如音乐、图片、下载等),可以使用path_provider插件来获取路径,但需要注意Android 10及以上版本的存储访问框架(Storage Access Framework, SAF)和分区存储(Scoped Storage)的限制。

    解决方案

    1. 使用path_provider插件
      path_provider插件可以获取应用的私有目录(如getApplicationDocumentsDirectory),但不能直接获取公有目录。

    2. 使用permission_handler插件
      在Android 10及以上版本中,需要动态申请存储权限。permission_handler插件可以帮助你请求权限。

    3. 使用flutter_file_manager插件
      这个插件可以帮助你管理文件和目录,但同样需要注意权限问题。

    4. 使用flutter_downloader插件
      这个插件可以帮助你下载文件到公有目录,但需要处理权限和存储访问框架。

    具体步骤

    1. 添加依赖

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

    dependencies:
      flutter:
        sdk: flutter
      path_provider: ^2.0.11
      permission_handler: ^10.0.0
      flutter_downloader: ^1.7.1
    

    2. 请求权限

    在Android 10及以上版本中,需要动态请求存储权限。使用permission_handler插件来请求权限:

    import 'package:permission_handler/permission_handler.dart';
    
    void requestStoragePermission() async {
      var status = await Permission.storage.status;
      if (!status.isGranted) {
        await Permission.storage.request();
      }
    }
    

    3. 获取公有目录路径

    使用path_provider插件获取公有目录路径:

    import 'package:path_provider/path_provider.dart';
    import 'dart:io';
    
    Future<String> getPublicDirectoryPath(String type) async {
      Directory directory;
      switch (type) {
        case 'music':
          directory = Directory('/storage/emulated/0/Music');
          break;
        case 'alarms':
          directory = Directory('/storage/emulated/0/Alarms');
          break;
        case 'podcasts':
          directory = Directory('/storage/emulated/0/Podcasts');
          break;
        case 'notifications':
          directory = Directory('/storage/emulated/0/Notifications');
          break;
        case 'pictures':
          directory = Directory('/storage/emulated/0/Pictures');
          break;
        case 'movies':
          directory = Directory('/storage/emulated/0/Movies');
          break;
        case 'downloads':
          directory = Directory('/storage/emulated/0/Download');
          break;
        case 'media':
          directory = Directory('/storage/emulated/0/DCIM');
          break;
        case 'documents':
          directory = Directory('/storage/emulated/0/Documents');
          break;
        default:
          throw Exception('Unsupported directory type');
      }
      return directory.path;
    }
    

    4. 写入文件

    使用dart:io库将文件写入公有目录:

    import 'dart:io';
    
    Future<void> writeFileToPublicDirectory(String filePath, String content) async {
      final file = File(filePath);
      await file.writeAsString(content);
    }
    

    5. 示例代码

    以下是一个完整的示例代码,展示如何将文件写入公有目录:

    import 'package:flutter/material.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:permission_handler/permission_handler.dart';
    import 'dart:io';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: HomeScreen(),
        );
      }
    }
    
    class HomeScreen extends StatefulWidget {
      @override
      _HomeScreenState createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
      Future<void> writeToPublicDirectory() async {
        await requestStoragePermission();
        final path = await getPublicDirectoryPath('music');
        await writeFileToPublicDirectory('$path/test.txt', 'Hello, World!');
        print('File written to $path');
      }
    
      Future<String> getPublicDirectoryPath(String type) async {
        Directory directory;
        switch (type) {
          case 'music':
            directory = Directory('/storage/emulated/0/Music');
            break;
          case 'alarms':
            directory = Directory('/storage/emulated/0/Alarms');
            break;
          case 'podcasts':
            directory = Directory('/storage/emulated/0/Podcasts');
            break;
          case 'notifications':
            directory = Directory('/storage/emulated/0/Notifications');
            break;
          case 'pictures':
            directory = Directory('/storage/emulated/0/Pictures');
            break;
          case 'movies':
            directory = Directory('/storage/emulated/0/Movies');
            break;
          case 'downloads':
            directory = Directory('/storage/emulated/0/Download');
            break;
          case 'media':
            directory = Directory('/storage/emulated/0/DCIM');
            break;
          case 'documents':
            directory = Directory('/storage/emulated/0/Documents');
            break;
          default:
            throw Exception('Unsupported directory type');
        }
        return directory.path;
      }
    
      Future<void> writeFileToPublicDirectory(String filePath, String content) async {
        final file = File(filePath);
        await file.writeAsString(content);
      }
    
      void requestStoragePermission() async {
        var status = await Permission.storage.status;
        if (!status.isGranted) {
          await Permission.storage.request();
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Write to Public Directory'),
          ),
          body: Center(
            child: ElevatedButton(
              onPressed: writeToPublicDirectory,
              child: Text('Write File'),
            ),
          ),
        );
      }
    }
    

    注意事项

    1. 分区存储(Scoped Storage)
      Android 10及以上版本引入了分区存储(Scoped Storage),限制了应用对公有目录的直接访问。你需要使用存储访问框架(SAF)来访问这些目录。

    2. 权限管理
      确保你已经请求了必要的权限,并且在AndroidManifest.xml中声明了存储权限。

    3. 兼容性
      对于Android 10及以上版本,建议使用flutter_downloader插件来处理文件下载和存储,因为它已经处理了分区存储的兼容性问题。

    通过以上步骤,你应该能够在Flutter中将文件写入手机的公有目录。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月17日