Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save FelipeGangrel/20dd0b589d66104fe2044489086b4455 to your computer and use it in GitHub Desktop.
Save FelipeGangrel/20dd0b589d66104fe2044489086b4455 to your computer and use it in GitHub Desktop.
React Native no Emulador Android Studio com WSL2

PROJETOS REACT-NATIVE RODANDO NO WSL2 UBUNTU 20.04 COM API BACKEND

📆 Artigo escrito dia: 03/09/2020 📆 Artigo atualizado dia: 10/10/2020

Minhas especificações: Microsoft Windows 10 Enterprise Versão 2004 (Compilação 19041.450). WSL2 - Ubuntu 20.04.

INDÍCE

INTRODUÇÃO

Aqui segue as instruções para poder utilizar o emulador do Android no WSL2, e também poder utilizar APIs backend conectando com o aplicativo no emulador sem erros. Certifique-se de ter instalado o Android Studio no Windows com todas as variáveis de ambiente configuradas corretamente, não vou cobrir isso aqui, porque o artigo já vai ficar longo e ficaria muito conteúdo, acredito que se você está buscando como uttilizar o react-native no wsl você deve ter um ambiente no Windows já configurado, portanto vou pular essa parte. Instale o WSL2 e obtenha o Ubuntu 20.04, configure a parte estética com os plugins zsh e etc, instale as ferramentas NVM, NodeJs e etc... Novamente não vou cobrir isso aqui, existem conteúdos muito bons ensinando a configurar o Ubuntu e o WSL2 na internet, recomendo esse curso aqui, que ensina a configurar o ambiente wsl2 completo: Curso Willian Justen - Criando ambiente WSL2

Estou escrevendo este tutorial porque eu fiquei 2 dias tentando solucionar esse problema e não encontrei absolutamente nada efetivo, encontrei conteúdos que me ajudaram? sem dúvida! no final do post deixo os créditos de referência, de onde encontrei ajuda. O que fiz foi juntar pedaços de diferentes artigos para poder chegar em uma solução realmente funcional, depois de muitos testes eu 🤸‍♂️ CONSEGUI!!! 🤸‍♂️ quase desisti 2 vezes 🤦‍♂️, mas sou brasileiro e não desisto nunca 😎. Agora tenho o ambiente NodeJS super completo no WSL2 Ubuntu 20.04.

Tentei deixar o mais claro e detalhado possível para que até pessoas sem muita experiência consigam seguir o tutorial com sucesso. Lembrando que caso você tenha algo a acrescentar ao artigo, alguma melhoria, resolução de problemas, erros que você enfrentou e não estão descritos aqui é só falar comigo que eu vejo se é possível atualizar o artigo.

Sem enrolação vamos ao tutorial:

Após isso, vamos configurar o Android Studio no Ubuntu 20.04 WSL2.

PASSO 1º

Liberar o wsl2 no Windows Defender e as portas no Firewall do Windows

Antes de prosseguir nós precisamos liberar permissões para o WSL no Windows. Para isso abra o Windows defender, só digitar Segurança do Windows na pesquisa do Windows. Vá em Proteção contra vírus e ameaças / Configurações de Proteção contra vírus e ameaças / Exclusões ⚠[ IMPORTANTE!!! ]⚠ Essa exclusão é necessária senão o sistema não vai funcionar. Você deve clicar em “Gerenciar configurações” e procure “Exclusões”, clicando em “Adicionar ou remover exclusões. Em seguida adicione a pasta C:\Users<USUARIO>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04onWindows_..., resultando nisso:

alt text

E também libere nas regras de firewall do Windows as portas: 8081, 3333, 3000.

PASSO 2º

Instalação das ferramentas do Android sdk no wsl2

Agora vamos instalar as ferramentas necessárias do Android no Ubuntu 20.04 WSL2, para isso execute os comandos a seguir na linha de comando do Ubuntu WSL2 pelo Windows Terminal.

# 1º Caso não esteja na home do seu user Linux navegue até ela (caso já esteja ignore este passo):
cd /home/<user>/

# 2º Instale o unzip:
sudo apt install unzip

# 3º Faça o download do pacote atual de command line tools Android ( verifique qual o pacote mais atual 
# aqui: https://developer.android.com/studio e mude a versão do pacote no comando caso esteja depreciado):
wget https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip

# 4º Descompacte o arquivo no diretório ao mesmo tempo que irá cria-lo.
unzip commandlinetools-linux-6609375_latest.zip -d Android

