├── README.md └── assets └── exone.png /README.md: -------------------------------------------------------------------------------- 1 | # Universal Linking For React-Native with Rails API, and Deep Linking Android 2 | Just a tutorial on how to set up Universal Linking for iOS with a Rails server, and Deep Linking on an Android device. 3 | 4 | ## iOS 5 | - Universal Linking allows users to click on a link from a text message or email and your app will `magically` launch 6 | 7 | - You can pass information in the url of link so your app can launch to a specific screen and fetch the proper data 8 | 9 | - The documentation from Apple is not the best, I will explain in extreme detail how to accomplish this with `React-Native` and a `Rails` server 10 | 11 | ### Requirements 12 | 13 | 1. You have to set up your server 14 | 2. Your server must use HTTPS or else the set-up sucks and and these instructions will not work for you 15 | 2. The links you provide to users should go to a valid web page should they not have the app installed. It's a fallback and good UX. 16 | 3. You have to have a developer account with iTunes to test on your device 17 | 4. You have to configure your app to handle the link/parse it for pertinent information. 18 | 19 | #### Universal Linking does not support iOS < 9. You want to support old versions of iOS, great...good for you. I hope you support old versions of IE as well... I do not support these old things. I also think everyone should always use flex-box...always...no exceptions :) 20 | 21 | ### Server Configuration 22 | 23 | This is where the Apple doc's didn't really help that much. I use Rails servers and the set-up instructions weren't the best for my use case. 24 | 25 |
26 | #### Your link should go to a valid web page. 27 | 28 | - for instance the link `https://brewcards.herokuapp.com/bars/1` goes to a web page. Should the user click the link and the app is not installed, then Safari will open to a web page. In this example I am going to extract the `1` from the url and re-direct the user to the proper app screen and fetch data. 29 | 30 | 31 | #### Your server has to have a route that is defined as a `get` with the path `/apple-app-site-association` *you can not change this name* 32 | 33 | - Rails example `get '/apple-app-site-association' => 'whatever#whatever_method'` 34 | 35 | 36 | #### When a request is made to that path, you must return the proper file with the proper configuration. 37 | - Apple docs do a great job explaining this file configuration. Click here to see how to structure your file 38 | 39 | #### Apple says the the file has to have a certain name and certain location. 40 | - This is not true. You can name the file whatever the eff you want as long as you return it when the request is made to the `apple-app-site-association` url and there is no extension on the file. It may be JSON format, just don't put .anything as the extension 41 | 42 | - In Rails, I put the file in the `public` directory 43 | 44 | 45 | ## My controller in Rails 46 | 47 | 48 | ```ruby 49 | 50 | class WhateverController < ApplicationController 51 | 52 | def whatever_method 53 | send_file "#{Rails.root}/public/whatever_I_named_my_apple_association_file_with_no_extension", {:type => "application/json"} 54 | end 55 | 56 | end 57 | 58 | ``` 59 | 60 | # Server Configuration Done 61 | 62 | # App Configuration 63 | 64 | 1. In X-Code turn on Associated Domains 65 | 2. Add your domain. 66 | 3. Make sure to prefix the domain with `applinks:` in place of `https://` 67 | 68 | ![screenshot](./assets/exone.png) 69 | 70 | ### Add RCTLinking to your project 71 | Do what is says in the link about. **Make sure to add the library to the header search path as recursive** 72 | 73 | 74 | ### Modify App Delegate 75 | 76 | ```objc 77 | #import "RCTLinkingManager.h" // import 78 | 79 | // ADD THIS METHOD 80 | 81 | - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity 82 | restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler 83 | { 84 | return [RCTLinkingManager application:application 85 | continueUserActivity:userActivity 86 | restorationHandler:restorationHandler]; 87 | } 88 | 89 | 90 | ``` 91 | 92 | ### Handle the links in your app. 93 | 94 | - There are two scenarios you must account for. 95 | 1. Your app is closed and gets opened via the `Universal Linking` we have enabled or `Deep Linking Android` 96 | 2. Your app is running in the background and is `woke up` from the `Universal Linking` or `Deep Linking` 97 | 98 | In your app's Navigator, add some methods to handle the Universal Linking. 99 | 100 | ```js 101 | 102 | componentDidMount(){ 103 | // this handles the case where the app is closed and is launched via Universal Linking. 104 | Linking.getInitialURL() 105 | .then((url) => { 106 | if (url) { 107 | // Alert.alert('GET INIT URL','initial url ' + url) 108 | this.resetStackToProperRoute(url) 109 | } 110 | }) 111 | .catch((e) => {}) 112 | 113 | // This listener handles the case where the app is woken up from the Universal or Deep Linking 114 | Linking.addEventListener('url', this.appWokeUp); 115 | } 116 | 117 | componentWillUnmount(){ 118 | // Remove the listener 119 | Linking.removeEventListener('url', this.appWokeUp); 120 | } 121 | 122 | appWokeUp = (event) => { 123 | // this handles the use case where the app is running in the background and is activated by the listener... 124 | // Alert.alert('Linking Listener','url ' + event.url) 125 | this.resetStackToProperRoute(event.url) 126 | } 127 | 128 | resetStackToProperRoute = (url) => { 129 | // grab the trailing portion of the url so we can use that data to fetch proper information from the server 130 | let trailing = url.slice(url.lastIndexOf('/') + 1,url.length) 131 | // reset the stack, let your properly coded application handle everything and populate everthing. 132 | this.props.resetStack([ BarsMain, { ...BarDetail, id:parseInt(trailing) } ]) 133 | } 134 | ``` 135 | 136 | 137 | # Universal Linking....Boom. 138 | 139 | # Android 140 | 141 | Android is a little easier...no server configuration 142 | 143 | 1. Add an `` to you `AndroidManifest.xml` 144 | 2. Describe what url scheme you want handled. 145 | 3. Profit? 146 | 147 | ```xml 148 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 172 | 173 | 174 | 175 | ``` 176 | 177 | The `` attribute is the important stuff. It defines what url schemes to intercept read about it here 178 | 179 | # Deep Linking...Boom. 180 | -------------------------------------------------------------------------------- /assets/exone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parkerdan/React-Native-Rails-Universal-Linking/2a4cdb0ae9a318d468a7b7ae0915e13abfbdf1b1/assets/exone.png --------------------------------------------------------------------------------