React-Native Universal Linking iOS, Deep Linking Android with a Rails Server

Universal Linking and Deep Linking allow your app to launch from a link within an email or text message, if your app is installed on the users device

Dan Parker
3 min readFeb 26, 2017
  • You can pass information in the url of link so your app can launch to a specific screen and fetch the proper data.
  • Set up is fairly easy with a Rails server using HTTPS, and if you only support iOS 9+.
  • If you want to support iOS versions less than 9, or use HTTP…this isn’t for you…

Requirements

  • Access to server.
  • Developer account with Apple/Google Play.
  • Links that actually go to a webpage should the user not have the app installed…it’s just good UX.

Rails Server Configuration

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.

Your server must have a route with a get method at the path apple-app-site-association. Rails Example:

get '/apple-app-site-association' => 'whatever#whatever_method'

When a request is made to that url, you must return a file with the proper configuration. Apple docs do a great job of explaining this.

  • Apple Docs say the file has to have a certain name and location…this is not true.
  • You can name the file whatever you want as long as you return it when a request is made to the above URL.
  • Do not put an extension on the file.
  • Do not put an extension on the file.
  • Put the file in the public directory…

Rails Controller

class WhateverController < ApplicationController

def whatever_method
send_file "#{Rails.root}/public/whatever_I_named_my_apple_association_file_with_no_extension", {:type => "application/json"}
end

end

Server configuration done

App Configuration…time to play with X-Code

  • In X-Code turn on Associated Domains.
  • Add your Domain.
  • Make sure to prefix the domain with applinks: in place of https://

Add RCTLinking to your project

Do what is says in the link about. Make sure to add the library to the header search path as recursive

Modify App Delegate:

#import "RCTLinkingManager.h" // import

// ADD THIS METHOD

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}

Handle the links in your app

There are two scenarios you must account for:

1: Your app is closed and gets opened via the Universal Linking or Deep Linking Android .

2: Your app is running in the background and is woken up from the Universal Linking or Deep Linking .

In your app’s Top-Most Navigator, add some methods to handle the Links.

componentDidMount(){
// this handles the case where the app is closed and is launched via Universal Linking.
Linking.getInitialURL()
.then((url) => {
if (url) {
// Alert.alert('GET INIT URL','initial url ' + url)
this.resetStackToProperRoute(url)
}
})
.catch((e) => {})

// This listener handles the case where the app is woken up from the Universal or Deep Linking
Linking.addEventListener('url', this.appWokeUp);
}

componentWillUnmount(){
// Remove the listener
Linking.removeEventListener('url', this.appWokeUp);
}

appWokeUp = (event) => {
// this handles the use case where the app is running in the background and is activated by the listener...
// Alert.alert('Linking Listener','url ' + event.url)
this.resetStackToProperRoute(event.url)
}

resetStackToProperRoute = (url) => {
// Do Whatever you need to do within your app to redirect users to the proper route
}

Android Set-Up

Android is a pretty easy set-up in comparison to iOS, only three steps…

1: Add an <intent-filter> to you AndroidManifest.xml

2: Describe what url scheme you want handled.

3: Profit??

<!-- Add an Intent filter within your       
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">

...rest of stuffs

....the intent filter below...
</activity>
-->


<!-- This is how you structure your Intent filter -->
<intent-filter>
<!-- This is just configuration -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- This is the important stuff. Link to Android docs below -->
<data android:scheme="https"
android:host="brewcards.herokuapp.com"
android:pathPrefix="/bars" />

</intent-filter>

The <data /> attribute is the important stuff. It defines what url schemes to intercept read about it here

--

--