Flutter使用Dio从URL下载PDF文件无下载进度通知问题咨询
实现Flutter Dio下载PDF带系统通知进度的方案
你当前的下载逻辑仅完成了文件写入操作,Dio本身不自带系统通知展示能力,需要配合通知插件手动触发系统通知展示下载状态,具体实现步骤如下:
1. 添加所需依赖
在pubspec.yaml的dependencies节点下新增通知插件依赖,原有依赖保持不变:
dependencies: flutter_local_notifications: ^16.1.0 # 你已有的dio、fluttertoast、permission_handler、path_provider依赖无需修改
执行flutter pub get完成依赖安装。
2. 补充Android权限配置
你现有的AndroidManifest.xml已经配置了存储和网络权限,需要新增Android 13及以上版本的通知权限,在<manifest>根节点下添加如下代码:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
3. 初始化通知插件
Android 8.0及以上版本要求必须创建通知渠道才能正常展示通知,需要在应用启动时完成通知插件初始化和渠道创建,修改后的main函数代码如下:
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; // 全局声明通知插件实例 final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); void main() async { WidgetsFlutterBinding.ensureInitialized(); // 安卓通知初始化配置,传入应用图标 const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // 创建下载专用的通知渠道 const AndroidNotificationChannel downloadChannel = AndroidNotificationChannel( 'download_notify_channel', // 渠道唯一ID,后续通知需要和该ID匹配 '文件下载通知', // 渠道名称,会在系统通知设置中展示 description: '用于展示PDF文件下载进度', // 渠道描述 importance: Importance.low, // 低优先级避免下载过程中频繁响铃震动 playSound: false, ); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(downloadChannel); runApp(MyApp()); }
4. 改造downloadBook方法,添加进度监听和通知更新
修改后的下载方法会在下载过程中实时更新通知进度,下载完成/失败时也会同步修改通知状态:
downloadBook({String? downloadLink, String? title}) async { Dio dio = Dio(); const downloadNotifyId = 10086; // 通知唯一ID,下载全程复用该ID更新通知,避免生成多条通知 // 先校验通知权限 if (await Permission.postNotifications.request().isDenied) { Fluttertoast.showToast(msg: "请开启通知权限以查看下载进度"); return; } // 校验存储权限 if (await Permission.storage.request().isGranted) { final downloadPath = await path.getExternalStorageDirectory(); var filePath = "${downloadPath!.path}/$title.pdf"; try { await dio.download( downloadLink, filePath, // 监听下载进度回调 onReceiveProgress: (receivedBytes, totalBytes) { if (totalBytes != -1) { // 计算下载百分比 int progress = (receivedBytes / totalBytes * 100).round(); // 构建进度通知 AndroidNotificationDetails progressNotify = AndroidNotificationDetails( 'download_notify_channel', '文件下载通知', channelDescription: '用于展示PDF文件下载进度', importance: Importance.low, playSound: false, showProgress: true, maxProgress: 100, progress: progress, ongoing: true, // 下载过程中禁止用户手动清除通知 ); NotificationDetails notifyDetails = NotificationDetails(android: progressNotify); // 更新通知 flutterLocalNotificationsPlugin.show( downloadNotifyId, "正在下载 $title", "已完成 $progress%", notifyDetails, ); } }, ); // 下载完成,更新通知为完成状态 AndroidNotificationDetails finishNotify = const AndroidNotificationDetails( 'download_notify_channel', '文件下载通知', channelDescription: '用于展示PDF文件下载进度', importance: Importance.defaultImportance, playSound: true, showProgress: false, ongoing: false, ); NotificationDetails finishNotifyDetails = NotificationDetails(android: finishNotify); await flutterLocalNotificationsPlugin.show( downloadNotifyId, "$title 下载完成", "文件已保存到本地存储", finishNotifyDetails, ); } catch (e) { // 下载失败,更新通知为失败状态 AndroidNotificationDetails errorNotify = const AndroidNotificationDetails( 'download_notify_channel', '文件下载通知', channelDescription: '用于展示PDF文件下载进度', importance: Importance.defaultImportance, playSound: true, showProgress: false, ongoing: false, ); NotificationDetails errorNotifyDetails = NotificationDetails(android: errorNotify); await flutterLocalNotificationsPlugin.show( downloadNotifyId, "$title 下载失败", "请检查网络后重试", errorNotifyDetails, ); Fluttertoast.showToast(msg: "Terjadi kesalahan. Download gagal.", timeInSecForIosWeb: 1); } finally { dio.close(); } } }
如果需要实现点击下载完成的通知直接打开PDF,可以在初始化通知时添加onDidReceiveNotificationResponse回调,配合open_file等插件跳转打开本地PDF文件即可。
内容的提问来源于stack exchange,提问作者lukman azhari
相关产品推荐
相关产品推荐

