如何在安卓上将PDF附加到意图中以便发送(通过电子邮件、Dropbox等)

huangapple go评论76阅读模式
英文:

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(), &quot;pdfs&quot;);
  pdfDirPath.mkdirs();
  
  File file = new File(pdfDirPath, &quot;attachment.pdf&quot;);
  file.deleteOnExit();

  Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + &quot;.file.provider&quot;, file);
  FileOutputStream os = null;
  try {
    Logger.info(&quot;Generate file &quot; + 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(&quot;text/plain&quot;);
  
  emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
  emailIntent.putExtra(EXTRA_SUBJECT, &quot;Send something&quot;);
  emailIntent.putExtra(Intent.EXTRA_TEXT, &quot;You receive attachment&quot;);
  emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

  startActivity(emailIntent);
}

In your app add the file provider definition:

AndroidManifest.xml
 
&lt;application
  android:name=&quot;.DemaApplication&quot;
  android:allowBackup=&quot;false&quot;
  android:icon=&quot;@mipmap/ic_launcher&quot;
  android:label=&quot;@string/app_name&quot;
  android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
  android:supportsRtl=&quot;true&quot;
  android:theme=&quot;@style/AppTheme&quot;&gt;

  &lt;provider
    android:name=&quot;androidx.core.content.FileProvider&quot;
    android:authorities=&quot;${applicationId}.file.provider&quot;
    android:exported=&quot;false&quot;
    android:grantUriPermissions=&quot;true&quot;&gt;
    &lt;meta-data
       android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
             android:resource=&quot;@xml/provider_paths&quot; /&gt;
  &lt;/provider&gt;
  ...
&lt;/application&gt;
provider_path.xml
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;paths&gt;
&lt;files-path
name=&quot;internal_files&quot;
path=&quot;/&quot;/&gt;
&lt;!--&lt;external-path name=&quot;external_files&quot; path=&quot;./files&quot;/&gt;--&gt;
&lt;/paths&gt;

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 &quot;mailto:&quot; should not be there).

Problem #4: The MIME type of a PDF is not text/plain &mdash; 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.

huangapple
  • 本文由 发表于 2020年4月5日 23:39:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/61045118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定