From 0cc6d4938880d2821c4a9659c76b9058140689b6 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 5 Jun 2026 17:35:21 -0500 Subject: [PATCH] Android share intent: logging + temp file cleanup (#10762) Co-authored-by: Claude Opus 4.8 --- .../ExpoReceiveAndroidIntentsModule.kt | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt index 71400672be..af7344216b 100644 --- a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt +++ b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt @@ -6,6 +6,7 @@ import android.media.MediaMetadataRetriever import android.net.Uri import android.os.Build import android.provider.MediaStore +import android.util.Log import androidx.core.net.toUri import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition @@ -13,6 +14,8 @@ import java.io.File import java.io.FileOutputStream import java.net.URLEncoder +private const val TAG = "ExpoReceiveAndroidIntents" + enum class AttachmentType { IMAGE, VIDEO, @@ -161,14 +164,25 @@ class ExpoReceiveAndroidIntentsModule : Module() { // app, since this runs synchronously on the module init path. try { FileOutputStream(file).use { out -> - val input = appContext.currentActivity?.contentResolver?.openInputStream(uri) ?: return + val input = + appContext.currentActivity?.contentResolver?.openInputStream(uri) + ?: run { + file.delete() + return + } input.use { it.copyTo(out) } } } catch (e: Exception) { + Log.w(TAG, "Failed to copy shared video to cache", e) + file.delete() return } - val info = getVideoInfo(uri) ?: return + val info = + getVideoInfo(uri) ?: run { + file.delete() + return + } val encodedText = text?.let { URLEncoder.encode(it, "UTF-8") } @@ -188,15 +202,22 @@ class ExpoReceiveAndroidIntentsModule : Module() { } 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. + Log.w(TAG, "Failed to read shared image", e) return null } ?: return null // 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" val file = createFile("jpeg") - val out = FileOutputStream(file) - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out) - out.flush() - out.close() + try { + FileOutputStream(file).use { out -> + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out) + out.flush() + } + } catch (e: Exception) { + Log.w(TAG, "Failed to write shared image to cache", e) + file.delete() + return null + } return mapOf( "width" to bitmap.width, @@ -215,6 +236,7 @@ class ExpoReceiveAndroidIntentsModule : Module() { 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. + Log.w(TAG, "Failed to read shared video metadata", e) return null } finally { retriever.release()