Closed osamasado closed 2 years ago
I had the same issue, I end up using getTemporaryDirectory from path_provider instead of getApplicationDocumentsDirectory.
Hi @CodingWithTashi could you please explain in a little more detail how this works for you?
In my case the problem is only on Android. Works fine on iOS. I am creating a PDF in another class and pass the path to that PDF into the class I am working with at this stage. I use that path successfully when creating a PDF review, loading the previously saved file and displaying it fine. However when I use the same path to try and add it as an attachment to an email I get the same error message. If I don't try and add an attachment the email is generated and works fine.
I do currently save the generated file as getApplicationDocumentsDirectory() when creating the file in a previous class. I have tried getTemporaryDirectory() but then the path does not even survive to create the Preview.
The error I get is
Platform Response PlatformException(error, Failed to find configured root that contains /data/data/com.XXXX.XXXX/app_flutter/example.pdf, null, java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.XXXX.XXXX/app_flutter/example.pdf
I have indicated below where the path works and does not work in my full code for the class:
import 'package:XXXX/screens/home/settings_form.dart'; import 'package:XXXX/shared/constants.dart'; import 'package:flutter/material.dart'; import 'package:pdf_viewer_plugin/pdf_viewer_plugin.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart';
class PdfPreviewScreen extends StatefulWidget { final String path;
PdfPreviewScreen({this.path});
@override _PdfPreviewScreenState createState() => _PdfPreviewScreenState(); }
class _PdfPreviewScreenState extends State
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text("Your PDF Preview",
style: TextStyle(color: Colors.black, fontSize: 12 textAdjust)),
),
body: Center(
child: Column(children:
Future
if (remainMail < 1) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => SettingsForm()));
} else {
print("Setting up email");
final Email email = Email(
body:
'Please find attached the generated PDF',
subject: "Generated PDF",
recipients: [""],
attachmentPaths: [widget.path], //THIS WORKS FOR IOS BUT FAILS FOR ANDROID
isHTML: false,
);
String platformResponse;
try {
await FlutterEmailSender.send(email);
platformResponse = 'success';
} catch (error) {
platformResponse = error.toString();
print("Platform Response $platformResponse");
}
Navigator.pop(context);
Navigator.pop(context);
if (platformResponse == 'success') {
sendingMail();
}
}
} }
Hi @LeapingSwan, You mentioned you are using getApplicationDocumentsDirectory
in your case and I can also see you are passing the path in PdfPreviewScreen. I not able to replicate your issue since code attached is just a snippet of your application.
But what I could recommend you is that try getTemporaryDirectory
instead of getApplicationDocumentsDirectory
.
/// This all field and method are define outside class so that you can use anywhere in your application
late File logFile; // global file it can be txt,pdf,docx etc
Future
Future
2. Here is how you can get the path and attach to mail
static void launchEmail(BuildContext context) async { try { final Email email = Email( body: 'Attaching log for ${getFormattedDateFromDateTime( dateTime: DateTime.now(), )}', subject: 'Log', recipients: ['abc@cde.com'], attachmentPaths: [logFile.path], // global file define at first isHTML: false, ); await FlutterEmailSender.send(email); } on PlatformException catch (e) { ApplicationUtil.showSnackBar(context: context, message: e.message!); } catch (e) { print("=========================ERROR========================="); ApplicationUtil.showSnackBar(context: context, message: e.toString()); } }
I have tested in both IOS and android. It worked in both.
@CodingWithTashi thanks for coming back to me so quickly.
Unfortunately it's a large project so not really practicable to share the full project hence providing the single class. That said the only thing I do elsewhere that is relevant is save the draft PDF when I have created it. For that I use the following:
Future savePdf() async { Directory documentDirectory = await getApplicationDocumentsDirectory();
String documentPath = documentDirectory.path;
File file = File("$documentPath/example.pdf");
file.writeAsBytesSync(await pdf.save());
PdfDoc("$documentPath/example.pdf");
}
and when I go to the class I shared in my original post I then call
Directory documentDirectory = await getApplicationDocumentsDirectory();
String documentPath = documentDirectory.path;
String fullPath = "$documentPath/example.pdf";
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PdfPreviewScreen(
path: fullPath,
)));
I have been trying your suggestion of getTemporaryDirectory but the problem I am having is the file does not seem to persist across classes. So if I use getTemporaryDirectory the file is not available for use when I go to preview the PDF and certainly not to attach it. I am currently exploring trying to re-save the file to the getTemporaryDirectory just before I try and load it as a preview or attachment but can't get that working yet (I'm self taught on Flutter so these things take me a while) but in any case that seems like a bit of a hack even if it does work. Ideally I would save it in the getApplicationsDirectory and have it to use elsewhere just by passing the path.
Any further thoughts welcome.
Thanks
Stephen
Ok I solved it using, as you suggested the getTemporaryDirectory, and the key to getting that working was putting the file in global location and querying it for it's own path when I needed it rather than trying to pass the path through. That's brilliant, thanks so much for your help.
Stephen
Interesting, passing globally works. Worth the tip.
Added additional path for PathProvider:
<files-path name="files" path="../"/>
This seems to solve the access problem when the file is in getApplicationDocumentsDirectory()
.
Fix will be available in v5.1.0.
I am considering adding:
<root-path name="root" path="." />
That also fixes a problem but it is not officially documented, so maybe the first solution will be enough.
flutter_email_sender: ^4.0.0 path_provider: ^2.0.1
Please help me, how can I solve this issue?