Flutter使用file_manager获取PDF路径及外部存储访问问题求助
PDF阅读器文件列表页面修复方案
关键问题修复点
1. 外部存储访问配置
- 首先添加权限处理依赖,在
pubspec.yaml中加入:permission_handler: ^10.2.0 - 将页面改为
StatefulWidget,在初始化时申请存储权限,并指定控制器初始路径为外部存储根目录
2. PDF文件筛选逻辑修正
- 移除原代码中错误的异步循环(
await不能在同步builder中使用,且遍历修改原列表会导致异常) - 通过
where方法过滤列表:保留所有目录,仅保留后缀为.pdf的文件
修正后的完整代码
import 'dart:io'; import 'HomePage.dart'; import 'package:file_manager/controller/file_manager_controller.dart'; import 'package:file_manager/file_manager.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; class FolderPage extends StatefulWidget { const FolderPage({Key? key}) : super(key: key); @override State<FolderPage> createState() => _FolderPageState(); } class _FolderPageState extends State<FolderPage> { late final FileManagerController controller; @override void initState() { super.initState(); _initStoragePermissionAndController(); } // 申请存储权限并初始化控制器 Future<void> _initStoragePermissionAndController() async { // 请求存储权限 final status = await Permission.storage.request(); if (status.isGranted) { // 获取外部存储根目录 final externalDir = await getExternalStorageDirectory(); if (externalDir != null) { // 初始化控制器,指向外部存储根目录(适配不同设备路径) controller = FileManagerController( initialDirectory: externalDir.parent.parent, ); setState(() {}); } } else { // 权限被拒绝, fallback 到内部存储 controller = FileManagerController(); } } @override Widget build(BuildContext context) { // 权限未初始化时显示加载状态 if (!mounted || !controller.isInitialized) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } return ControlBackButton( controller: controller, child: FileManager( controller: controller, builder: (context, snapshot) { List<FileSystemEntity> entities = snapshot; // 筛选目录和PDF文件 final filteredEntities = entities.where((entity) { if (FileManager.isDirectory(entity)) { return true; } else if (FileManager.isFile(entity)) { return entity.path.toLowerCase().endsWith('.pdf'); } return false; }).toList(); return Container( padding: const EdgeInsets.only(top: 3.0), decoration: const BoxDecoration(color: Color.fromARGB(255, 35, 51, 75)), child: ListView.builder( itemCount: filteredEntities.length, itemBuilder: (context, index) { final entity = filteredEntities[index]; return Container( margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(12.0)), color: const Color.fromRGBO(255, 255, 255, 0.4), ), child: ListTile( leading: CircleAvatar( backgroundColor: const Color.fromARGB(255, 40, 58, 85), child: FileManager.isFile(entity) ? const Icon(Icons.picture_as_pdf, color: Colors.white) : const Icon(Icons.folder, color: Colors.white), ), title: Text( FileManager.basename(entity), style: const TextStyle(color: Colors.white), ), onTap: () { if (FileManager.isDirectory(entity)) { controller.openDirectory(entity); } else { // 在此添加打开PDF文件的逻辑 } }, ), ); }, ), ); }, ), ); } }
额外说明
- 外部存储路径适配:
externalDir.parent.parent用于适配部分设备中getExternalStorageDirectory()返回的内部存储子目录,确保指向真正的外部存储根 - 权限处理:若用户拒绝权限,页面自动切换到内部存储,可根据需求添加权限引导弹窗
- 视觉优化:将原文件图标替换为PDF专属图标,提升用户识别度
内容的提问来源于stack exchange,提问作者Ahsan Tony
相关产品推荐
相关产品推荐

