You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何正确获取Uri/String并转换为ByteString用于邮件附件?

解决Android中Content Uri转字节数组用于邮件附件的问题

核心问题分析

你之前的错误点:

  • 直接把Content Uri的字符串文本转成输入流,读取的是Uri本身的字节,而非文件实际内容,所以生成1KB的无效文件。
  • getRealPathFromURI依赖MediaStore.Images.Media.DATA字段,在Android 10(API 29)及以上的**分区存储(Scoped Storage)**机制下,该字段可能返回空或无效路径,无法再通过这种方式获取真实文件路径。

正确解决方案:用ContentResolver统一处理所有Uri

Android官方推荐使用ContentResolver直接打开任何合法Uri(包括file://和content://类型)对应的输入流,无需区分Uri类型,这是兼容全版本的标准方案。

完整代码实现

import android.content.Context
import android.net.Uri
import android.util.Base64
import java.io.InputStream

// 通用方法:将Uri转换为Base64字符串
fun uriToBase64(context: Context, uri: Uri): String? {
    return runCatching {
        context.contentResolver.openInputStream(uri)?.use { inputStream ->
            val bytes = inputStream.readBytes()
            Base64.encodeToString(bytes, Base64.DEFAULT)
        }
    }.getOrNull()
}

// 生成邮件附件JSON的方法
fun createAttachmentJson(context: Context, uri: Uri, currentDate: String, index: Int): String? {
    val base64Content = uriToBase64(context, uri) ?: return null
    val mimeType = context.contentResolver.getType(uri) ?: "image/jpeg"
    val filename = "IMAGE_${currentDate}_$index.jpg"
    
    return """
        {
            "content": "$base64Content",
            "filename": "$filename",
            "type": "$mimeType",
            "disposition": "attachment"
        }
    """.trimIndent()
}

代码说明

  1. uriToBase64方法:

    • 通过contentResolver.openInputStream(uri)获取文件输入流,这是处理Content Uri的标准方式。
    • 用use块自动关闭流,避免资源泄漏。
    • 捕获异常并返回null,保证程序稳定性。
  2. createAttachmentJson方法:

    • 通过contentResolver.getType(uri)自动获取文件的MIME类型,比硬编码更准确。
    • 生成符合要求的附件JSON字符串。

使用示例

处理PhotoPicker返回的Uri列表:

val uris: List<Uri> = // 从PhotoPicker获取的Uri列表
val currentDate = "2023-08-15"

uris.forEachIndexed { index, uri ->
    val attachmentJson = createAttachmentJson(context, uri, currentDate, index)
    attachmentJson?.let {
        // 将该JSON添加到邮件附件列表
    }
}

额外注意事项

  • 权限:确保应用已申请必要权限,Android 10以下需READ_EXTERNAL_STORAGE,Android 13及以上需READ_MEDIA_IMAGES。
  • 大文件优化:如果处理超大图片,readBytes()可能占用过多内存,建议分块读取并编码Base64,避免OOM。

内容的提问来源于stack exchange,提问作者user21300258

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 00:42:01