Advertisement
  1. Code
  2. React Native

Separar Aplicaciones de Expo a ExpoKit

Scroll to top
Read Time: 18 min

Spanish (Español) translation by Jean Perez (you can also view the original English article)

En mi post más Fácil Desarrollo React Native con Expo, aprendieron sobre cómo Expo hace más fácil para principiantes empezar a crear aplicaciones con reaccionar nativo. Usted también aprendió que Expo permite a los desarrolladores a levantarse y correr con el desarrollo de aplicaciones nativas reaccionan más rápido porque ya no hay necesidad de configurar Android Studio, Xcode u otras herramientas de desarrollo.

Pero como también ha visto, Expo no soporta todas las funciones nativas que necesita una aplicación. Aunque el equipo de Expo siempre está trabajando para apoyar la funcionalidad más nativa, es una buena idea para aprender a convertir un proyecto de exposición existente en un proyecto nativo estándar así que usted puede fácilmente transición si es necesario.

Por lo tanto, en esta serie de dos partes, estamos tomando un vistazo a cómo hacerlo. En la primera parte de la serie, has aprendido los conceptos básicos de ExpoKit. En este post, a continuar donde nos quedamos por separar realmente la aplicación para ExpoKit y seguir la codificación de la aplicación para compartir ubicación.

Desprendimiento de ExpoKit

Para separar a ExpoKit, primero tienes que editar los archivos app.json y package.json.

En el archivo de app.json, asegúrese de que se ha establecido un nombre. Las plataformas deben ser las plataformas que quiere construir.

1
{
2
  "expo": {
3
    "name": "ocdmom",
4
    "platforms": [
5
      "ios",
6
      "android"
7
    ],

Si usted quiere construir para iOS, debe especificar la opción ios:

1
"ios": {
2
  "bundleIdentifier": "com.ocd.mom"
3
},

Si usted desea apoyar Android, también especifique la siguiente opción:

1
"android": {
2
  "package": "com.ocd.mom"
3
}

Hay otras opciones que fueron prellenados por la herramienta de línea de comandos de exp cuando el proyecto fue creado. Pero el sólo importantes son el bundleIdentifier para iOS y el paquete para Android. Estos serán los identificadores únicos para la aplicación una vez que haz publicados a la tienda de Apple o el juego. Desmontaje requiere esos detalles porque realmente genera el código nativo de la aplicación para ejecutarse en un dispositivo. Puede encontrar más información sobre las diferentes opciones de configuración para el archivo app.json en la documentación de Expo.

Puede ver el contenido completo del archivo en el repositorio de GitHub.

A continuación, abra el archivo package.json y agregue el nombre del proyecto:

1
"name": "ocdmom"

Este debe ser el nombre que utilizó cuando creó el proyecto utilizando init exp. Es muy importante que son los mismos porque el nombre que se especifica en el package.json se utiliza al compilar la aplicación inconsistencias en este nombre producirá un error.

Ahora estamos listos para separar a ExpoKit. Ejecute el siguiente comando en la raíz del directorio del proyecto:

1
exp detach

Esto descargará los paquetes Expo nativos para Android y iOS localmente.

Si tuvo éxito, debería ver una salida similar al siguiente:

Expo detachExpo detachExpo detach

Si usted está desplegando en iOS, usted necesita instalar la última versión de Xcode. En el momento de escribir este tutorial la última versión es la 9. A continuación, instale CocoaPods ejecutando sudo gem install cocoapods. Esto le permite instalar las dependencias de iOS nativas del proyecto. Una vez hecho esto, el ios al directorio del proyecto y ejecutar pod install para instalar todas las dependencias nativas.

Instalación de Paquetes Native Personalizados

Ahora que nos hemos separado, ahora podemos instalar paquetes nativos al igual que en una nativa estándar de reaccionar al proyecto.

Para esta aplicación, tenemos los paquetes de Temporizador de Fondo React Native y Pusher.

En primer lugar, instalar el paquete de empuje porque es más fácil:

1
npm install --save pusher-js

Esto nos permite comunicarnos con el empujador de la aplicación que creó anteriormente.

A continuación, instale al temporizador de fondo React Native. Esto nos permite periódicamente ejecutar código (incluso cuando la aplicación está en segundo plano) en función de un intervalo específico:

1
npm install --save react-native-background-timer

A diferencia del paquete de empuje, esto requiere una biblioteca nativa (iOS o Android) vinculados a la aplicación ejecutando el siguiente comando que hace por ti:

1
react-native link

Una vez hecho, también debe inicializar el módulo de android/app/src/main/host/exp/exponent/MainApplication.java. Pero sólo para asegurarse, compruebe si existe el siguiente en el archivo:

1
import com.ocetnik.timer.BackgroundTimerPackage; // check this

2
3
public List<ReactPackage> getPackages() {
4
    return Arrays.<ReactPackage>asList(
5
      new BackgroundTimerPackage() // also check this

6
    );
7
}

Si vas a compilar para iOS, abra el Podfile dentro del directorio de ios y que se añade lo siguiente antes de la declaración de post_install:

1
pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'

Una vez hecho esto, ejecuta pod install dentro del directorio de ios para instalar el módulo nativo.

Para Android, ya ello automáticamente al ejecutar la aplicación usando Android Studio.

Actualizar el Archivo de Manifiesto Android

Si vas a compilar para Android, abrir el Android manifest file (android/app/src/main/AndroidManifest.xml) y asegúrese de que se han agregado los siguientes permisos:

1
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
2
<uses-permission android:name="android.permission.INTERNET" />
3
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
4
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Esto nos permite pedir permiso para el botón para acceder a la internet y la exposición para obtener la ubicación actual del usuario en dispositivos Android.

Ejecuta la Aplicación

Aún no hemos terminado, pero es mejor ejecutar la aplicación ahora, así que ya veremos si funciona o no. De este modo, también puede ver los cambios mientras estamos desarrollando la aplicación.

El primer paso para ejecutar la aplicación debe ejecutar exp start desde el directorio raíz del proyecto. Con esto iniciará el servidor de desarrollo para que se Haz reflejará cualquier cambio que realice al código fuente en la vista previa de la aplicación.

Si vas a compilar para Android, abrir Android Studio y seleccione Abrir un Proyecto Existente de Android Studio. En el selector de directorio que se muestra, seleccione la carpeta android dentro del proyecto de la Expo. Una vez hayas seleccionado la carpeta, deben indizar los archivos en esa carpeta. En ese momento, ahora debe ser capaz de reconstruir el proyecto seleccionando Build > Reconstruir el Proyecto en el menú superior. Una vez hecho esto, ejecute la aplicación seleccionando Ejecutar > Ejecutar 'app'.

Android Studio puede ejecutar la aplicación en cualquier dispositivo Android conectado a la computadora, en uno de los emuladores que instaló mediante estudio de Android o desde Genymotion (estudio Android detecta automáticamente una instancia de emulador en ejecución). Para esta aplicación, te recomiendo que uses el emulador Genymotion ya que tiene un bonito widget de emulación de GPS que le permite cambiar la ubicación a través de una interfaz de mapas de Google:

Genymotion location emulationGenymotion location emulationGenymotion location emulation

(Si tienes problemas al ejecutar la aplicación en su dispositivo, asegúrese de revisar esta cuestión Stack Overflow en conseguir Android Studio reconozca el dispositivo.)

Una vez hecho esto, abra el archivo ios/ocdmom.xcworkspace con Xcode. Una vez realizado el Xcode indexación de los archivos, podrá pulsar gran juego y ejecutará automáticamente la aplicación en el simulador de iOS seleccionado.

Xcode permite burlarse de la situación, pero sólo cuando se compila la aplicación para correr en el simulador. Realizar un cambio en el código y tener el servidor de desarrollo actualizar la aplicación realmente no cambian la situación. Para cambiar la ubicación, haga clic en el icono enviar y seleccione la ubicación que desea utilizar:

Xcode location simulationXcode location simulationXcode location simulation

Continuar la Codificando la Aplicación

Ahora estamos listos para seguir escribiendo el código de la aplicación. Esta vez, se va añadiendo la funcionalidad para ejecutar algún código cuando la aplicación está en el fondo.

Agregar una Tarea en Segundo Plano

Importar el paquete empujador y temporizador de fondo que antes de instalar:

1
import BackgroundTimer from 'react-native-background-timer';
2
import Pusher from 'pusher-js/react-native';

Establecer el valor de la clave de la API de Google el proyecto de Google que creó anteriormente:

1
const GOOGLE_API_KEY = 'YOUR GOOGLE PROJECT API KEY';

Utilizar la API de Ubicación y Permisos de Expo:

1
const { Location, Permissions } = Expo;

APIs de la Expo cruz-plataforma de trabajo, esto no es diferente a un proyecto estándar de React Native  donde usted tiene que instalar un paquete como permisos React Native para obtener acceso a una API de permisos que funciona entre plataformas.

A continuación, establece el intervalo (en milisegundos) que el código para el seguimiento de la ubicación del usuario actual se va a ejecutar. En este caso, queremos que ejecute cada 30 minutos. Tenga en cuenta que en el código de abajo estamos utilizando el valor de la variable location_status para comprobar si fue otorgado el permiso para acceder a la ubicación del usuario actual o no. A establecer el valor de esta variable más adelante, una vez montado el componente:

1
var interval_ms = 1800 * 100; // 1800 seconds = 30 minutes, times 100 to convert to milliseconds

2
var location_status = null; // whether accessing the user's location is allowed or not

3
4
BackgroundTimer.runBackgroundTimer(() => { // run the background task

5
 
6
  if(location_status == 'granted'){ // if permission to access the location is granted by the user

7
8
    // next: add code for getting the user's current location

9
  
10
  }
11
  
12
}, 
13
interval_ms);

Obtener la Ubicación Actual

Obtener la ubicación actual utilizando la API de Ubicación de Expo:

1
Location.getCurrentPositionAsync({ // get the user's coordinates

2
  enableHighAccuracy: true // enable fetching of high accuracy location

3
})
4
.then((res) => {
5
 
6
  let { latitude, longitude } = res.coords; // extract the latitude and longitude values

7
8
  // next: add code for getting the address based on the coordinates

9
});

A continuación, utilizando los mapas Google Geocoding API, solicitar al extremo de geocodificación inversa mediante el suministro de los valores de latitud y longitud. Esto devuelve una dirección con formato basada en las coordenadas:

1
fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=${GOOGLE_API_KEY}`)
2
  .then((response) => response.json())
3
  .then((responseJson) => {
4
    let addr = responseJson.results[0].formatted_address;
5
6
    // next: send the location with Pusher

7
8
  })
9
  .catch((error) => {
10
    console.error(error);
11
  });

Enviar la Ubicación Con Pusher

El siguiente paso es la ubicación usando el botón de enviar. Posteriormente vamos a crear el servidor que servirá como el punto final de auth y al mismo tiempo Mostrar la página que muestra la ubicación actual del usuario.

Actualización el constructor para establecer un valor predeterminado para la instancia de Pusher:

1
constructor() {
2
  /*

3
  the code for generating unique code from earlier

4
  */
5
  this.pusher = null;
6
}

Cuando el componente se monta, queremos inicializar empujador. Ahora puede proporcionar la clave de API de Pusher y de la configuración de la aplicación de Pusher que creó anteriormente:

1
componentWillMount() {
2
  this.pusher = new Pusher('YOUR PUSHER APP KEY', {
3
    authEndpoint: 'YOUR AUTH SERVER ENDPOINT (TO BE ADDED LATER)',
4
    cluster: 'YOUR PUSHER CLUSTER',
5
    encrypted: true // whether the connection will be encrypted or not. This requires https if set to true

6
  });
7
}

A continuación, ahora puede Agregar el código para el envío de la ubicación actual. En el botón, esto se hace llamando al método trigger(). El primer argumento es el nombre del evento de activación, y el segundo argumento es un objeto que contiene los datos que desea enviar.

Posteriormente en el servidor, podrá suscribirse en el mismo canal que suscribirán una vez montado el componente. Entonces te unen al evento de client-location para que cada vez que se activa de alguna parte, también haz notificará el servidor (aunque sólo cuando la página está sirviendo también es suscrito en el mismo canal):

1
fetch(...)
2
  .then(...)
3
  .then((responseJson) => {
4
    let addr = responseJson.results[0].formatted_address;
5
6
    current_location_channel.trigger('client-location', {
7
      addr: addr,
8
      lat: latitude,
9
      lng: longitude
10
    });
11
12
  })
13
  .catch(...);

La única vez que vamos a pedir permiso para acceder a la ubicación actual del usuario es cuando el componente se monta. Vamos entonces a actualizar el location_status basado en selección del usuario. El valor puede ser "concedido" o "denegado".

Recuerde que el código de comprobación de la ubicación actual del usuario se ejecuta periódicamente. Esto significa que el nuevo valor de la variable location_status también se utilizará en un momento posterior cuando se ejecuta la función. Después de eso, también queremos a suscribiros al canal de Pusher donde se enviarán las actualizaciones de Ubicación:

1
componentDidMount() { 
2
  try {
3
    Permissions.askAsync(Permissions.LOCATION).then(({ status }) => {
4
      location_status = status;
5
    });
6
  }catch(error){
7
    console.log('err: ', error);
8
  }
9
  // subscribe to the Pusher channel 

10
  current_location_channel = this.pusher.subscribe('private-current-location-' + this.state.unique_code);
11
}

Crear el Servidor

Ahora estamos listos para crear el servidor. En primer lugar, crear el directorio de trabajo (ocdmom-server) fuera del directorio de proyecto de la aplicación navegar dentro del directorio y ejecutar npm init. Solo presiona Enter hasta que crea el archivo package.json.

A continuación, instale los paquetes que necesitamos:

1
npm install --save express body-parser pusher

Aquí está un resumen de lo que hace cada paquete:

  • express: se utiliza para crear un servidor. Esto es responsable de servir la página de seguimiento, así como responder al extremo auth.
  • body-parser: Express middleware que analiza el cuerpo de la solicitud y lo hace disponible como un objeto de JavaScript.
  • pusher: utilizado para la comunicación con la aplicación Pusher que creó anteriormente.

Una vez hecho esto, el archivo package.json debe ahora este aspecto:

1
{
2
  "name": "ocdmom-server",
3
  "version": "1.0.0",
4
  "description": "",
5
  "main": "server.js",
6
  "scripts": {
7
    "test": "echo \"Error: no test specified\" && exit 1",
8
    "start": "node server.js"
9
  },
10
  "author": "",
11
  "license": "ISC",
12
  "dependencies": {
13
    "body-parser": "^1.18.2",
14
    "express": "^4.16.2",
15
    "pusher": "^1.5.1"
16
  }
17
}

Crear un archivo server.js e importar los paquetes que hemos instalados:

1
var express = require('express');
2
var bodyParser = require('body-parser');
3
var Pusher = require('pusher');

Configurar el servidor para utilizar el paquete body-parser y configurar la carpeta pública como el directorio de archivos estáticos:

1
var app = express();
2
app.use(bodyParser.json()); // set middleware to parse request body to JavaScript object

3
app.use(bodyParser.urlencoded({ extended: false })); // for parsing URL encoded request body

4
app.use(express.static('public')); // specify the directory where the static files like css, JavaScript and image files lives

Inicializar el empujador. Los valores proporcionados aquí vendrá de las variables de entorno. Vamos a añadir ésos más adelante, cuando desplegamos el servidor:

1
var pusher = new Pusher({ 
2
  appId: process.env.APP_ID, 
3
  key: process.env.APP_KEY, 
4
  secret:  process.env.APP_SECRET,
5
  cluster: process.env.APP_CLUSTER, 
6
});

Cuando se accede a la URL base de servir la página de seguimiento:

1
app.get('/', function(req, res){
2
  res.sendFile(__dirname + '/public/tracker.html');
3
});

A continuación, crear la ruta para responder a las peticiones para el endpoint de auth. Esto golpeará cada vez la aplicación inicializa la conexión al empujador, así como cuando se accede a la página de seguimiento. Lo que esto hace es autenticar al usuario para que se puedan comunicar a la aplicación de empuje directamente del lado del cliente.

Tenga en cuenta que esto realmente no tiene las medidas de seguridad en el lugar. Esto significa que cualquier persona puede hacer una petición a su extremo auth si tienen acceso a su clave de aplicación Pusher. En una aplicación de producción, desea seguridad más sólida!

1
app.post('/pusher/auth', function(req, res) {
2
  var socketId = req.body.socket_id;
3
  var channel = req.body.channel_name;
4
  var auth = pusher.authenticate(socketId, channel);  
5
  var app_key = req.body.app_key;
6
7
  var auth = pusher.authenticate(socketId, channel);
8
  res.send(auth);
9
});

Por último, hacer que el servidor escucha el puerto especificado en las variables de entorno. Por defecto, lo del puerto 80, pero nosotros también estamos estableciéndolo como un valor alternativo en caso de que no existe:

1
var port = process.env.PORT || 80;
2
app.listen(port);

Página de Seguimiento

El seguimiento de la página muestra un mapa que se actualiza cada vez que se desencadena el evento client-location de la bobina no olvide suministrar su clave de API de Google:

1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
5
    <meta charset="utf-8">
6
    <title>OCDMom Tracker</title>
7
    <script src="https://js.pusher.com/4.2/pusher.min.js"></script> <!-- the pusher library -->
8
    <link rel="stylesheet" href="css/style.css">
9
  </head>
10
  <body>
11
    <div id="map"></div>
12
    
13
    <script src="js/tracker.js"></script> <!-- the main JavaScript file for this page -->
14
15
    <script async defer
16
    src="https://maps.googleapis.com/maps/api/js?key=YOUR-GOOGLE-API-KEY&callback=initMap"> 
17
    </script> <!-- the google maps library -->
18
  </body>
19
</html>

A continuación, cree un archivo public/js/tracker.js y añadir lo siguiente:

1
function getParameterByName(name, url) {
2
    if (!url) url = window.location.href;
3
    name = name.replace(/[\[\]]/g, "\\$&");
4
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
5
        results = regex.exec(url);
6
    if (!results) return null;
7
    if (!results[2]) return '';
8
    return decodeURIComponent(results[2].replace(/\+/g, " "));
9
}

La función anterior extrae el parámetro de consulta de la URL. El código único (la que se muestra en la aplicación) debe ser incluido como un parámetro de consulta cuando se accede a la URL base del servidor en un navegador. Esto nos permite hacer un seguimiento de la ubicación del usuario porque nosotros Suscríbete al mismo canal que el suscrito por la aplicación.

A continuación, inicializar el Pusher . El código es similar al código en el servidor anterior. La única diferencia es que sólo tenemos que especificar la clave de aplicación Pusher , auth endpoint y cluster:

1
var pusher = new Pusher('YOUR PUSHER APP KEY', {
2
  authEndpoint: 'YOUR PUSHER AUTH ENDPOINT',
3
  cluster: 'YOUR PUSHER CLUSTER',
4
  encrypted: true
5
});

Compruebe si el código se proporciona como un parámetro de consulta y solo suscribiros al canal de Pusher si se suministra:

1
var channel = null;
2
3
if(getParameterByName('code') == null){
4
  alert('Make sure that the code is supplied as a query parameter, then refresh the page.');
5
}else{
6
  channel = pusher.subscribe('private-current-location-' + getParameterByName('code'));
7
}

Añadir la función para inicializar el mapa. Esto mostrará el mapa con un marcador señala a la ubicación por defecto que hemos especificado:

1
var map = null;
2
var marker = null;
3
4
function initMap(){
5
  var myLatLng = { // set the default location displayed on the map

6
    lat: -25.363, 
7
    lng: 131.044
8
  };
9
10
  map = new google.maps.Map(document.getElementById('map'), {
11
    zoom: 16,
12
    center: myLatLng
13
  });
14
15
  marker = new google.maps.Marker({
16
    position: myLatLng,
17
    map: map
18
  });
19
}

Se unen al evento client-location. La función de devolución de llamada es ejecutada cada vez que la aplicación desencadena un evento de client-location que tiene el mismo código único como del usuario como un parámetro de consulta:

1
if(channel){
2
  channel.bind('client-location', function(data) {
3
    console.log('message received: ', data);
4
    var position = new google.maps.LatLng(data.lat, data.lng); // create a new Google maps position object

5
    // set it as the position for the marker and the map

6
    marker.setPosition(position); 
7
    map.setCenter(position);
8
  });
9
}

A continuación, añadir los estilos de la página de seguimiento (public/css/style.css):

1
#map {
2
  height: 100%;
3
}
4
5
html, body {
6
  height: 100%;
7
  margin: 0;
8
  padding: 0;
9
}

Implementar el Servidor

Utilizaremos Now para implementar el servidor. Es gratuito para proyectos de código abierto.

Instalar Now a nivel mundial:

1
npm install now

Una vez instalado, ahora puede Agregar las credenciales de la aplicación Pusher como secretos. Como se mencionó anteriormente, ahora es gratuito para proyectos de código abierto. Esto significa que una vez que el servidor se ha desplegado, su código fuente estará disponible en la ruta /_src. Esto no es muy bueno porque todos pueden ver también las credenciales de la aplicación Pusher. Así que lo que haremos es añadirlos como un secreto de modo que se puede acceder como una variable de entorno.

¿Recuerde que el process.env.APP_ID o process.env.APP_KEY desde el código del servidor antes? Los que se están estableciendo como variables de entorno mediante secretos. pusher_app_id es el nombre asignado al secreto, y YOUR_PUSHER_APP_ID es el ID de su aplicación Pusher. ejecutar los siguientes comandos para añadir su aplicación Pusher credenciales como secretos:

1
now secret add pusher_app_id YOUR_PUSHER_APP_ID
2
now secret add pusher_app_key YOUR_PUSHER_APP_KEY
3
now secret add pusher_app_secret YOUR_PUSHER_APP_SECRET
4
now secret add pusher_app_cluster YOUR_PUSHER_APP_CLUSTER

Una vez que los hayas añadido, ahora puede implementar el servidor. APP_ID es el nombre de la variable de entorno, y pusher_app_id es el nombre del secreto que desea acceder:

1
now -e APP_ID=@pusher_app_id -e APP_KEY=@pusher_app_key -e APP_SECRET=@pusher_app_secret APP_CLUSTER=@pusher_app_cluster

Esto es como una vez lo ha hecho desplegar. La URL devuelve es la dirección URL base del servidor:

deploy serverdeploy serverdeploy server

Copiar la URL al archivo App.js y guardar los cambios:

1
this.pusher = new Pusher('YOUR PUSHER APP KEY', {
2
  authEndpoint: 'https://BASE-URL-OF-YOUR-SERVER/pusher/auth',
3
  cluster: 'YOUR PUSHER APP CLUSTER',
4
  encrypted: true
5
});

En este punto, la aplicación ahora debe ser completamente funcional.

Conclusión

¡Eso es todo! En esta serie de dos partes, ha aprendido a separar un proyecto existente de exposición a ExpoKit. ExpoKit es una buena manera de utilizar algunas de las herramientas que ofrece la plataforma de la Expo mientras su aplicación se convierte ya en un proyecto estándar nativo. Esto le permite utilizar módulos nativos existentes para reaccionar nativo y crear tus propios.

Mientras estás aquí, revisa algunos de nuestros otros posts sobre desarrollo de aplicaciones React Native!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.