crash fix for users who somehow revoked ACCESS_MEDIA_LOCATION permission

This commit is contained in:
Thibault Deckers 2021-06-22 08:31:38 +09:00
parent 2d32b782bc
commit 62a8f05d1a
3 changed files with 12 additions and 7 deletions

View file

@ -112,7 +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
} }
contentUri = StorageUtils.getOriginalUri(contentUri) contentUri = StorageUtils.getOriginalUri(context, contentUri)
} }
} }

View file

@ -658,7 +658,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
} }
contentUri = StorageUtils.getOriginalUri(contentUri) contentUri = StorageUtils.getOriginalUri(context, contentUri)
} }
} }

View file

@ -1,8 +1,10 @@
package deckers.thibault.aves.utils package deckers.thibault.aves.utils
import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.content.pm.PackageManager
import android.media.MediaMetadataRetriever import android.media.MediaMetadataRetriever
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
@ -399,21 +401,24 @@ 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 getOriginalUri(uri: Uri): Uri { fun getOriginalUri(context: Context, uri: Uri): 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)) {
val path = uri.path val path = uri.path
path ?: return uri path ?: return uri
// from Android R, accessing the original URI for a file media content yields a `SecurityException` // 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/")) { if (path.startsWith("/external/images/") || path.startsWith("/external/video/")) {
// "Caller must hold ACCESS_MEDIA_LOCATION permission to access original"
if (context.checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return MediaStore.setRequireOriginal(uri) return MediaStore.setRequireOriginal(uri)
} }
} }
}
return uri return uri
} }
fun openInputStream(context: Context, uri: Uri): InputStream? { fun openInputStream(context: Context, uri: Uri): InputStream? {
val effectiveUri = getOriginalUri(uri) val effectiveUri = getOriginalUri(context, uri)
return try { return try {
context.contentResolver.openInputStream(effectiveUri) context.contentResolver.openInputStream(effectiveUri)
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
@ -426,7 +431,7 @@ object StorageUtils {
} }
fun openMetadataRetriever(context: Context, uri: Uri): MediaMetadataRetriever? { fun openMetadataRetriever(context: Context, uri: Uri): MediaMetadataRetriever? {
val effectiveUri = getOriginalUri(uri) val effectiveUri = getOriginalUri(context, uri)
return try { return try {
MediaMetadataRetriever().apply { MediaMetadataRetriever().apply {
setDataSource(context, effectiveUri) setDataSource(context, effectiveUri)