FlutterDownloader works downloading pdf in android but fails on iOS
I could to solve this problem. The previous developers committed a bad programming practice, which caused a race condition in ios when trying to force open a task without checking its status.
I had to change the "while" loop and within it, check the status and progress of the download task. Once it reached 100% progress and its status was complete, then we break the loop and finally open the task.
In provider/download/downloadprovider.dart
bool waitTask = true;
while(waitTask) {
String query = "SELECT * FROM task WHERE task_id='" + taskId + "'";
var _tasks = await FlutterDownloader.loadTasksWithRawQuery(query: query);
String taskStatus = _tasks[0].status.toString();
int taskProgress = _tasks[0].progress;
if(taskStatus == "DownloadTaskStatus(3)" && taskProgress == 100){
waitTask = false;
}
}
await FlutterDownloader.open(taskId: taskId);
Angel Pineda
Updated on December 27, 2022Comments
-
Angel Pineda over 1 year
I'm new to flutter/iOS.
I'm using:
Flutter 1.22.6 • channel stable • https://github.com/flutter/flutter.git Framework • revision 9b2d32b605 • 2021-01-22 14:36:39 -0800 Engine • revision 2f0af37152 Tools • Dart 2.10.5 flutter_downloader: ^1.4.4
I have to correct an application that I did not code I'm trying to understand it. It downloads a pdf file and open it, but is not working in iOS.
All the configuration that I read in https://github.com/fluttercommunity/flutter_downloader is correct.
Flutter doctor is OK.
Below I show you parts of the code
main.dart
final _prefs = SharedPreferences(); void main() async { WidgetsFlutterBinding.ensureInitialized(); final prefs = SharedPreferences(); await prefs.initPrefs(); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown ]); WidgetsFlutterBinding.ensureInitialized(); await FlutterDownloader.initialize(debug: true); _prefs.uid = await getId(); runApp(MyApp()); }
pages/registry/facture.dart
List<Widget> _actionsCreateBar(BuildContext context) { return <Widget>[ (document.id != null) ? IconButton( icon: Icon(EvaIcons.downloadOutline), onPressed: () async { _downloadAction(); // This method is executed when user press download icon }, color: primaryColor, iconSize: 25, ) : Container(), ]; } void _downloadAction() async { if (await utils.isInternetAvailable()) { if (await _validateUrlRideBeforeDownload()) { await _pdfBloc.downloadPdf(document.url_ride, Theme.of(context).platform); setState(() {}); return; } _showDialogOk( context, 'Download', 'Wait please'); } else { _showDialogOk(context, 'Info', 'No conection'); } }
bloc/pdf/pdfbloc.dart
class PdfBloc { final _downloadingController = BehaviorSubject<bool>(); final _loadingController = BehaviorSubject<bool>(); final _progressStringController = BehaviorSubject<String>(); final _pdfProvider = DownloadProvider(); Stream<String> get progressStringStream => _progressStringController.stream; Stream<bool> get loadingStream => _loadingController.stream; Stream<bool> get downloadingStream => _downloadingController.stream; Future<ResponseData> downloadPdf(String url, var platform) async { _downloadingController.sink.add(true); ResponseData resData = await _pdfProvider.downloadPdf(url, _progressStringController, platform); _downloadingController.sink.add(false); return resData; } dispose() { _downloadingController.close(); _progressStringController.close(); _loadingController.close(); } }
provider/download/downloadprovider.dart
class DownloadProvider { Future<ResponseData> downloadPdf(String url, dynamic progressString, var platform) async { ResponseData resData = ResponseData(); final _prefs = SharedPreferences(); try { var path = await findLocalPath(platform) + '/'; FlutterDownloader.cancelAll(); final String taskId = await FlutterDownloader.enqueue( url: url, savedDir: path, showNotification: true, // show download progress in status bar (for Android) openFileFromNotification: true, // click on notification to open downloaded file (for Android) headers: {HttpHeaders.authorizationHeader: _prefs.token, 'Content-type': 'application/json'}, ); // Last developer used this "while" to wait while a dialog is shown // Android behaviour: flutter says "only success task can be opened" but then it works // iOS behaviour: flutter says "only success task can be opened" infinitely and never // shows the pdf // In iOS this loop iterates forever while(!await FlutterDownloader.open(taskId: taskId,)) { // Last developer did this validation, but I don't know why if (platform == TargetPlatform.iOS) { await FlutterDownloader.open(taskId: taskId); } } _setResponseData(resData, 'Completed', false); return resData; } catch(e) { _setResponseData(resData, 'Error', true); return resData; } } _setResponseData(ResponseData resData, String message, bool state) { resData.setData(message); resData.setError(state); } }
Future<String> findLocalPath(var platform) async { final directory = platform == TargetPlatform.android ? await getExternalStorageDirectory() : await getApplicationDocumentsDirectory(); return directory.path; }
I have tried several versions of ios and iphone without success.
Any ideas? Please help me, I'm stuck.
Thanks.
-
Anoop Thiruonam over 2 yearsNice clean code!
-
-
Angel Pineda about 3 yearsAll the configuration is fine. I think the problem is in code
-
Fahmi Sawalha over 2 yearsi have a similar issue , any help will be appreciated