Attempt Link to Implement React Native Application on iOS and Android

Keywords: iOS React Android TypeScript

Original: https://pantao.parcmg.com/press/react-native-deep-linking-for-ios-android.html
Code: https://github.com/pantao/react-native-deep-linking-example

We live in an age of all things being shared, and the process of sharing will almost eventually share a link. So, as a developer, the most common problem should include how to quickly open App through a URL address and navigate to a specific page.

What is Deep Link?

Deep Link is a technology that allows an App to be opened through a URL address and then navigated to a specific page or resource, or to display a specific UI. Deep means that an open page or resource is not the home page of App, and most commonly used places include but are far from limited to Push Notification, e-mail, and web. Page links, etc.

In fact, this technology has existed for a long time. Click on the mouse. mailto:pantao@parcmg.com Such links, the system will open the default mail software, and then pantao@parcmg.com mailbox to fill in the recipient input field, which is the deep link.

This article will create an application from scratch that supports opening the article details page through a URL such as deep-linking://articles/{ID} and loading the articles specified by {ID} such as: deep-linking://articles/4 will open the article details page with ID 4.

What problems does deep linking solve?

Web links are not able to open native applications. If a user visits a resource in your web page and your application has been installed on his mobile phone, how do we make the system open the application automatically and display the resources in that page that the user visits in the application? This is the problem of deep linking.

Different ways to implement deep links

There are two ways to achieve deep links:

  • URL scheme
  • Universal links

The front end is the most common way, the latter is a new way provided by iOS, which can link to specific resources of App with a common web address.

This article will create an application called DeepLinking Example, which allows users to open the home page of App and the article details page of ID 4 in App by opening deep-linking://home and deep-linking://articles/4 respectively.

react-native init DeepLinkingExample
cd DeepLinkingExample

Install the necessary Libraries

Following the trend of TypeScript, our App writing 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 App's navigation library.

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 the 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"
}

Write our application

Create an src directory under the project root directory, which will be the directory of the original project 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: {},
})

Configure iOS

Open ios/DeepLinkingExample.xcodeproj:

open ios/DeepLinkingExample.xcodeproj

Click on the Info Tab page to find the URL Types configuration and add an item:

  • identifier: deep-linking
  • URL Schemes: deep-linking
  • Two other items are left blank

Open the AppDelegate.m file under the project and directory and add a new import:

#import "React/RCTLinkingManager.h"

Then before @end, add the following code:

- (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 iOS configuration, run and test for success.

react-native run-ios

After opening the simulator, open the Safari browser and enter deep-linking://article/4 in the address bar. Your application will automatically open and enter the Article page at the same time.

Similarly, you can execute the following commands in the command line tool:

xcrun simctl openurl booted deep-linking://article/4

Configure Android

To create External Linking for Android applications, you need to create a new intent, open Android/app/src/main/Android Manifest.xml, and then add a new intent-filter to 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.

Implementation:

react-native run-android

Open the system browser and enter:

deep-linking://article/4

The system will automatically open your application and go to the Article page.

The following commands can also be used in command line tools to open:

adb shell am start -W -a android.intent.action.VIEW -d "deep-linking://article/3" com.deeplinkingexample;

appendix

Click on the following link:

Posted by warik on Sun, 18 Aug 2019 06:10:02 -0700