# 4.1 Renomeie Android/cmdline-tools/cmdline-tools para Android/cmdline-tools/latest

# 5º Remova o arquivo .zip que você acabou de baixar e descompactar, pois não é mais necessário.
rm -rf commandlinetools-linux-6609375_latest.zip

# 6º Instale o JDK do Java e o emulador
sudo apt install -y lib32z1 openjdk-8-jdk

# 7º Setando a variável de ambiente do Java
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

# 8º Setando a variável de ambiente do Java
export PATH=$PATH:$JAVA_HOME/bin

# 9º Exportando as variáveis de ambiente para o arquivo .bashrc
printf "\n\nexport JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64\nexport PATH=\$PATH:\$JAVA_HOME/bin" >> ~/.bashrc

# 10º ⚠[IMPORTANTE!!!]⚠ verifique se o java foi instalado corretamente com 
java -version

# 11º ⚠[IMPORTANTE!!!]⚠ E verifique se as variáveis de ambiente estão inseridas em ambos arquivos .bashrc e .zshrc 
# caso você utilize o zsh, se faltar em algum insira manualmente para que ambos sistemas tenham acesso ao Java.

# 12º ⚠[IMPORTANTE!!!]⚠ Nesta parte é necessário criar a pasta cmdline-tools e colocar a pasta tools dentro dela, 
# porque o diretório originalmente não tem essa pasta, e sem ela ocorre erro ao executar o próximo comando de 
# instalação do plataform-tools. O caminho do diretório original caso o comando 4º não der certo vai ser esse:
Android/tools/bin

# Crie o diretório cmdline-tools
mkdir cmdline-tools

# Mova a pasta tools para dentro da cmdline-tools
mv tools cmdline-tools

# Navegue até este diretório
cd Android/cmdline-tools/tools/bin

# 13º [Verifique no site: https://developer.android.com/studio/command-line/sdkmanager qual a versão mais 
# atual para instalação.] E execute este comando abaixo
./sdkmanager --install "platform-tools" "platforms;android-28" "build-tools;29.0.2"

# 14º  Criando as variáveis de ambiente do Android, copie e cole essas variáveis de ambiente nos arquivos 
# .zshrc e .bashrc, faça isso manualmente.
export ANDROID_HOME=/home/<seu_user_linux>/Android
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

# Reinicie o terminal para validar as alterações ou faça o source para atualizar os arquivos.

# 15º Ainda no diretório 'Android/cmdline-tools/tools/bin' Uma vez que o comando android está obsoleto, o 
# comando abaixo:
android update sdk --no-ui # deve ser substituído por:
sdkmanager --update

# 16º Instale o Gradle
sudo apt install gradle

# 17º Verifique a versão do Gradle
gradle -v

A partir de agora você já deve ter uma AVD no Android Studio do Windows, se ainda não, crie uma AVD para testarmos tudo daqui para a frente.

PASSO 3º

Habilitar acesso ao servidor adb no wsl2

Precisamos habilitar o acesso ao servidor adb no wsl2, para isso cole a seguinte variável de ambiente nos arquivos .bashrc e .zshrc:

export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d' ' -f2)
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037

Salve o arquivo e atualize ou feche o terminal para a alteração fazer efeito.

PASSO 4º

Linkar a rede do wsl2 para conectar portas

⚠[ IMPORTANTE!!! ]⚠ Antes de seguir veja essa observação

⚠[ OUTRA NOTA IMPORTANTE!!! ]⚠ Cada vez que você reiniciar o sistema Windows o IP do Ubuntu WSL2 vai mudar, por isso é necessário repetir este procedimento a cada reinicialização do sistema, a não ser que alguém consiga setar o IP do WSL2 como estático, que é uma outra issue bem procurada para ser resolvida.

Não basta apenas executar um projeto react-native no emulador a partir do wsl2, os projetos possuem conexões de backend que utilizam portas para se comunicar entre serviços, e para que essa comunicação funcione corretamente no wsl precisamos linkar a rede do wsl2 habilitando as portas desejadas, utilizando o IP da máquina WSL2. Para isso vamos utilizar esse script abaixo:

# No script onde está com < > é para adicionar as suas informações, e remova as < > quando editar.
netsh interface portproxy add v4tov4 listenport=<PORTA_DESEJADA> listenaddress=0.0.0.0 connectport=<PORTA_DESEJADA> connectaddress=<IP_WSL>

#Para fazer o procedimento, abra um terminal do wsl2 ubuntu e digite o comando:
# Esse comando vai mostrar para você o IP da máquina WSL2.
ip addr | grep eth0

Veja o resultado do comando acima:

alt text

No caso acima vamos utilizar o IP: 172.28.76.189 que corresponde somente a minha máquina aqui, verifique o seu. Abra o Powershell em modo de administrador, e edite o comando para podemos habilitar as portas desejadas, neste caso eu vou habilitar a porta 3333, que é muito utilizada em backend NodeJS, para conexão de API, principalmente o Axios. Veja o comando modificado:

netsh interface portproxy add v4tov4 listenport=3333 listenaddress=0.0.0.0 connectport=3333 connectaddress=172.28.76.189

Cole no terminal e aperte enter para executar o comando, se for bem sucedido ele não retorna nenhuma resposta de sucesso, apenas é executado sem avisos. Feito isso está tudo certo para você poder utilizar o seu aplicativo com uma API backend, os links de APIs que fazem conexão com o emulador do Android continuam sendo feitos com o IP padrão 10.0.2.2. Como por exemplo o Axios que você precisa para configurar a sua conexão com a API e seus front-ends e apps, veja um exemplo de configuração do Axios no meu projeto de teste:

import axios from 'axios';

const api = axios.create({
  baseURL: 'http://10.0.2.2:3333',
});

export default api;

/**
 * Como linkar a baseURL nos dispositivos android e emuladores:
 * 
 * iOS com emulador: localhost
 * iOS com dispositivo físico: IP da máquina
 * Android com emulador: localhost (adb reverse)
 * Android com emulador IP: 10.0.2.2 (Android Studio)
 * Android com emulador IP: 10.0.3.2 (Genymotion)
 * Android com dispositivo físico: IP da máquina 
 */

Repare que existem diferentes baseURLs para trabalhar no Axios, utilizando o Android Studio utiliza-se o IP 10.0.2.2, não fiz nenhuma alteração para trabalhar com esse projeto no Ubuntu WSL2, apenas fiz o build no ubunt, está idêntico ao utilizado no ambiente de desenvolvimento do Windows 10. E funciona no Ubuntu WSL2, realizando este procedimento. Você pode utilizar o mesmo comando para liberar outras portas, como por exemplo, 3000, 3390 etc. Libere de acordo com a sua necessidade.

PASSO 5º

Executando um projeto react-native no wsl2

Agora inicie um dispositivo virtual avd no Windows, seja pelo Android Studio ou pelo cmd do Windows mesmo, não importa apenas inicie um avd. ⚠[ IMPORTANTE!!! ]⚠ O emulador do Android tem que estar aberto e ativo primeiramente, antes do próximo passo, se fizer o próximo passo sem o emulador estar aberto ativo, não vai dar certo o próximo comando.

alt text

Agora vamos precisar de 3 terminais abertos 1 do Powershell e dois Linux Ubuntu.

No terminal do Powershell inicie o servidor adb no Windows:

adb kill-server
adb -a nodaemon server start

alt text

Deixe esse prompt powershell sempre aberto, não o feche enquanto estiver trabalhando no seu projeto Android.

Agora crie um projeto React Native no seu Ubuntu WSL2:

npx react-native init SeuProjeto

depois de criar o projeto abra dois terminais do ubuntu e navegue até o diretório raiz desse projeto react-native que você criou, nos dois terminais.

No primeiro terminal execute o comando:

npx react-native start --host 127.0.0.1

alt text

Deixe esse terminal executando esse comando e não mecha ou feche esse terminal.

Vá para o segundo terminal e execute o comando:

npx react-native run-android --variant=debug --deviceId emulator-5554

alt text

Se deu tudo certo até esta etapa você vai ver o projeto ser aberto no emulador avd do android no Windows. Pode ser que apareça uma tela branca e pode demorar um pouco para iniciar, mas ele compila e inicia, veja:

alt text

Executando servidor backend e consumindo pelo app

Agora como já mepeamos a porta 3333 no passo 4º, você pode executar um projeto react-native que consome um backend, basta abrir mais um terminal e executar o seu projeto backend normalmente. Como estamos utilizando aqui o emulador do Android Studio, ele utiliza o host de mapeamento 10.0.2.2, pode continuar utilizando esse host que vai funcionar normalmente, aqui eu testei com uma api que utiliza o Axios, veja o sistema com a conexão funcionando:

