Configurando deep linking no React Native
O Deep Linking possibilita que o usuário acesse seu aplicativo através de aplicações terceiras ou por links em websites acessados pelo smartphone. Vemos muito essa funcionalidade em aplicativos de GPS por exemplo.
Essa funcionalidade também permite a comunicação entre outros apps, ou seja, você pode abrir o WhatsApp, Facebook, ou qualquer outro app, diretamente da sua aplicação.
Vamos supor que você tenha criado um app de receitas e no site do seu aplicativo você possua um botão “Visualizar no app” que deve abrir a aplicação, se o usuário estiver no smartphone, já na página da receita.
Dessa forma seu app teria um endereço, uma URL, só dele, assim como um website. Vamos admitir que o aplicativo se chama “Receita Fácil”, teríamos uma URL receitafacil://
e tudo que vier depois das duas barras indica a página e parâmetros que o usuário está acessando.
Uma grande utilidade para o Deep Linking é enviar notificações push com uma URL personalizada, dessa forma, ao clicar na notificação, o usuário é destinado à página desejada e até com parâmetros personalizados.
Configurando ambiente iOS
Se você estiver utilizando um sistema OSx, pode configurar o Deep Linking no iOS. Primeiramente, abra o arquivo ios/receitafacil/AppDelegate.m
e adicione o seguinte import junto aos demais:
#import <React/RCTLinkingManager.h>
Agora, no fim do arquivo, adicione o seguinte trecho de código:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
}
Seu arquivo deve ficar muito parecido com esse.
A partir disso, nosso app está preparado pra receber deep linking, mas ainda precisamos informar qual a URL que nosso aplicativo reconhecerá (no nosso caso vai ser receitafacil://
).
Agora no XCode, abra seu projeto, na barra lateral esquerda clique sobre o projeto e nas abas superiores selecione a aba Info. No fim da aba, na opção URL Types, adicione a URL da seguinte forma:
Configurando ambiente Android
Vamos começar configurando o Android para permitir Deep Linking abrindo o arquivo android/app/src/main/AndroidManifest.xml
e adicionando um novo intent-filter
ao XML:
<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="receitafacil"
android:host="receitafacil" />
</intent-filter>
Seu arquivo deve ficar parecido com esse.
Veja que no Android temos um host
que será o prefixo antes do ://
e temos também um scheme
, que virá logo após as duas barras, para só depois disso vir o resto da nossa URL, então vamos acessar algo parecido com a seguinte URL no Android: receitafacil://receitafacil/pagina/parametro
Utilizando react-navigation (recomendado)
Durante esse exemplo, vou utilizar a biblioteca React Navigation para identificar a página correta recebida pelo link, mas a funcionalidade de Deep Linking é do React Native, então você pode utilizar a lib que preferir (explico isso no próximo tópico). O código desse exemplo está disponível no Github.
Vamos começar criando nossa aplicação e instalando o React Navigation:
react-native init receitafacil
yarn add react-navigation
Agora, crie uma pasta src
ao seu projeto com um arquivo index.js
dentro. Vamos utilizar esse arquivo index.js
como ponto de entrada para aplicação (assim não precisamos de um index para cada plataforma).
Nos seus arquivos index.android.js
e index.ios.js
, substitua o conteúdo por esse:
import { AppRegistry } from 'react-native';
import App from './src';
AppRegistry.registerComponent('receitafacil', () => App);
Dentro da pasta src
crie uma nova pasta chamada pages
com dois arquivos dentro, list.js
e recipe.js
:
/* Core */
import React, { Component } from 'react';
/* Presentational */
import { View, Platform, Linking } from 'react-native';
export default class List extends Component {
static navigationOptions = {
title: 'Lista de receitas',
};
render() {
return <View />
}
}
/* Core */
import React, { Component } from 'react';
/* Presentational */
import { View, Text } from 'react-native';
export default class Recipe extends Component {
static navigationOptions = {
title: 'Detalhe da receita'
};
render() {
const { params } = this.props.navigation.state;
return (
<View>
<Text>Você acessou a receita: {params.recipe}</Text>
</View>
);
}
}
Note que no segundo arquivo, estamos buscando o parâmetro “recipe” da rota e exibindo-o em tela. Agora no seu arquivo index.js
na pasta src
, utilize o seguinte código:
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator } from 'react-navigation';
import List from './pages/list';
import Recipe from './pages/recipe';
const Router = createStackNavigator({
List,
Recipe: {
screen: Recipe,
path: 'recipe/:recipe',
},
});
const prefix = (Platform.OS === 'ios')
? 'receitafacil://'
: 'receitafacil://receitafacil/';
export default () => <Router uriPrefix={prefix} />;
Aqui definimos um navigator com duas rotas (list e recipe). Como a página recipe é a que queremos acessar via URL, definimos um path para ela. Logo abaixo definimos o prefixo de URL utilizado no iOS e no Android (lembre que o Android possui o scheme além do host, então o nome repete mesmo).
Estamos dizendo para a página recipe ouvir a URL recipe/nome-da-receita
e nomear o parâmetro após a barra como “recipe”.
Agora com o emulador aberto podemos fazer os testes utilizando a linha de comando.
Testando no Android
No Android podemos utilizar o adb
para testar a URL:
adb shell am start -W -a android.intent.action.VIEW -d "receitafacil://receitafacil/recipe/teste" com.receitafacil
Testando no iOS
No iOS podemos tanto utilizar a linha de comando:
xcrun simctl openurl booted receitafacil://recipe/teste
Ou podemos acessar diretamente pelo Safari do emulador:
Sem react-navigation
Caso você não esteja usando react-navigation, os passos de configuração para Android e iOS são os mesmos, porém no código você terá que ouvir a URL inicial acessada no app e redirecionar o usuário conforme o conteúdo dela, inclusive passar os parâmetros enviados.
Para isso, sua página inicial (no nosso caso list
) ficará mais ou menos assim:
/* Core */
import React, { Component } from 'react';
/* Presentational */
import { View, Platform, Linking } from 'react-native';
export default class List extends Component {
async componentDidMount() {
if (Platform.OS === 'android') {
const url = await Linking.getInitialURL();
this.navigate(url);
} else {
Linking.addEventListener('url', this.handleOpenURL);
}
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL = (event) => {
this.navigate(event.url);
};
navigate = (url) => {
const { navigate } = this.props.navigation;
const route = url.replace(/.*?:\/\//g, '');
const recipe = route.match(/\/([^\/]+)\/?$/)[1];
const routeName = route.split('/')[0];
// routeName: recipe
// recipe: teste (parâmetro)
};
render() {
return <View />
}
}
No método componentDidMount
eu acesso a URL inicial e no Android posso chamar diretamente a função navigate
, já no iOS precisamos assinar ao evento url
da classe Linking para receber a string com a URL.
Abaixo na função navigate
, nós quebramos a URL recebida utilizando Javascript para identificar as partes em forma de variável, dessa forma, temos uma variável para o nome da rota (routeName) e o nome da receita acessada (recipe). Caso tiver mais parâmetros, você pode utilizar as próximas posições no array que a variável recipe
utiliza.
E por hoje é só
Nesse post aprendemos a configurar o Deep Linking no React Native utilizando, ou não, o react-navigation. Lembrando que essa técnica é muito interessante para notificações push ou interações com outras aplicações (como login no Facebook).
Código do projeto: https://github.com/Rocketseat/blog-react-native-deep-linking