action view: fixed opening file media content
This commit is contained in:
parent
f5b38d2e3f
commit
23997d1f4f
4 changed files with 23 additions and 19 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue