Add deep linking support to IntentAndroid
Summary: Add a method to handle URLs registered to the app, ```js IntentAndroid.getInitialURL(url => { if (url) { // do stuff } }); ``` Refer - http://developer.android.com/training/app-indexing/deep-linking.html#adding-filters The API cannot be same as the iOS API (i.e. as a constant), as the activity is not availble at the time of module initialization. Moreover, multiple activties can share the same bridge instance, and the activity itself is not a constant. Hence the initialURL can change. Closes https://github.com/facebook/react-native/pull/4320 Reviewed By: svcscm Differential Revision: D2759667 Pulled By: foghina fb-gh-sync-id: b725231ae1401fa5565d444eee5a30d303e263ae
This commit is contained in:
parent
cf94a9ea95
commit
eb188c8d98
|
@ -16,6 +16,26 @@ var invariant = require('invariant');
|
||||||
/**
|
/**
|
||||||
* `IntentAndroid` gives you a general interface to handle external links.
|
* `IntentAndroid` gives you a general interface to handle external links.
|
||||||
*
|
*
|
||||||
|
* ### Basic Usage
|
||||||
|
*
|
||||||
|
* #### Handling deep links
|
||||||
|
*
|
||||||
|
* If your app was launched from an external url registered to your app you can
|
||||||
|
* access and handle it from any component you want with
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* componentDidMount() {
|
||||||
|
* var url = IntentAndroid.getInitialURL(url => {
|
||||||
|
* if (url) {
|
||||||
|
* console.log('Initial url is: ' + url);
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* NOTE: For instructions on how to add support for deep linking,
|
||||||
|
* refer [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).
|
||||||
|
*
|
||||||
* #### Opening external links
|
* #### Opening external links
|
||||||
*
|
*
|
||||||
* To start the corresponding activity for a link (web URL, email, contact etc.), call
|
* To start the corresponding activity for a link (web URL, email, contact etc.), call
|
||||||
|
@ -75,6 +95,20 @@ class IntentAndroid {
|
||||||
IntentAndroidModule.canOpenURL(url, callback);
|
IntentAndroidModule.canOpenURL(url, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the app launch was triggered by an app link with {@code Intent.ACTION_VIEW},
|
||||||
|
* it will give the link url, otherwise it will give `null`
|
||||||
|
*
|
||||||
|
* Refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
|
||||||
|
*/
|
||||||
|
static getInitialURL(callback: Function) {
|
||||||
|
invariant(
|
||||||
|
typeof callback === 'function',
|
||||||
|
'A valid callback function is required'
|
||||||
|
);
|
||||||
|
IntentAndroidModule.getInitialURL(callback);
|
||||||
|
}
|
||||||
|
|
||||||
static _validateURL(url: string) {
|
static _validateURL(url: string) {
|
||||||
invariant(
|
invariant(
|
||||||
typeof url === 'string',
|
typeof url === 'string',
|
||||||
|
|
|
@ -9,15 +9,15 @@
|
||||||
|
|
||||||
package com.facebook.react.modules.intent;
|
package com.facebook.react.modules.intent;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.facebook.react.bridge.Callback;
|
import com.facebook.react.bridge.Callback;
|
||||||
|
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContext;
|
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intent module. Launch other activities or open URLs.
|
* Intent module. Launch other activities or open URLs.
|
||||||
|
@ -33,25 +33,58 @@ public class IntentModule extends ReactContextBaseJavaModule {
|
||||||
return "IntentAndroid";
|
return "IntentAndroid";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the URL the activity was started with
|
||||||
|
*
|
||||||
|
* @param callback a callback which is called with the initial URL
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void getInitialURL(Callback callback) {
|
||||||
|
try {
|
||||||
|
Activity currentActivity = getCurrentActivity();
|
||||||
|
String initialURL = null;
|
||||||
|
|
||||||
|
if (currentActivity != null) {
|
||||||
|
Intent intent = currentActivity.getIntent();
|
||||||
|
String action = intent.getAction();
|
||||||
|
Uri uri = intent.getData();
|
||||||
|
|
||||||
|
if (Intent.ACTION_VIEW.equals(action) && uri != null) {
|
||||||
|
initialURL = uri.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.invoke(initialURL);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JSApplicationIllegalArgumentException(
|
||||||
|
"Could not get the initial URL : " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a corresponding external activity for the given URL.
|
* Starts a corresponding external activity for the given URL.
|
||||||
*
|
*
|
||||||
* For example, if the URL is "https://www.facebook.com", the system browser will be opened,
|
* For example, if the URL is "https://www.facebook.com", the system browser will be opened,
|
||||||
* or the "choose application" dialog will be shown.
|
* or the "choose application" dialog will be shown.
|
||||||
*
|
*
|
||||||
* @param URL the URL to open
|
* @param url the URL to open
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void openURL(String url) {
|
public void openURL(String url) {
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Activity currentActivity = getCurrentActivity();
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||||
// We need Intent.FLAG_ACTIVITY_NEW_TASK since getReactApplicationContext() returns
|
|
||||||
// the ApplicationContext instead of the Activity context.
|
if (currentActivity != null) {
|
||||||
|
currentActivity.startActivity(intent);
|
||||||
|
} else {
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
getReactApplicationContext().startActivity(intent);
|
getReactApplicationContext().startActivity(intent);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new JSApplicationIllegalArgumentException(
|
throw new JSApplicationIllegalArgumentException(
|
||||||
"Could not open URL '" + url + "': " + e.getMessage());
|
"Could not open URL '" + url + "': " + e.getMessage());
|
||||||
|
@ -61,21 +94,22 @@ public class IntentModule extends ReactContextBaseJavaModule {
|
||||||
/**
|
/**
|
||||||
* Determine whether or not an installed app can handle a given URL.
|
* Determine whether or not an installed app can handle a given URL.
|
||||||
*
|
*
|
||||||
* @param URL the URL to open
|
* @param url the URL to open
|
||||||
* @param promise a promise that is always resolved with a boolean argument
|
* @param callback a callback that is always called with a boolean argument
|
||||||
*/
|
*/
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void canOpenURL(String url, Callback callback) {
|
public void canOpenURL(String url, Callback callback) {
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||||
// We need Intent.FLAG_ACTIVITY_NEW_TASK since getReactApplicationContext() returns
|
// We need Intent.FLAG_ACTIVITY_NEW_TASK since getReactApplicationContext() returns
|
||||||
// the ApplicationContext instead of the Activity context.
|
// the ApplicationContext instead of the Activity context.
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
boolean canOpen =
|
boolean canOpen =
|
||||||
intent.resolveActivity(this.getReactApplicationContext().getPackageManager()) != null;
|
intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null;
|
||||||
callback.invoke(canOpen);
|
callback.invoke(canOpen);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new JSApplicationIllegalArgumentException(
|
throw new JSApplicationIllegalArgumentException(
|
||||||
|
|
Loading…
Reference in New Issue