From 6609ba98e5f738cb8746c7ccfda1072cfa05f986 Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Tue, 8 Apr 2025 08:54:33 -0700 Subject: [PATCH] Resolve sendIntent call, reject on exception thrown (#50538) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50538 Promises created from `Linking.sendIntent` calls never resolve, leaving them dangling. This change fixes the issue in two spots: 1. By calling promise.resolve directly after the startActivity call 1. By wrapping startActivity in a try/catch so any exceptions thrown are forwarded to the promise as a rejection Changelog: [Android][Fixed] - Ensure Linking.sendIntent promises resolve or reject Reviewed By: NickGerleman Differential Revision: D72606918 fbshipit-source-id: cd437bf65bb631bc04f99b4d2e3d637f7e98b25e --- .../react/modules/intent/IntentModule.kt | 55 ++++++++++--------- .../js/examples/Linking/LinkingExample.js | 38 ++++++++----- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt index 77eedfca244..8785bce7880 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt @@ -202,39 +202,44 @@ public open class IntentModule(reactContext: ReactApplicationContext) : return } - if (extras != null) { - for (i in 0.. { - intent.putExtra(name, map.getString(EXTRA_MAP_KEY_FOR_VALUE)) - } + when (type) { + ReadableType.String -> { + intent.putExtra(name, map.getString(EXTRA_MAP_KEY_FOR_VALUE)) + } - ReadableType.Number -> { - // We cannot know from JS if is an Integer or Double - // See: https://github.com/facebook/react-native/issues/4141 - // We might need to find a workaround if this is really an issue - val number = map.getDouble(EXTRA_MAP_KEY_FOR_VALUE) - intent.putExtra(name, number) - } + ReadableType.Number -> { + // We cannot know from JS if is an Integer or Double + // See: https://github.com/facebook/react-native/issues/4141 + // We might need to find a workaround if this is really an issue + val number = map.getDouble(EXTRA_MAP_KEY_FOR_VALUE) + intent.putExtra(name, number) + } - ReadableType.Boolean -> { - intent.putExtra(name, map.getBoolean(EXTRA_MAP_KEY_FOR_VALUE)) - } + ReadableType.Boolean -> { + intent.putExtra(name, map.getBoolean(EXTRA_MAP_KEY_FOR_VALUE)) + } - else -> { - promise.reject( - JSApplicationIllegalArgumentException("Extra type for $name not supported.")) - return + else -> { + promise.reject( + JSApplicationIllegalArgumentException("Extra type for $name not supported.")) + return + } } } } - } - sendOSIntent(intent, true) + sendOSIntent(intent, true) + promise.resolve(null) + } catch (e: Exception) { + promise.reject(e) + } } private fun sendOSIntent(intent: Intent, useNewTaskFlag: Boolean) { diff --git a/packages/rn-tester/js/examples/Linking/LinkingExample.js b/packages/rn-tester/js/examples/Linking/LinkingExample.js index cec6043f197..789d698148f 100644 --- a/packages/rn-tester/js/examples/Linking/LinkingExample.js +++ b/packages/rn-tester/js/examples/Linking/LinkingExample.js @@ -64,25 +64,30 @@ class OpenSettingsExample extends React.Component { } } -class SendIntentButton extends React.Component { - handleIntent = async () => { +const SendIntentButton = ({action, extras}: Props) => { + const [isOpeningIntent, setIsOpeningIntent] = React.useState(false); + + const handleIntent = async () => { + setIsOpeningIntent(true); try { - await Linking.sendIntent(this.props.action, this.props.extras); + await Linking.sendIntent(action, extras); } catch (e) { ToastAndroid.show(e.message, ToastAndroid.LONG); + } finally { + setIsOpeningIntent(false); } }; - render() { - return ( - - - {this.props.action} - - - ); - } -} + return ( + + + + {isOpeningIntent ? `Opening ${action}...` : action} + + + + ); +}; class IntentAndroidExample extends React.Component { render() { @@ -100,12 +105,15 @@ class IntentAndroidExample extends React.Component { - Next one will crash if Facebook app is not installed. + Next one will throw an exception if Facebook app is not installed.