Fix Android crash when sharing unreadable media into the app (#10674)
This commit is contained in:
+39
-19
@@ -119,17 +119,15 @@ class ExpoReceiveAndroidIntentsModule : Module() {
|
|||||||
uris: List<Uri>,
|
uris: List<Uri>,
|
||||||
text: String?,
|
text: String?,
|
||||||
) {
|
) {
|
||||||
var allParams = ""
|
// Some URIs we receive may be unreadable (revoked permission, deleted file,
|
||||||
|
// a provider that rejects the read). Skip those rather than crashing the
|
||||||
|
// whole app, since this runs synchronously on the module init path.
|
||||||
|
val allParams =
|
||||||
|
uris
|
||||||
|
.mapNotNull { uri -> getImageInfo(uri) }
|
||||||
|
.joinToString(",") { info -> buildUriData(info) }
|
||||||
|
|
||||||
uris.forEachIndexed { index, uri ->
|
if (allParams.isEmpty()) return
|
||||||
val info = getImageInfo(uri)
|
|
||||||
val params = buildUriData(info)
|
|
||||||
allParams = "${allParams}$params"
|
|
||||||
|
|
||||||
if (index < uris.count() - 1) {
|
|
||||||
allParams = "$allParams,"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val encodedUris = URLEncoder.encode(allParams, "UTF-8")
|
val encodedUris = URLEncoder.encode(allParams, "UTF-8")
|
||||||
val encodedText = text?.let { URLEncoder.encode(it, "UTF-8") }
|
val encodedText = text?.let { URLEncoder.encode(it, "UTF-8") }
|
||||||
@@ -158,9 +156,16 @@ class ExpoReceiveAndroidIntentsModule : Module() {
|
|||||||
}
|
}
|
||||||
val file = createFile(extension)
|
val file = createFile(extension)
|
||||||
|
|
||||||
val out = FileOutputStream(file)
|
// The URI may be unreadable (revoked permission, deleted file, or a
|
||||||
appContext.currentActivity?.contentResolver?.openInputStream(uri)?.use {
|
// provider that rejects the read). Bail rather than crashing the whole
|
||||||
it.copyTo(out)
|
// app, since this runs synchronously on the module init path.
|
||||||
|
try {
|
||||||
|
FileOutputStream(file).use { out ->
|
||||||
|
val input = appContext.currentActivity?.contentResolver?.openInputStream(uri) ?: return
|
||||||
|
input.use { it.copyTo(out) }
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val info = getVideoInfo(uri) ?: return
|
val info = getVideoInfo(uri) ?: return
|
||||||
@@ -176,8 +181,15 @@ class ExpoReceiveAndroidIntentsModule : Module() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getImageInfo(uri: Uri): Map<String, Any> {
|
private fun getImageInfo(uri: Uri): Map<String, Any>? {
|
||||||
val bitmap = MediaStore.Images.Media.getBitmap(appContext.currentActivity?.contentResolver, uri)
|
val bitmap =
|
||||||
|
try {
|
||||||
|
MediaStore.Images.Media.getBitmap(appContext.currentActivity?.contentResolver, uri)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// The URI may be unreadable (revoked permission, deleted file, or a
|
||||||
|
// provider that rejects the read). Skip this image rather than crash.
|
||||||
|
return null
|
||||||
|
} ?: return null
|
||||||
// We have to save this so that we can access it later when uploading the image.
|
// We have to save this so that we can access it later when uploading the image.
|
||||||
// createTempFile will automatically place a unique string between "img" and "temp.jpeg"
|
// createTempFile will automatically place a unique string between "img" and "temp.jpeg"
|
||||||
val file = createFile("jpeg")
|
val file = createFile("jpeg")
|
||||||
@@ -195,10 +207,18 @@ class ExpoReceiveAndroidIntentsModule : Module() {
|
|||||||
|
|
||||||
private fun getVideoInfo(uri: Uri): Map<String, Any>? {
|
private fun getVideoInfo(uri: Uri): Map<String, Any>? {
|
||||||
val retriever = MediaMetadataRetriever()
|
val retriever = MediaMetadataRetriever()
|
||||||
retriever.setDataSource(appContext.currentActivity, uri)
|
val width: Int?
|
||||||
|
val height: Int?
|
||||||
val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull()
|
try {
|
||||||
val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull()
|
retriever.setDataSource(appContext.currentActivity, uri)
|
||||||
|
width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull()
|
||||||
|
height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// The URI may be unreadable or not a valid media source. Skip rather than crash.
|
||||||
|
return null
|
||||||
|
} finally {
|
||||||
|
retriever.release()
|
||||||
|
}
|
||||||
|
|
||||||
if (width == null || height == null) {
|
if (width == null || height == null) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
Reference in New Issue
Block a user