Matt’s Tidbits #103 — Launching an app from a URL

Matthew Groves
Nov 2 · 6 min read

This week’s tidbit will show you how to launch an app when a user clicks on a link. Last time, I wrote about debugging a view binding issue in Android.

Have you ever had an app launch on your mobile device when you click a link in an email, on a webpage, etc. and wondered how to do the same thing for your app? Wonder no more, because in this simple guide I will show you how to accomplish this!

Android

On Android, this can be accomplished by defining an <intent-filter> in your app’s AndroidManifest.xml.

Here’s a simple example:

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="matthew-b-groves.medium.com"
>
</intent-filter>

Doing something like this would cause any link that began with https://matthew-b-groves.medium.com (the URL for my Medium profile) to launch this app instead.

You can even define multiple <data> listings to allow multiple URL patterns to invoke your app. (Note that any possible combination of schemes/hosts that you have defined will match — even across <data> entries)

Depending on your desired behavior, you can even use something completely custom for the android:scheme, such as mattstidbits, and omit the android:host property entirely. This would allow any URL starting with mattstidbits:// to launch your app. However, this will only work if the user has your app is installed. If you want to direct the user to the Play Store listing for your app if they don’t have it installed, you’ll want to use an http or https scheme and a host/domain that you own. Then, you can follow these instructions to create a JSON file that you can embed on your website that will instruct browsers to redirect users to the Play Store listing page for your app.

If you want to have your app access information that’s embedded in the URL (so you can take them to a specific screen within the app), you’ll want to add something like the following to your application’s onCreate method:

val action: String? = intent?.action
val uri: Uri? = intent?.data

You can then verify that the action was Intent.ACTION_VIEW and grab the uri that was passed in and use the methods/properties of the Uri class to pull out information from the URI to help you handle the request.

It’s also a good idea to test your deep linking, which you can do on a simulator or physical device using the adb command, like this:

adb shell am start -d "your-deep-link-url" 

The Android developer documentation for implementing deep linking is really excellent, which you can find here: https://developer.android.com/training/app-links/deep-linking

iOS

Disclaimer: I am not an iOS developer by trade, so I can’t provide nearly the level of detail that I can for Android.

Apple appears to offer two different mechanisms for launching an app from a URL — URL Schemes and Universal Links.

  • URL Schemes are easier/faster to implement, but prompt the user for permission and don’t work if the app is not installed.
  • Universal Links require you to have control of the domain (much like Google’s App Links that I described above), so they require more work to set up, but they won’t prompt the user and allow you to provide a fallback URL if the user doesn’t have the app installed.

This article does a good job of explaining some of the differences: https://medium.com/wolox/ios-deep-linking-url-scheme-vs-universal-links-50abd3802f97

For now, let’s focus on URL Schemes, since that’s the approach I have worked with before. To set one up, all you have to do is specify the scheme in Xcode via the Info tab in your project’s settings. Note that unlike Android, iOS only lets you define the scheme (the part that comes before the :// in a URL). So, you could enter mattstidbits in the “URL Schemes” field, so any links beginning with mattstidbits:// would launch your app (if it’s installed).

In your Info.plist file this shows up under the CFBundleURLSchemes key.

If you want your app to access the information that’s stored in the URL, then you’ll need to handle this inside of your app delegate’s application() method. There’s a url argument that will contain the data.

As with Android, you can test these deep links by running the following terminal command:

xcrun simctl openurl booted "your-deep-link-url"

(Again, I don’t pretend to be an iOS developer, so please see the official documentation for how to do this.)

React Native

If you’ve been following my tidbits for a while, you probably wondered if I would touch on this — here’s how to do this in React Native!

React Native has two different setups — if you are using Expo, follow these instructions to specify the scheme you’d like to use within Expo’s JSON config.

However, if you are not using Expo, you generally need to follow the same steps above for iOS/Android to set up deep linking in your AndroidManifest.xml and Info.plist. To get this working in a React Native CLI project, you should follow these instructions to configure your project. Note that for iOS you’ll need to add some special code to your AppDelegate to make this work.

Note that both of these options assume you are using React Navigation for managing navigation within your app (which I highly recommend you do!)

If you want to be able to actually do something with the URL (and not just simply invoke the app), you will need to configure a linking object and assign that to your NavigationContainer.

The linking object is a little funky, in that it’s like a copy of your navigation graph. It gives you the power to map URL parameters to internal route names/paths, but does require you to match your app’s navigation graph precisely.

For example, you might set this up as follows:

const config = {
screens: {
Tidbit: 'post/:id',
Profile: 'user',
},
};

const linking = {
prefixes: ['https://matthew-b-groves.medium.com'],
config,
};

function App() {
return (
<NavigationContainer linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Tidbit" component={PostDetailScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}

Where this can start to get a little tedious is if you have nested navigators (which you likely do), your linking object will need to also match that nesting.

For more details, see this article.

To test the link with an Expo project, run the following command (substituting ios in place of android below if you’d like to change what platform you’re targeting):

npx uri-scheme open "your-deep-link-url://127.0.0.1:19000" --android

For a non-Expo project, you can test the deep linking via the native iOS/Android commands described in the sections above.

Overall strategies

What can we take away from this?

  • Deep linking on both iOS/Android/React Native provides sophisticated functionality.
  • In nearly all cases, you probably want your links to have the same format across iOS/Android for consistency’s sake (having links work on either platform seamlessly)
  • I would recommend starting with the simplest approach and building from there — there can be a lot of red tape to work through to get files changed in your company’s/project’s website in order to use the more sophisticated App Links (Android) or Universal Links (iOS), so if you’re able to get by with the more basic deep linking/URL schemes (where you don’t need to modify a website), then start with that.

Interested in working with me in the awesome Digital Products team here at Accenture? We have an opening:

Do you have other deep linking tips you’d like to share? Let me know in the comments below!

Nerd For Tech

From Confusion to Clarification

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Matthew Groves

Written by

Digital Products NE Mobile Capability Co-Lead & Senior Software Engineer in Cambridge, MA — https://www.linkedin.com/in/matthew-groves-85677631/

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.