如何在 android 中将 pdf 附加到意图发送(到电子邮件、保管箱等)
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"); // 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();
我收到错误消息:
Caused by: java.lang.IllegalArgumentException: File /storage/emulated/0/file.pdf contains a path separator
我认为我正在保存我的文件有问题,但找不到任何最新的示例。
问题 #1:getFileStreamPath()
不支持子目录并且与文件所在的 external storage 无关。
问题 #2:Uri.fromFile()
无法在 Android 7.0 上运行,因为您的应用程序会因 FileUriExposedException
而崩溃。要解决此问题和问题 #1,请使用 FileProvider
设置可用于 EXTRA_STREAM
.
的 content
Uri
问题 #3:ACTION_SEND
没有使用 "data" Uri
(即你的 "mailto:"
不应该存在)。
问题 #4:PDF 的 MIME 类型不是 text/plain
— 如您的评论所述,请使用 application/pdf
.
问题 #5:getExternalStorageDirectory()
在 Android 10 及更高版本上已弃用,您将无法在那里写入文件。考虑使用 getExternaFilesDir(null)
(在 Context
上调用)以获得更好的位置,无需权限即可在更多 Android OS 版本上工作。
can't find any examples that are up-to-date
文档涵盖 the use of ACTION_SEND
。
要使用 Intent 将文件共享为电子邮件附件,您需要使用 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);
}
在您的应用中添加文件提供程序定义:
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>
最后但同样重要的是,您需要指定文件提供程序路径(您的文件在哪里)。我希望这有帮助。 Here,关于如何使用 intent 发送电子邮件和附件的官方文档。
嘿,所以我将我的 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"); // 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();
我收到错误消息:
Caused by: java.lang.IllegalArgumentException: File /storage/emulated/0/file.pdf contains a path separator
我认为我正在保存我的文件有问题,但找不到任何最新的示例。
问题 #1:getFileStreamPath()
不支持子目录并且与文件所在的 external storage 无关。
问题 #2:Uri.fromFile()
无法在 Android 7.0 上运行,因为您的应用程序会因 FileUriExposedException
而崩溃。要解决此问题和问题 #1,请使用 FileProvider
设置可用于 EXTRA_STREAM
.
content
Uri
问题 #3:ACTION_SEND
没有使用 "data" Uri
(即你的 "mailto:"
不应该存在)。
问题 #4:PDF 的 MIME 类型不是 text/plain
— 如您的评论所述,请使用 application/pdf
.
问题 #5:getExternalStorageDirectory()
在 Android 10 及更高版本上已弃用,您将无法在那里写入文件。考虑使用 getExternaFilesDir(null)
(在 Context
上调用)以获得更好的位置,无需权限即可在更多 Android OS 版本上工作。
can't find any examples that are up-to-date
文档涵盖 the use of ACTION_SEND
。
要使用 Intent 将文件共享为电子邮件附件,您需要使用 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);
}
在您的应用中添加文件提供程序定义:
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>
最后但同样重要的是,您需要指定文件提供程序路径(您的文件在哪里)。我希望这有帮助。 Here,关于如何使用 intent 发送电子邮件和附件的官方文档。