We live in an age where everything can be shared, and the process of sharing almost always ends up sharing a link. So, as a developer, the most common problems should include how to quickly open an App through a URL address and navigate to a specific page. What is Deep Link? Deep linking is a technology that allows an App to be opened through a URL address and then navigate to a specific page or resource, or display a specific UI. Deep means that the page or resource opened is not the homepage of the App. The most commonly used places include but are far from limited to Push Notification, emails, web links, etc. In fact, this technology has existed for a long time. When you click a link like mailto:[email protected], the system will open the default email software, and then fill in the email address [email protected] in the recipient input field. This is a deep link. This article will create an application from scratch that supports opening an article detail page through a URL such as deep-linking://articles/{ID} and loading the article specified by {ID}. For example, deep-linking://articles/4 will open the article detail page with ID 4. What problem does deep linking solve? Web links cannot open native applications. If a user visits a resource on your web page and your application is already installed on his phone, how can we let the system automatically open the application and then display the resources on the page visited by the user in the application? This is the problem that deep links need to solve. Different ways to implement deep linking There are two ways to implement deep linking: - URL scheme
- Universal links
The front end is the most common method, and the latter is a new method provided by iOS, which can link to specific resources of the App with a normal web address. This article will create an app named DeepLinkingExample, which allows users to open the home page of the App and the details page of the article with ID 4 in the App by opening deep-linking://home and deep-linking://articles/4 respectively. - react-native init DeepLinkingExample
- cd DeepLinkingExample
Install Necessary Libraries Following the TypeScript trend, our App will be developed using TypeScript. - yarn add react-navigation react-native-gesture-handler
- react-native link react-native-gesture-handler
We will use the react-navigation module as the navigation library for the App. Add TypeScript related development dependencies: - yarn add typescript tslint tslint-react tslint-config-airbnb tslint-config-prettier ts-jest react-native-typescript-transformer -D
- yarn add @types/jest @types/node @types/react @types/react-native @types/react-navigation @types/react-test-renderer
Add tsconfig.json: - {
- "compilerOptions" : {
- "target" : "es2017" , /* Specify ECMAScript target version: 'ES3' ( default ), 'ES5' , 'ES2015' , 'ES2016' , 'ES2017' , or 'ESNEXT' . */
- "module" : "es2015" , /* Specify module code generation: 'none' , 'commonjs' , 'amd' , 'system' , 'umd' , 'es2015' , or 'ESNext' . */
- "lib" : [ /* Specify library files to be included in the compilation: */
- "es2017" ,
- "dom"
- ],
- "resolveJsonModule" : true ,
- "allowJs" : false , /* Allow javascript files to be compiled. */
- "skipLibCheck" : true , /* Skip type checking of all declaration files. */
- "jsx" : "react-native" , /* Specify JSX code generation: 'preserve' , 'react-native' , or 'react' . */
- "declaration" : true , /* Generates corresponding '.d.ts' file. */
- "sourceMap" : true , /* Generates corresponding '.map' file. */
- "outDir" : "./lib" , /* Redirect output structure to the directory. */
- "removeComments" : true , /* Do not emit comments to output . */
- "noEmit" : true , /* Do not emit outputs. */
-
- /* Strict Type-Checking Options */
- "strict" : true , /* Enable all strict type-checking options. */
- "noImplicitAny" : true , /* Raise error on expressions and declarations with an implied 'any' type. */
- "strictNullChecks" : true , /* Enable strict null checks. */
- "strictFunctionTypes" : true , /* Enable strict checking of function types. */
- "noImplicitThis" : true , /* Raise error on 'this' expressions with an implied 'any' type. */
- "alwaysStrict" : true , /* Parse in strict mode and emit "use strict" for each source file. */
-
- /* Additional Checks */
- "noUnusedLocals" : true , /* Report errors on unused locals. */
- "noUnusedParameters" : true , /* Report errors on unused parameters. */
- "noImplicitReturns" : true , /* Report error when not all code paths in Function return a value. */
- "noFallthroughCasesInSwitch" : true , /* Report errors for fallthrough cases in switch statement. */
-
- /* Module Resolution Options */
- "moduleResolution" : "node" , /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
- "baseUrl" : "./" , /* Base directory to resolve non- absolute module names. */
- "paths" : { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl' . */
- "*" : [
- "*.android" ,
- "*.ios" ,
- "*.native" ,
- "*.web" ,
- "*"
- ]
- },
- "typeRoots" : [ /* List of folders to include type definitions from . */
- "@types" ,
- "../../@types"
- ],
- // "types" : [], /* Type declaration files to be included in compilation. */
- "allowSyntheticDefaultImports" : true , /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
- // "preserveSymlinks" : true , /* Do not resolve the real path of symlinks. */
-
- /* Experimental Options */
- "experimentalDecorators" : true , /* Enables experimental support for ES7 decorators. */
- "emitDecoratorMetadata" : true /* Enables experimental support for emitting type metadata for decorators. */
- },
- "exclude" : [
- "node_modules" ,
- "web"
- ]
- }
Add tslint.json file - {
- "defaultSeverity" : "warning" ,
- "extends" : [
- "tslint:recommended" ,
- "tslint-react" ,
- "tslint-config-airbnb" ,
- "tslint-config-prettier"
- ],
- "jsRules" : {},
- "rules" : {
- "curly" : false ,
- "function-name" : false ,
- "import-name" : false ,
- "interface-name" : false ,
- "jsx-boolean-value" : false ,
- "jsx-no-multiline-js" : false ,
- "member-access" : false ,
- "no-console" : [ true , "debug" , "dir" , "log" , "trace" , "warn" ],
- "no-empty-interface" : false ,
- "object-literal-sort-keys" : false ,
- "object-shorthand-properties-first" : false ,
- "semicolon" : false ,
- "strict-boolean-expressions" : false ,
- "ter-arrow-parens" : false ,
- "ter-indent" : false ,
- "variable-name" : [
- true ,
- "allow-leading-underscore" ,
- "allow-pascal-case" ,
- "ban-keywords" ,
- "check-format"
- ],
- "quotemark" : false
- },
- "rulesDirectory" : []
- }
Add .prettierrc file: - {
- "parser" : "typescript" ,
- "printWidth" : 100,
- "semi" : false ,
- "singleQuote" : true ,
- "trailingComma" : "all"
- }
Writing our application Create a src directory in the project root directory, which will be the directory for the project source code. Add src/App.tsx file - import React from 'react'
-
- import { createAppContainer, createStackNavigator } from 'react-navigation'
-
- import About from './screens/About'
- import Article from './screens/Article'
- import Home from './screens/Home'
-
- const AppNavigator = createStackNavigator(
- {
- Home: { screen: Home },
- About: { screen: About, path: 'about' },
- Article: { screen: Article, path: 'article/:id' },
- },
- {
- initialRouteName: 'Home' ,
- },
- )
-
- const prefix = 'deep-linking://'
-
- const App = createAppContainer(AppNavigator)
-
- const MainApp = () => <App uriPrefix={prefix} />
-
- export default MainApp
Add src/screens/Home.tsx file - import React from 'react' ;
Add src/screens/About.tsx - import React from 'react'
-
- import { StyleSheet, Text, View } from 'react-native'
-
- import { NavigationScreenComponent } from 'react-navigation'
-
- interface IProps {}
-
- interface IState {}
-
- const AboutScreen: NavigationScreenComponent<IProps, IState> = props => {
- return (
- < View style={styles.container}>
- <Text style={styles.title}>About Page</Text>
- </ View >
- )
- }
-
- AboutScreen.navigationOptions = {
- title: 'About' ,
- }
-
- export default AboutScreen
-
- const styles = StyleSheet. create ({
- container: {},
- title: {},
- })
Add src/screens/Article.tsx - import React from 'react'
-
- import { StyleSheet, Text, View } from 'react-native'
-
- import { NavigationScreenComponent } from 'react-navigation'
-
- interface NavigationParams {
- id: string
- }
-
- const ArticleScreen: NavigationScreenComponent<NavigationParams> = ({ navigation }) => {
- const { params } = navigation.state
-
- return (
- < View style={styles.container}>
- <Text style={styles.title}>Article {params ? params.id : 'No ID' }</Text>
- </ View >
- )
- }
-
- ArticleScreen.navigationOptions = {
- title: 'Article' ,
- }
-
- export default ArticleScreen
-
- const styles = StyleSheet. create ({
- container: {},
- title: {},
- })
Configuring iOS Open ios/DeepLinkingExample.xcodeproj: - open ios/DeepLinkingExample.xcodeproj
Click the Info Tab page, find the URL Types configuration, and add an item: - identifier:deep-linking
- URL Schemes: deep-linking
- Leave the other two items blank
Open the AppDelegate.m file in the project's root directory and add a new import: - #import "React/RCTLinkingManager.h"
Then add the following code before @end: - - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
- return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
- }
So far, we have completed the configuration of iOS, running and testing whether it is successful. - react-native run-ios
After opening the simulator, open the Safari browser and enter deep-linking://article/4 in the address bar. Your app will automatically open and go to the Article page at the same time. Similarly, you can also execute the following command in the command line tool: - xcrun simctl openurl booted deep-linking://article/4
Configuring Android To create External Linking for Android applications, you need to create a new intent, open android/app/src/main/AndroidManifest.xml, and then add a new intent-filter in the MainActivity node: - <application ...>
- <activity android: name = ".MainActivity" ...>
- ...
- <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= "deep-linking" />
- </intent-filter>
- ...
- </activity>
- </application>
Android only needs to complete the above configuration. implement: - react-native run-android
Open the system browser and enter: - deep-linking://article/4
The system will automatically open your app and enter the Article page You can also use the following command to open it in the command line tool: - adb shell am start -W -a android.intent. action . VIEW -d "deep-linking://article/3" com.deeplinkingexample;
|