【问题标题】:kotlin send email with attachment fails with URIkotlin 发送带有附件的电子邮件失败,带有 URI
【发布时间】:2018-03-22 11:44:43
【问题描述】:

我有以下 kotlin 代码来发送带有附件的电子邮件:

val file = File(directory, filename)
file.createNewFile()
file.writeText("My Text", Charsets.UTF_8)
// ---- file is written succesfully, now let us
// try to get the URI and pass it for the intent

val fileURI = FileProvider.getUriForFile(this, "com.mydomain.myapp", file!!)

val emailIntent = Intent(Intent.ACTION_SEND).apply {
        putExtra(Intent.EXTRA_SUBJECT, "My subject"))
        putExtra(Intent.EXTRA_TEXT, "My message")
        putExtra(Intent.EXTRA_STREAM, fileURI)
    }
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.type = "text/plain"
startActivity(emailIntent)

现在,当我运行上面的代码时,我得到一个错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference

用于 fileURI 分配行。如果不是 FileProvider,如果我使用:

putExtra(Intent.EXTRA_STREAM, file!!.toURI())

作为额外的意图参数,我得到一个错误:

W/Bundle: Key android.intent.extra.STREAM expected Parcelable but value was a java.net.URI.  The default value <null> was returned.

03-22 11:39:06.625 9620-9620/com.secretsapp.secretsapp W/Bundle:尝试强制转换生成的内部异常:

W/Bundle: Key android.intent.extra.STREAM expected Parcelable but value was a java.net.URI.  The default value <null> was returned.
   W/Bundle: Attempt to cast generated internal exception:
   java.lang.ClassCastException: java.net.URI cannot be cast to android.os.Parcelable
   at android.os.Bundle.getParcelable(Bundle.java:945)

该文件是在全局Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) 目录下的子目录下创建的,并且应用程序也具有Manifest.permission.WRITE_EXTERNAL_STORAGE 权限。关于如何获取文件的 URI 并将其附加到电子邮件意图的任何指针?

【问题讨论】:

    标签: android kotlin kotlin-android-extensions


    【解决方案1】:

    对于您的第一次尝试 — 这是正确的方法 — 您的 &lt;provider&gt; 没有com.mydomain.myapp 的权限值。清单中&lt;provider&gt; 元素中的权限字符串必须与您传递给getUriForFile() 的第二个参数匹配。这在the documentation for FileProvider 中有介绍。

    对于您的第二次尝试,toURI() 返回 URI,而不是 Uri。虽然您可以将其切换为Uri.fromFile(),但一旦您的targetSdkVersion 升至 24 或更高,您将在 Android 7.0+ 上崩溃。使用FileProvider 方法。

    【讨论】:

    • 我已经成功了。我完全忽略了 标签。经过一番疯狂的谷歌搜索后,我找到了它。谢谢。我将此标记为已接受的答案,但是也许您可以粘贴一些(清单的)代码,以便对寻找解决方案的人有用?
    【解决方案2】:

    CommonsWare's answer的实现

    清单:

    <application> 
    ...
    <provider
                android:name="android.support.v4.content.FileProvider" <- or use your provider implementation
                android:authorities="com.your.package.fileprovider" <- must end with .fileprovider
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/provider_paths" />
            </provider>
    ...
    </application
    

    res/xml/provider_paths.xml

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path path="Android/data/" name="files_root" />
        <external-path path="." name="external_storage_root" />
    </paths>
    

    使用 Sankar 的实现,但要获取文件 uri,权限必须等于清单中声明的​​权限:

    val fileURI = FileProvider.getUriForFile(context, "$packageName.fileprovider", yourFile)
    

    【讨论】:

      【解决方案3】:

      使用以下代码在 Kotlin 中发送有意图的电子邮件:

      private fun sendEmail() {
          val filename = "contacts_sid.vcf"
          val filelocation = File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename)
          val path = Uri.fromFile(filelocation)
          val emailIntent = Intent(Intent.ACTION_SEND)
          // set the type to 'email'
          emailIntent.type = "vnd.android.cursor.dir/email"
          val to = arrayOf("asd@gmail.com")
          emailIntent.putExtra(Intent.EXTRA_EMAIL, to)
          // the attachment
          emailIntent.putExtra(Intent.EXTRA_STREAM, path)
          // the mail subject
          emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject")
          startActivity(Intent.createChooser(emailIntent, "Send email..."))
      }
      

      【讨论】:

        猜你喜欢
        • 2013-08-26
        • 2015-09-09
        • 2013-11-26
        • 2014-11-09
        • 2017-02-04
        • 2011-10-09
        相关资源
        最近更新 更多