action view: fixed opening file media content

This commit is contained in:
Thibault Deckers 2021-03-19 14:35:26 +09:00
parent f5b38d2e3f
commit 23997d1f4f
4 changed files with 23 additions and 19 deletions

View file

@ -2,6 +2,8 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [Unreleased] ## [Unreleased]
### Fixed
- opening media shared by other apps as file media content
## [v1.3.6] - 2021-03-18 ## [v1.3.6] - 2021-03-18
### Added ### Added

View file

@ -112,9 +112,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id) isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)
else -> uri else -> uri
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentUri = StorageUtils.getOriginalUri(contentUri)
contentUri = MediaStore.setRequireOriginal(contentUri)
}
} }
} }

View file

@ -8,7 +8,6 @@ import android.media.MediaExtractor
import android.media.MediaFormat import android.media.MediaFormat
import android.media.MediaMetadataRetriever import android.media.MediaMetadataRetriever
import android.net.Uri import android.net.Uri
import android.os.Build
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Log
import androidx.exifinterface.media.ExifInterface import androidx.exifinterface.media.ExifInterface
@ -684,9 +683,7 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id) isVideo(mimeType) -> ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)
else -> uri else -> uri
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentUri = StorageUtils.getOriginalUri(contentUri)
contentUri = MediaStore.setRequireOriginal(contentUri)
}
} }
} }

View file

@ -293,9 +293,13 @@ object StorageUtils {
// need a document URI (not a media content URI) to open a `DocumentFile` output stream // need a document URI (not a media content URI) to open a `DocumentFile` output stream
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isMediaStoreContentUri(mediaUri)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isMediaStoreContentUri(mediaUri)) {
// cleanest API to get it // cleanest API to get it
val docUri = MediaStore.getDocumentUri(context, mediaUri) try {
if (docUri != null) { val docUri = MediaStore.getDocumentUri(context, mediaUri)
return DocumentFileCompat.fromSingleUri(context, docUri) if (docUri != null) {
return DocumentFileCompat.fromSingleUri(context, docUri)
}
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get document URI for mediaUri=$mediaUri", e)
} }
} }
// fallback for older APIs // fallback for older APIs
@ -401,13 +405,21 @@ object StorageUtils {
return ContentResolver.SCHEME_CONTENT.equals(uri.scheme, ignoreCase = true) && MediaStore.AUTHORITY.equals(uri.host, ignoreCase = true) return ContentResolver.SCHEME_CONTENT.equals(uri.scheme, ignoreCase = true) && MediaStore.AUTHORITY.equals(uri.host, ignoreCase = true)
} }
fun openInputStream(context: Context, uri: Uri): InputStream? { fun getOriginalUri(uri: Uri): Uri {
var effectiveUri = uri
// we get a permission denial if we require original from a provider other than the media store // we get a permission denial if we require original from a provider other than the media store
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isMediaStoreContentUri(uri)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isMediaStoreContentUri(uri)) {
effectiveUri = MediaStore.setRequireOriginal(uri) val path = uri.path
path ?: return uri
// from Android R, accessing the original URI for a file media content yields a `SecurityException`
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || path.startsWith("/external/images/") || path.startsWith("/external/video/")) {
return MediaStore.setRequireOriginal(uri)
}
} }
return uri
}
fun openInputStream(context: Context, uri: Uri): InputStream? {
val effectiveUri = getOriginalUri(uri)
return try { return try {
context.contentResolver.openInputStream(effectiveUri) context.contentResolver.openInputStream(effectiveUri)
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
@ -420,12 +432,7 @@ object StorageUtils {
} }
fun openMetadataRetriever(context: Context, uri: Uri): MediaMetadataRetriever? { fun openMetadataRetriever(context: Context, uri: Uri): MediaMetadataRetriever? {
var effectiveUri = uri val effectiveUri = getOriginalUri(uri)
// we get a permission denial if we require original from a provider other than the media store
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isMediaStoreContentUri(uri)) {
effectiveUri = MediaStore.setRequireOriginal(uri)
}
return try { return try {
MediaMetadataRetriever().apply { MediaMetadataRetriever().apply {
setDataSource(context, effectiveUri) setDataSource(context, effectiveUri)