英文:
How to attach a pdf to intent to send (to email, dropbox, etc) in android
问题
嗨,所以我把我的PDF文件保存在外部数据存储中。例如:
Environment.getExternalStorageDirectory().getPath() + "/file.pdf";
然后,我尝试将其附加到意图以进行发送:
File attachment = this.getFileStreamPath(fileDirectory + "/" + fileName);
Uri uri = Uri.fromFile(attachment);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setDataAndType(Uri.parse("mailto:"), "text/plain"); // 我还尝试过"application/pdf"
emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Calc PDF报告");
emailIntent.putExtra(Intent.EXTRA_TEXT, "PDF报告");
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "发送邮件..."));
finish();
但是我遇到了错误:
Caused by: java.lang.IllegalArgumentException: File /storage/emulated/0/file.pdf 包含路径分隔符
我认为可能是我保存文件的位置有问题,但是找不到任何最新的示例。
英文:
Hey so I save my pdf in external data storage. Eg:
Environment.getExternalStorageDirectory().getPath() + "/file.pdf"
Then, I try to attach it to intent to send:
File attachment = this.getFileStreamPath(fileDirectory + "/" + fileName);
Uri uri = Uri.fromFile(attachment);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setDataAndType(Uri.parse("mailto:"), "text/plain"); // I have also tried "application/pdf"
emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Calc PDF Report");
emailIntent.putExtra(Intent.EXTRA_TEXT, " PDF Report");
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "Send mail..."));
finish();
and im getting the error:
Caused by: java.lang.IllegalArgumentException: File /storage/emulated/0/file.pdf contains a path separator
I am thinking it is something wrong with were I am saving my file, but can't find any examples that are up-to-date.
答案1
得分: 2
要使用意图将文件作为电子邮件附件共享,您需要使用FileProvider。
/**
* 生成文件内容并返回文件的Uri
*/
public static Uri generateFile(Context context) {
File pdfDirPath = new File(context.getFilesDir(), "pdfs");
pdfDirPath.mkdirs();
File file = new File(pdfDirPath, "attachment.pdf");
file.deleteOnExit();
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".file.provider", file);
FileOutputStream os = null;
try {
Logger.info("生成文件 " + file.getAbsolutePath());
os = new FileOutputStream(file);
document.writeTo(os);
document.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
return uri;
}
private void share(Context context) {
Uri uri = generateFile(context);
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
emailIntent.putExtra(EXTRA_SUBJECT, "发送内容");
emailIntent.putExtra(Intent.EXTRA_TEXT, "您将收到附件");
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(emailIntent);
}
在您的应用程序中添加文件提供程序的定义:
AndroidManifest.xml
<application
android:name=".DemaApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.file.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
...
</application>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="internal_files"
path="/"/>
<!--<external-path name="external_files" path="./files"/>-->
</paths>
最后但同样重要的是,您需要指定文件提供程序的路径(您的文件在哪里)。希望这有所帮助。在此查看有关如何使用意图发送电子邮件和附件的官方文档。
英文:
To share a file as an email attachment using intent, you need to use a FileProvider.
/**
* Generate file content and returns uri file
*/
public static Uri generateFile(Context context) {
File pdfDirPath = new File(context.getFilesDir(), "pdfs");
pdfDirPath.mkdirs();
File file = new File(pdfDirPath, "attachment.pdf");
file.deleteOnExit();
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".file.provider", file);
FileOutputStream os = null;
try {
Logger.info("Generate file " + file.getAbsolutePath());
os = new FileOutputStream(file);
document.writeTo(os);
document.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
return uri;
}
private void share(Context context) {
Uri uri = generateFile(context);
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
emailIntent.putExtra(EXTRA_SUBJECT, "Send something");
emailIntent.putExtra(Intent.EXTRA_TEXT, "You receive attachment");
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(emailIntent);
}
In your app add the file provider definition:
AndroidManifest.xml
<application
android:name=".DemaApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.file.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
...
</application>
provider_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="internal_files"
path="/"/>
<!--<external-path name="external_files" path="./files"/>-->
</paths>
At last but not least, you need to specify the file provider path (where are your files). I hope this helps. Here, the official documentation about how to send email and attachment with intent.
答案2
得分: 1
问题#1:getFileStreamPath()
不支持子目录,并且与外部存储无关,其中您的文件驻留。
问题#2:Uri.fromFile()
在Android 7.0上不起作用,因为您的应用程序将由于FileUriExposedException
而崩溃。为了解决这个问题和问题#1,使用FileProvider
设置一个content
Uri
,您可以将其用于EXTRA_STREAM
。
问题#3:ACTION_SEND
不使用“data”Uri
(即,您的“mailto:”不应该在那里)。
问题#4:PDF的MIME类型不是text/plain
——正如您的注释所指出的那样,使用application/pdf
。
问题#5:在Android 10及更高版本上已弃用getExternalStorageDirectory()
,您将无法在那里写入文件。考虑使用getExternaFilesDir(null)
(在Context
上调用)作为更好的位置,可在不需要权限的情况下运行,并支持更多Android操作系统版本。
找不到最新的示例
文档涵盖了使用ACTION_SEND
的方法。
英文:
Problem #1: getFileStreamPath()
does not support subdirectories and is not related to external storage, where your file resides.
Problem #2: Uri.fromFile()
will not work on Android 7.0, as your app will crash with a FileUriExposedException
. To fix this and Problem #1, use FileProvider
to set up a content
Uri
that you can use for EXTRA_STREAM
.
Problem #3: ACTION_SEND
does not use a "data" Uri
(i.e., your "mailto:"
should not be there).
Problem #4: The MIME type of a PDF is not text/plain
— as your comment notes, use application/pdf
.
Problem #5: getExternalStorageDirectory()
is deprecated on Android 10 and higher, and you will not be able to write files there. Consider using getExternaFilesDir(null)
(called on a Context
) for a better location that works without permissions and on more Android OS versions.
> can't find any examples that are up-to-date
The documentation covers the use of ACTION_SEND
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论