Reputation: 11537
My App manages a few videos and photos downloaded from a IoT device. It downloads videos & photos from these devices and places them in the Apps external Downloads
directory (retrieved with context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
).
The App offers a sharing feature, which utilizes the ACTION_SEND
intent to export a file to another application.
I have observed different behavior with my App, based on the phones Android OS version. My test is simple: Share the same file (a single photo) to 3 different Apps: 1) WhatsApp, 2) Gmail 3) InShot.
The App is using a FileProvider to export the files as it's the standard on Android now.
Support library version is 27.1.0.
The relevant code parts looks like this:
Nothing special, just the default config and a link to the paths.xml. applicationId and filesAuthority placeholders are correctly replaced.
<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>
<?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);
What is missing to create the same behavior - and most importantly - ensure WhatsApp and other apps can see the image properly, like Gmail?
Upvotes: 2
Views: 1972
Reputation: 11537
This question was resolved by ensuring the filename is passed along in lowercase.
Some Android phones did trip over this while others didn't.
Upvotes: 1