Open source IntentAndroid
Summary: Move the code to the github folder, add more docs and improve the example. We might want to merge this with `LinkingIOS` later (it has the same functionality plus support for deep links) but want to see how people use the `IntentAndroid` API first (and what other methods we should add) to have more data points. public Reviewed By: lexs Differential Revision: D2646936 fb-gh-sync-id: 751f35784d387efcd031f9b458821cdfde048a54
This commit is contained in:
parent
d5209a0829
commit
ab7b3b2dea
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* The examples provided by Facebook are for non-commercial testing and
|
||||||
|
* evaluation purposes only.
|
||||||
|
*
|
||||||
|
* Facebook reserves all rights not expressly granted.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react-native');
|
||||||
|
var {
|
||||||
|
IntentAndroid,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TouchableNativeFeedback,
|
||||||
|
View,
|
||||||
|
} = React;
|
||||||
|
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||||
|
|
||||||
|
var OpenURLButton = React.createClass({
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
url: React.PropTypes.string,
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick: function() {
|
||||||
|
IntentAndroid.canOpenURL(this.props.url, (supported) => {
|
||||||
|
if (supported) {
|
||||||
|
IntentAndroid.openURL(this.props.url);
|
||||||
|
} else {
|
||||||
|
console.log('Don\'t know how to open URI: ' + this.props.url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<TouchableNativeFeedback
|
||||||
|
onPress={this.handleClick}>
|
||||||
|
<View style={styles.button}>
|
||||||
|
<Text style={styles.text}>Open {this.props.url}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableNativeFeedback>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var IntentAndroidExample = React.createClass({
|
||||||
|
|
||||||
|
statics: {
|
||||||
|
title: 'IntentAndroid',
|
||||||
|
description: 'Shows how to use Android Intents to open URLs.',
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<UIExplorerBlock title="Open external URLs">
|
||||||
|
<OpenURLButton url={'https://www.facebook.com'} />
|
||||||
|
<OpenURLButton url={'http://www.facebook.com'} />
|
||||||
|
<OpenURLButton url={'http://facebook.com'} />
|
||||||
|
<OpenURLButton url={'geo:37.484847,-122.148386'} />
|
||||||
|
</UIExplorerBlock>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
padding: 10,
|
||||||
|
paddingTop: 30,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: '#3B5998',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = IntentAndroidExample;
|
|
@ -38,6 +38,7 @@ var COMPONENTS = [
|
||||||
var APIS = [
|
var APIS = [
|
||||||
require('./AccessibilityAndroidExample.android'),
|
require('./AccessibilityAndroidExample.android'),
|
||||||
require('./BorderExample'),
|
require('./BorderExample'),
|
||||||
|
require('./IntentAndroidExample.android'),
|
||||||
require('./LayoutEventsExample'),
|
require('./LayoutEventsExample'),
|
||||||
require('./LayoutExample'),
|
require('./LayoutExample'),
|
||||||
require('./PanResponderExample'),
|
require('./PanResponderExample'),
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @providesModule IntentAndroid
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var IntentAndroidModule = require('NativeModules').IntentAndroid;
|
||||||
|
var invariant = require('invariant');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `IntentAndroid` gives you a general interface to handle external links.
|
||||||
|
*
|
||||||
|
* #### Opening external links
|
||||||
|
*
|
||||||
|
* To start the corresponding activity for a link (web URL, email, contact etc.), call
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* IntentAndroid.openURL(url)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If you want to check if any installed app can handle a given URL beforehand you can call
|
||||||
|
* ```
|
||||||
|
* IntentAndroid.canOpenURL(url, (supported) => {
|
||||||
|
* if (!supported) {
|
||||||
|
* console.log('Can\'t handle url: ' + url);
|
||||||
|
* } else {
|
||||||
|
* IntentAndroid.openURL(url);
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class IntentAndroid {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
* or the "choose application" dialog will be shown.
|
||||||
|
*
|
||||||
|
* You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact,
|
||||||
|
* or any other URL that can be opened with {@code Intent.ACTION_VIEW}.
|
||||||
|
*
|
||||||
|
* NOTE: This method will fail if the system doesn't know how to open the specified URL.
|
||||||
|
* If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first.
|
||||||
|
*
|
||||||
|
* NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
|
||||||
|
*/
|
||||||
|
static openURL(url: string) {
|
||||||
|
this._validateURL(url);
|
||||||
|
IntentAndroidModule.openURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether or not an installed app can handle a given URL.
|
||||||
|
*
|
||||||
|
* You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact,
|
||||||
|
* or any other URL that can be opened with {@code Intent.ACTION_VIEW}.
|
||||||
|
*
|
||||||
|
* NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
|
||||||
|
*
|
||||||
|
* @param URL the URL to open
|
||||||
|
*/
|
||||||
|
static canOpenURL(url: string, callback: Function) {
|
||||||
|
this._validateURL(url);
|
||||||
|
invariant(
|
||||||
|
typeof callback === 'function',
|
||||||
|
'A valid callback function is required'
|
||||||
|
);
|
||||||
|
IntentAndroidModule.canOpenURL(url, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _validateURL(url: string) {
|
||||||
|
invariant(
|
||||||
|
typeof url === 'string',
|
||||||
|
'Invalid URL: should be a string. Was: ' + url
|
||||||
|
);
|
||||||
|
invariant(
|
||||||
|
url,
|
||||||
|
'Invalid URL: cannot be empty'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = IntentAndroid;
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @providesModule IntentAndroid
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
openURI: function(url) {
|
||||||
|
console.error('IntentAndroid is not supported on iOS');
|
||||||
|
},
|
||||||
|
};
|
|
@ -23,7 +23,7 @@ var _initialURL = RCTLinkingManager &&
|
||||||
var DEVICE_NOTIF_EVENT = 'openURL';
|
var DEVICE_NOTIF_EVENT = 'openURL';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `LinkingIOS` gives you a general interface to interact with both, incoming
|
* `LinkingIOS` gives you a general interface to interact with both incoming
|
||||||
* and outgoing app links.
|
* and outgoing app links.
|
||||||
*
|
*
|
||||||
* ### Basic Usage
|
* ### Basic Usage
|
||||||
|
@ -65,13 +65,13 @@ var DEVICE_NOTIF_EVENT = 'openURL';
|
||||||
*
|
*
|
||||||
* #### Triggering App links
|
* #### Triggering App links
|
||||||
*
|
*
|
||||||
* To trigger an app link (browser, email or custom schemas) you call
|
* To trigger an app link (browser, email or custom schemas), call
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* LinkingIOS.openURL(url)
|
* LinkingIOS.openURL(url)
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* If you want to check if any installed app can handle a given url beforehand you can call
|
* If you want to check if any installed app can handle a given URL beforehand you can call
|
||||||
* ```
|
* ```
|
||||||
* LinkingIOS.canOpenURL(url, (supported) => {
|
* LinkingIOS.canOpenURL(url, (supported) => {
|
||||||
* if (!supported) {
|
* if (!supported) {
|
||||||
|
@ -127,7 +127,7 @@ class LinkingIOS {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether or not an installed app can handle a given `url`
|
* Determine whether or not an installed app can handle a given URL.
|
||||||
* The callback function will be called with `bool supported` as the only argument
|
* The callback function will be called with `bool supported` as the only argument
|
||||||
*
|
*
|
||||||
* NOTE: As of iOS 9, your app needs to provide a `LSApplicationQueriesSchemes` key
|
* NOTE: As of iOS 9, your app needs to provide a `LSApplicationQueriesSchemes` key
|
||||||
|
|
|
@ -66,6 +66,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||||
Dimensions: require('Dimensions'),
|
Dimensions: require('Dimensions'),
|
||||||
Easing: require('Easing'),
|
Easing: require('Easing'),
|
||||||
ImagePickerIOS: require('ImagePickerIOS'),
|
ImagePickerIOS: require('ImagePickerIOS'),
|
||||||
|
IntentAndroid: require('IntentAndroid'),
|
||||||
InteractionManager: require('InteractionManager'),
|
InteractionManager: require('InteractionManager'),
|
||||||
LayoutAnimation: require('LayoutAnimation'),
|
LayoutAnimation: require('LayoutAnimation'),
|
||||||
LinkingIOS: require('LinkingIOS'),
|
LinkingIOS: require('LinkingIOS'),
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.react.modules.intent;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.Callback;
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.bridge.ReactContext;
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intent module. Launch other activities or open URLs.
|
||||||
|
*/
|
||||||
|
public class IntentModule extends ReactContextBaseJavaModule {
|
||||||
|
|
||||||
|
public IntentModule(ReactApplicationContext reactContext) {
|
||||||
|
super(reactContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "IntentAndroid";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
* or the "choose application" dialog will be shown.
|
||||||
|
*
|
||||||
|
* @param URL the URL to open
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void openURL(String url) {
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
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.
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
getReactApplicationContext().startActivity(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JSApplicationIllegalArgumentException(
|
||||||
|
"Could not open URL '" + url + "': " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether or not an installed app can handle a given URL.
|
||||||
|
*
|
||||||
|
* @param URL the URL to open
|
||||||
|
* @param promise a promise that is always resolved with a boolean argument
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void canOpenURL(String url, Callback callback) {
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
throw new JSApplicationIllegalArgumentException("Invalid URL: " + url);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
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.
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
boolean canOpen =
|
||||||
|
intent.resolveActivity(this.getReactApplicationContext().getPackageManager()) != null;
|
||||||
|
callback.invoke(canOpen);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JSApplicationIllegalArgumentException(
|
||||||
|
"Could not check if URL '" + url + "' can be opened: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import com.facebook.react.bridge.JavaScriptModule;
|
||||||
import com.facebook.react.bridge.NativeModule;
|
import com.facebook.react.bridge.NativeModule;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.modules.fresco.FrescoModule;
|
import com.facebook.react.modules.fresco.FrescoModule;
|
||||||
|
import com.facebook.react.modules.intent.IntentModule;
|
||||||
import com.facebook.react.modules.network.NetworkingModule;
|
import com.facebook.react.modules.network.NetworkingModule;
|
||||||
import com.facebook.react.modules.storage.AsyncStorageModule;
|
import com.facebook.react.modules.storage.AsyncStorageModule;
|
||||||
import com.facebook.react.modules.toast.ToastModule;
|
import com.facebook.react.modules.toast.ToastModule;
|
||||||
|
@ -47,6 +48,7 @@ public class MainReactPackage implements ReactPackage {
|
||||||
return Arrays.<NativeModule>asList(
|
return Arrays.<NativeModule>asList(
|
||||||
new AsyncStorageModule(reactContext),
|
new AsyncStorageModule(reactContext),
|
||||||
new FrescoModule(reactContext),
|
new FrescoModule(reactContext),
|
||||||
|
new IntentModule(reactContext),
|
||||||
new NetworkingModule(reactContext),
|
new NetworkingModule(reactContext),
|
||||||
new WebSocketModule(reactContext),
|
new WebSocketModule(reactContext),
|
||||||
new ToastModule(reactContext));
|
new ToastModule(reactContext));
|
||||||
|
|
Loading…
Reference in New Issue