alt text

Veja também o Metro Bundle funcionando 100%, criando o bulid a cada alteração feita e gerando os logs.

alt text

Portanto basta continuar trabalhando normalmente nos seus projetos, caso precise liberar outra porta, basta repetir o PASSO 4º e adicionar a porta que você precisa.

EXTRAS

Conectando API Local Json-Server

Para podermos utilizar o Json-Server no WSL2, precisamos modificar o host que ele se conecta, que por padrão é o localhost, se utilizarmos o padrão no WSL2 a conexão não irá funcionar, por isso é preciso redirecionar o host de conexão. Como mapeamos as portas nas etapas anteriores o host 0.0.0.0 é onde vamos nos conectar no Json-Server, com isso ele irá se conectar nos redirecionamentos de porta que fizemos nas etapas anteriores.

Utilizando este código:

yarn json-server -H 0.0.0.0 -w server.json -p 3333

O server.json é apenas o arquivo onde você tem os dados dos objetos que você vai popular a api fake. E se você digitar o endereço http://localhost:3333 no navegador do Windows a API irá funcionar, e ela também irá funcionar no WSL2 e no emulador adb que está utilizando a porta 10.0.2.2.

Veja como na imagem abaixo: alt text

Resolvendo erro Unable to load script from assets index android bundle Make sure

Para não ter problemas e caso ocorra este erro ao tentar buildar um app no emulador avd, veja o erro:

alt text

Esse erro geralmente acontece porque o sistema não conseguiu criar o bundle inicial que contém todo o código Javascript da aplicação. Para resolver comece criando uma pasta assets dentro da pasta do seu projeto react-native:

android/app/src/main

Logo após, execute o comando:

npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/

Agora, feche as abas do terminal e execute novamente o comando:

npx react-native run-android --variant=debug --deviceId emulator-5554

Caso ainda haja erro, para garantir feche todos os terminais, desinstale o app do emulador, feche o emulador e inicie novamente.

Resolvendo erro Error Duplicate resources

Esse erro pode acontecer após resolver o erro Unable to load script from assets 'index.android.bundle'. Make sure...

alt text

para resolver basta entrar no diretório do seu projeto react-native:

android\app\src\main\res

E deletar o conteúdo dentro destas pastas, mas somente o conteúdo dentro e não a pasta em si:

drawable-mdpi
mipmap-xhdpi
mipmap-xxhdpi
raw

⚠[IMPORTANTE]⚠ antes de deletar o conteúdo destas pastas descritas acima, leia o log de erro e veja se o caminho da pasta é referido no log de erro, se alguma não estiver no log pode deixar intacta, por isso é bom prestar atenção no log de erro.

OBSERVAÇÕES

Sem o mapeamento das portas 8081, 3333, por esse script que vi na maioria dos tutoriais e artigos, veja:

iex "netsh interface portproxy delete v4tov4 listenport=8081 listenaddress=127.0.0.1" | out-null;
$WSL_CLIENT = bash.exe -c "ifconfig eth0 | grep 'inet '";
$WSL_CLIENT -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
$WSL_CLIENT = $matches[0];
iex "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=$WSL_CLIENT"

O Metro Bundle faz o build de forma normal, com os logs e funcionalidades tudo ok, atualiza a cada edição nos arquivos do projeto fazendo o build automaticamente. Porém se você fazer o mapeamento utilizando o script acima o Metro Bundle não funciona, somente fica no início e não faz build automático, você edita um arquivo, salva e ele não faz build automático. Portanto não utilize este script, pois ele é inutil, pelo menos para mim aqui no meu sistema. Caso você tenha executado esse script nas tentativas passadas de fazer funcionar, recomendo limpar os mapeamentos que você fez com esse script antes de fazer o passo 4º.

Abra o Powershell como administrador. Primeiro verifique se você possui mapeamentos de portas, com este comando:

netsh interface portproxy show all

Se você tiver algum mapeamento depois de verificar com o comando acima, limpe tudo executando o comando:

netsh interface portproxy reset

Voltar para o PASSO 4º

REFERÊNCIAS

Aqui estão os links dos artigos, blogs onde encontrei soluções para os problemas.

Building a react native app in WSL2

Ambiente de Desenvolvimento (React e React Native) no Windows com WSL

Android Emulator connecting to node server in WSL2

WSL 2 TPC NETWORK FORWARDING

wsl2-hacks

WSL 2 Networking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment