diff --git a/Libraries/Linking/Linking.js b/Libraries/Linking/Linking.js index 455de7ec75..0060e3ce26 100644 --- a/Libraries/Linking/Linking.js +++ b/Libraries/Linking/Linking.js @@ -44,13 +44,24 @@ const LinkingManager = Platform.OS === 'android' ? * NOTE: For instructions on how to add support for deep linking on Android, * refer to [Enabling Deep Links for App Content - Add Intent Filters for Your Deep Links](http://developer.android.com/training/app-indexing/deep-linking.html#adding-filters). * + * If you wish to receive the intent in an existing instance of MainActivity, + * you may set the `launchMode` of MainActivity to `singleTask` in + * `AndroidManifest.xml`. See [``](http://developer.android.com/guide/topics/manifest/activity-element.html) + * documentation for more information. + * + * ``` + * + * ``` + * * NOTE: On iOS you'll need to link `RCTLinking` to your project by following * the steps described [here](docs/linking-libraries-ios.html#manual-linking). * In case you also want to listen to incoming app links during your app's * execution you'll need to add the following lines to you `*AppDelegate.m`: * * ``` - *#import "RCTLinkingManager.h" + * #import "RCTLinkingManager.h" * * - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url * sourceApplication:(NSString *)sourceApplication annotation:(id)annotation @@ -84,8 +95,6 @@ const LinkingManager = Platform.OS === 'android' ? * console.log(event.url); * } * ``` - * Note that this is only supported on iOS. - * * #### Opening external links * * To start the corresponding activity for a link (web URL, email, contact etc.), call @@ -114,28 +123,16 @@ class Linking extends NativeEventEmitter { /** * Add a handler to Linking changes by listening to the `url` event type * and providing the handler - * - * @platform ios */ addEventListener(type: string, handler: Function) { - if (Platform.OS === 'android') { - console.warn('Linking.addEventListener is not supported on Android'); - } else { - this.addListener(type, handler); - } + this.addListener(type, handler); } /** * Remove a handler by passing the `url` event type and the handler - * - * @platform ios */ removeEventListener(type: string, handler: Function ) { - if (Platform.OS === 'android') { - console.warn('Linking.removeEventListener is not supported on Android'); - } else { - this.removeListener(type, handler); - } + this.removeListener(type, handler); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java b/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java index b6bdfb0b5b..4befbd3df7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java @@ -227,4 +227,13 @@ public abstract class ReactActivity extends Activity implements DefaultHardwareB public void invokeDefaultOnBackPressed() { super.onBackPressed(); } + + @Override + public void onNewIntent(Intent intent) { + if (mReactInstanceManager != null) { + mReactInstanceManager.onNewIntent(intent); + } else { + super.onNewIntent(intent); + } + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index f6db4ae351..a000a7ebd8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -88,6 +88,11 @@ public abstract class ReactInstanceManager { */ public abstract void onBackPressed(); + /** + * This method will give JS the opportunity to receive intents via Linking. + */ + public abstract void onNewIntent(Intent intent); + /** * Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do * any necessary cleanup. diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java index b347a81bfb..0f5aa1af34 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; +import android.net.Uri; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; @@ -466,6 +467,22 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START } } + @Override + public void onNewIntent(Intent intent) { + if (mCurrentReactContext == null) { + FLog.w(ReactConstants.TAG, "Instance detached from instance manager"); + } else { + String action = intent.getAction(); + Uri uri = intent.getData(); + + if (Intent.ACTION_VIEW.equals(action) && uri != null) { + DeviceEventManagerModule deviceEventManagerModule = + Assertions.assertNotNull(mCurrentReactContext).getNativeModule(DeviceEventManagerModule.class); + deviceEventManagerModule.emitNewIntentReceived(uri); + } + } + } + private void toggleElementInspector() { if (mCurrentReactContext != null) { mCurrentReactContext diff --git a/ReactAndroid/src/main/java/com/facebook/react/XReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/XReactInstanceManagerImpl.java index cdc96efede..b0afbd5366 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/XReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/XReactInstanceManagerImpl.java @@ -23,6 +23,7 @@ import android.app.Activity; import android.app.Application; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; @@ -57,6 +58,7 @@ import com.facebook.react.devsupport.DevServerHelper; import com.facebook.react.devsupport.DevSupportManager; import com.facebook.react.devsupport.DevSupportManagerFactory; import com.facebook.react.devsupport.ReactInstanceDevCommandsHandler; +import com.facebook.react.devsupport.RedBoxHandler; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.modules.debug.DeveloperSettings; @@ -67,10 +69,7 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.soloader.SoLoader; import com.facebook.systrace.Systrace; -import com.facebook.react.devsupport.RedBoxHandler; -import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_JS_MODULE_CONFIG_END; -import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_JS_MODULE_CONFIG_START; import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END; import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_END; @@ -476,6 +475,22 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; } } + @Override + public void onNewIntent(Intent intent) { + if (mCurrentReactContext == null) { + FLog.w(ReactConstants.TAG, "Instance detached from instance manager"); + } else { + String action = intent.getAction(); + Uri uri = intent.getData(); + + if (Intent.ACTION_VIEW.equals(action) && uri != null) { + DeviceEventManagerModule deviceEventManagerModule = + Assertions.assertNotNull(mCurrentReactContext).getNativeModule(DeviceEventManagerModule.class); + deviceEventManagerModule.emitNewIntentReceived(uri); + } + } + } + private void toggleElementInspector() { if (mCurrentReactContext != null) { mCurrentReactContext diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.java index 37a34283c8..2ac4f45024 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.java @@ -11,6 +11,8 @@ package com.facebook.react.modules.core; import javax.annotation.Nullable; +import android.net.Uri; + import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -52,6 +54,15 @@ public class DeviceEventManagerModule extends ReactContextBaseJavaModule { .emit("hardwareBackPress", null); } + /** + * Sends an event to the JS instance that a new intent was received. + */ + public void emitNewIntentReceived(Uri uri) { + getReactApplicationContext() + .getJSModule(RCTDeviceEventEmitter.class) + .emit("url", uri.toString()); + } + /** * Invokes the default back handler for the host of this catalyst instance. This should be invoked * if JS does not want to handle the back press itself.