ACTION_SEND:发送到 WhatsApp 的错误 mime 导致缺少缩略图
ACTION_SEND: Incorrect mime sent to WhatsApp resulting in missing Thumbnails
我的应用程序管理从 IoT 设备下载的一些视频和照片。它从这些设备下载视频和照片,并将它们放在 Apps 外部 Downloads
目录中(使用 context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
检索)。
该应用程序提供 共享 功能,该功能利用 ACTION_SEND
意图将文件导出到另一个应用程序。
根据手机 Android OS 版本,我观察到我的应用程序有不同的行为。我的测试很简单:将同一个文件(一张照片)共享到 3 个不同的应用程序:1) WhatsApp,2) Gmail 3) InShot.
在 Android 7.0 上,应用程序行为不完整:
- WhatsApp:无法显示图像缩略图,文件作为 "document" 发送。
- Gmail:没问题,文件已正确发送到 Gmail,包括缩略图
- InShot:无法检索文件并显示错误消息。
在 Android 8.0 上,一切正常。
- WhatsApp:显示视频或照片编辑器,然后正确复制文件。
- Gmail:没问题,同上。
- InShot:没问题,可以导入文件。
代码
应用程序正在使用 FileProvider 导出文件,因为它现在是 Android 上的标准。
支持库版本为27.1.0.
相关代码部分如下所示:
AndroidManifest.xml
没什么特别的,只是默认配置和 link 到 paths.xml。 applicationId 和 filesAuthority 占位符已正确替换。
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}${filesAuthority}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="Download"
path="Download"/>
</paths>
createSharingIntent(context: Context, videos: List<Video>): Intent
var hasVideos = false
var hasImages = false
var items = emptyArray<ClipData.Item>()
var contentTypes = emptyArray<String>()
// Create ClipData items & contentTypes which help to further specify the Intent contents.
for (video in videos) {
items += ClipData.Item(FileProvider.getUriForFile(context, BuildConfig.FILES_AUTHORITY, File(video.path)))
contentTypes += (if (video.isJpg) IMAGE_JPG else MediaFormat.MIMETYPE_VIDEO_AVC)
if (video.isJpg) {
hasImages = true
} else {
hasVideos = true
}
}
// Build the Intent
val intent: Intent
val intentType = when {
hasImages && hasVideos -> "*/*"
hasImages -> IMAGE_JPG
else -> MediaFormat.MIMETYPE_VIDEO_AVC
}
intent = if (items.size > 1) {
Intent().setAction(Intent.ACTION_SEND_MULTIPLE)
.setType(intentType)
.putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(items.map { it.uri }))
} else {
Intent().setAction(Intent.ACTION_SEND)
.setDataAndTypeAndNormalize(items[0].uri, intentType)
.putExtra(Intent.EXTRA_STREAM, items[0].uri)
}
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION.or(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
// Specify more detail in ClipData - which might be helpful for
val clipData = ClipData("Export", contentTypes, items[0])
for (i in 1 until items.size) {
clipData.addItem(items[i])
}
intent.clipData = clipData
return intent
接受意图并发送
Intent intent = createSharingIntent(activity, videos)
Intent chooser = Intent.createChooser(intent, activity.getString(R.string.share_files));
activity.startActivity(chooser);
创建相同的行为缺少什么 - 最重要的是 - 确保 WhatsApp 和其他应用程序可以正确看到图像,如 Gmail?
此问题已通过确保以小写形式传递的文件名得到解决。
一些 Android 手机确实被绊倒了,而其他手机则没有。
我的应用程序管理从 IoT 设备下载的一些视频和照片。它从这些设备下载视频和照片,并将它们放在 Apps 外部 Downloads
目录中(使用 context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
检索)。
该应用程序提供 共享 功能,该功能利用 ACTION_SEND
意图将文件导出到另一个应用程序。
根据手机 Android OS 版本,我观察到我的应用程序有不同的行为。我的测试很简单:将同一个文件(一张照片)共享到 3 个不同的应用程序:1) WhatsApp,2) Gmail 3) InShot.
在 Android 7.0 上,应用程序行为不完整:
- WhatsApp:无法显示图像缩略图,文件作为 "document" 发送。
- Gmail:没问题,文件已正确发送到 Gmail,包括缩略图
- InShot:无法检索文件并显示错误消息。
在 Android 8.0 上,一切正常。
- WhatsApp:显示视频或照片编辑器,然后正确复制文件。
- Gmail:没问题,同上。
- InShot:没问题,可以导入文件。
代码
应用程序正在使用 FileProvider 导出文件,因为它现在是 Android 上的标准。
支持库版本为27.1.0.
相关代码部分如下所示:
AndroidManifest.xml
没什么特别的,只是默认配置和 link 到 paths.xml。 applicationId 和 filesAuthority 占位符已正确替换。
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}${filesAuthority}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="Download"
path="Download"/>
</paths>
createSharingIntent(context: Context, videos: List<Video>): Intent
var hasVideos = false
var hasImages = false
var items = emptyArray<ClipData.Item>()
var contentTypes = emptyArray<String>()
// Create ClipData items & contentTypes which help to further specify the Intent contents.
for (video in videos) {
items += ClipData.Item(FileProvider.getUriForFile(context, BuildConfig.FILES_AUTHORITY, File(video.path)))
contentTypes += (if (video.isJpg) IMAGE_JPG else MediaFormat.MIMETYPE_VIDEO_AVC)
if (video.isJpg) {
hasImages = true
} else {
hasVideos = true
}
}
// Build the Intent
val intent: Intent
val intentType = when {
hasImages && hasVideos -> "*/*"
hasImages -> IMAGE_JPG
else -> MediaFormat.MIMETYPE_VIDEO_AVC
}
intent = if (items.size > 1) {
Intent().setAction(Intent.ACTION_SEND_MULTIPLE)
.setType(intentType)
.putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(items.map { it.uri }))
} else {
Intent().setAction(Intent.ACTION_SEND)
.setDataAndTypeAndNormalize(items[0].uri, intentType)
.putExtra(Intent.EXTRA_STREAM, items[0].uri)
}
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION.or(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
// Specify more detail in ClipData - which might be helpful for
val clipData = ClipData("Export", contentTypes, items[0])
for (i in 1 until items.size) {
clipData.addItem(items[i])
}
intent.clipData = clipData
return intent
接受意图并发送
Intent intent = createSharingIntent(activity, videos)
Intent chooser = Intent.createChooser(intent, activity.getString(R.string.share_files));
activity.startActivity(chooser);
创建相同的行为缺少什么 - 最重要的是 - 确保 WhatsApp 和其他应用程序可以正确看到图像,如 Gmail?
此问题已通过确保以小写形式传递的文件名得到解决。
一些 Android 手机确实被绊倒了,而其他手机则没有。