2016-01-26 22:34:00 +00:00
/ * *
* 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 Linking
* @ flow
* /
'use strict' ;
2016-05-27 17:14:12 +00:00
const NativeEventEmitter = require ( 'NativeEventEmitter' ) ;
const NativeModules = require ( 'NativeModules' ) ;
2016-01-26 22:34:00 +00:00
const Platform = require ( 'Platform' ) ;
2016-05-27 17:14:12 +00:00
const invariant = require ( 'fbjs/lib/invariant' ) ;
2016-01-26 22:34:00 +00:00
2016-05-27 17:14:12 +00:00
const LinkingManager = Platform . OS === 'android' ?
NativeModules . IntentAndroid : NativeModules . LinkingManager ;
2016-01-26 22:34:00 +00:00
/ * *
2017-04-26 14:09:36 +00:00
* < div class = "banner-crna-ejected" >
* < h3 > Projects with Native Code Only < / h 3 >
* < p >
* This section only applies to projects made with < code > react - native init < / c o d e >
* or to those made with Create React Native App which have since ejected . For
* more information about ejecting , please see
* the < a href = "https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md" target = "_blank" > guide < / a > o n
* the Create React Native App repository .
* < / p >
* < / d i v >
*
2016-01-26 22:34:00 +00:00
* ` Linking ` gives you a general interface to interact with both incoming
* and outgoing app 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 ( ) {
2017-03-21 23:21:46 +00:00
* Linking . getInitialURL ( ) . then ( ( url ) => {
2016-01-26 22:34:00 +00:00
* if ( url ) {
* console . log ( 'Initial url is: ' + url ) ;
* }
* } ) . catch ( err => console . error ( 'An error occurred' , err ) ) ;
* }
* ` ` `
*
* NOTE : For instructions on how to add support for deep linking on Android ,
2016-06-01 07:54:40 +00:00
* 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).
2016-01-26 22:34:00 +00:00
*
2016-06-06 01:46:32 +00:00
* 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 [ ` <activity> ` ] ( http : //developer.android.com/guide/topics/manifest/activity-element.html)
* documentation for more information .
2016-08-09 13:32:41 +00:00
*
2016-06-06 01:46:32 +00:00
* ` ` `
* < activity
* android : name = ".MainActivity"
* android : launchMode = "singleTask" >
* ` ` `
2016-08-09 13:32:41 +00:00
*
2017-05-17 00:51:20 +00:00
* NOTE : On iOS , you ' ll need to link ` RCTLinking ` to your project by following
2016-04-21 02:22:02 +00:00
* the steps described [ here ] ( docs / linking - libraries - ios . html # manual - linking ) .
2017-05-17 00:51:20 +00:00
* If you also want to listen to incoming app links during your app ' s
* execution , you ' ll need to add the following lines to your ` *AppDelegate.m ` :
2016-01-26 22:34:00 +00:00
*
* ` ` `
2017-05-25 18:24:07 +00:00
* // iOS 9.x or newer
2017-05-17 00:51:20 +00:00
* # import < React / RCTLinkingManager . h >
2017-05-25 18:24:07 +00:00
*
2017-05-17 00:51:20 +00:00
* - ( BOOL ) application : ( UIApplication * ) application
* openURL : ( NSURL * ) url
* options : ( NSDictionary < UIApplicationOpenURLOptionsKey , id > * ) options
* {
2017-05-25 18:24:07 +00:00
* return [ RCTLinkingManager application : app openURL : url options : options ] ;
2017-05-17 00:51:20 +00:00
* }
* ` ` `
*
2017-05-25 18:24:07 +00:00
* If you ' re targeting iOS 8. x or older , you can use the following code instead :
2017-05-17 00:51:20 +00:00
*
* ` ` `
2017-05-25 18:24:07 +00:00
* // iOS 8.x or older
2017-03-06 08:36:45 +00:00
* # import < React / RCTLinkingManager . h >
2016-02-10 16:37:58 +00:00
*
2016-01-26 22:34:00 +00:00
* - ( BOOL ) application : ( UIApplication * ) application openURL : ( NSURL * ) url
* sourceApplication : ( NSString * ) sourceApplication annotation : ( id ) annotation
* {
2016-02-10 16:37:58 +00:00
* return [ RCTLinkingManager application : application openURL : url
2017-05-25 18:24:07 +00:00
* sourceApplication : sourceApplication annotation : annotation ] ;
2016-01-26 22:34:00 +00:00
* }
2017-05-17 00:51:20 +00:00
* ` ` `
2017-05-25 18:24:07 +00:00
*
*
* // If your app is using [Universal Links](https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html),
2017-05-17 00:51:20 +00:00
* you ' ll need to add the following code as well :
2017-05-25 18:24:07 +00:00
*
2017-05-17 00:51:20 +00:00
* ` ` `
2016-01-26 22:34:00 +00:00
* - ( BOOL ) application : ( UIApplication * ) application continueUserActivity : ( NSUserActivity * ) userActivity
* restorationHandler : ( void ( ^ ) ( NSArray * _Nullable ) ) restorationHandler
* {
2016-02-10 16:37:58 +00:00
* return [ RCTLinkingManager application : application
2016-01-26 22:34:00 +00:00
* continueUserActivity : userActivity
* restorationHandler : restorationHandler ] ;
* }
* ` ` `
*
* And then on your React component you ' ll be able to listen to the events on
* ` Linking ` as follows
*
* ` ` `
* componentDidMount ( ) {
* Linking . addEventListener ( 'url' , this . _handleOpenURL ) ;
* } ,
* componentWillUnmount ( ) {
* Linking . removeEventListener ( 'url' , this . _handleOpenURL ) ;
* } ,
* _handleOpenURL ( event ) {
* console . log ( event . url ) ;
* }
* ` ` `
* # # # # Opening external links
*
* To start the corresponding activity for a link ( web URL , email , contact etc . ) , call
*
* ` ` `
* Linking . openURL ( url ) . catch ( err => console . error ( 'An error occurred' , err ) ) ;
* ` ` `
*
* If you want to check if any installed app can handle a given URL beforehand you can call
* ` ` `
* Linking . canOpenURL ( url ) . then ( supported => {
* if ( ! supported ) {
* console . log ( 'Can\'t handle url: ' + url ) ;
* } else {
* return Linking . openURL ( url ) ;
* }
* } ) . catch ( err => console . error ( 'An error occurred' , err ) ) ;
* ` ` `
* /
2016-05-27 17:14:12 +00:00
class Linking extends NativeEventEmitter {
2016-08-09 13:32:41 +00:00
2016-05-27 17:14:12 +00:00
constructor ( ) {
2016-08-09 13:32:41 +00:00
super ( LinkingManager ) ;
2016-05-27 17:14:12 +00:00
}
2016-08-09 13:32:41 +00:00
2016-01-26 22:34:00 +00:00
/ * *
* Add a handler to Linking changes by listening to the ` url ` event type
* and providing the handler
* /
2016-05-27 17:14:12 +00:00
addEventListener ( type : string , handler : Function ) {
2016-06-06 01:46:32 +00:00
this . addListener ( type , handler ) ;
2016-01-26 22:34:00 +00:00
}
/ * *
* Remove a handler by passing the ` url ` event type and the handler
* /
2016-05-27 17:14:12 +00:00
removeEventListener ( type : string , handler : Function ) {
2016-06-06 01:46:32 +00:00
this . removeListener ( type , handler ) ;
2016-01-26 22:34:00 +00:00
}
/ * *
* Try to open the given ` url ` with any of the installed apps .
*
2017-03-31 17:35:52 +00:00
* You can use other URLs , like a location ( e . g . "geo:37.484847,-122.148386" on Android
* or "http://maps.apple.com/?ll=37.484847,-122.148386" on iOS ) , a contact ,
2016-01-26 22:34:00 +00:00
* or any other URL that can be opened with the installed apps .
*
2017-04-28 10:51:50 +00:00
* The method returns a ` Promise ` object . If the user confirms the open dialog or the
* url automatically opens , the promise is resolved . If the user cancels the open dialog
* or there are no registered applications for the url , the promise is rejected .
*
2016-01-26 22:34:00 +00:00
* 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 !
* /
2016-06-03 09:37:43 +00:00
openURL ( url : string ) : Promise < any > {
2016-01-26 22:34:00 +00:00
this . _validateURL ( url ) ;
return LinkingManager . openURL ( url ) ;
}
/ * *
* Determine whether or not an installed app can handle a given URL .
*
* NOTE : For web URLs , the protocol ( "http://" , "https://" ) must be set accordingly !
*
* NOTE : As of iOS 9 , your app needs to provide the ` LSApplicationQueriesSchemes ` key
2016-05-27 17:14:12 +00:00
* inside ` Info.plist ` or canOpenURL will always return false .
2016-01-26 22:34:00 +00:00
*
* @ param URL the URL to open
* /
2016-05-27 17:14:12 +00:00
canOpenURL ( url : string ) : Promise < boolean > {
2016-01-26 22:34:00 +00:00
this . _validateURL ( url ) ;
return LinkingManager . canOpenURL ( url ) ;
}
/ * *
2016-05-27 17:14:12 +00:00
* If the app launch was triggered by an app link ,
2016-01-26 22:34:00 +00:00
* it will give the link url , otherwise it will give ` null `
*
* NOTE : To support deep linking on Android , refer http : //developer.android.com/training/app-indexing/deep-linking.html#handling-intents
* /
2016-05-27 17:14:12 +00:00
getInitialURL ( ) : Promise < ? string > {
return LinkingManager . getInitialURL ( ) ;
2016-01-26 22:34:00 +00:00
}
2016-05-27 17:14:12 +00:00
_validateURL ( url : string ) {
2016-01-26 22:34:00 +00:00
invariant (
typeof url === 'string' ,
'Invalid URL: should be a string. Was: ' + url
) ;
invariant (
url ,
'Invalid URL: cannot be empty'
) ;
}
}
2016-05-27 17:14:12 +00:00
module . exports = new Linking ( ) ;