Geo-tracking en React Native

Una aplicación móvil puede actuar como el "lugar de trabajo" de un empleado, mientras que puede ser necesario transferir coordenadas geográficas y otros datos. En el desarrollo de aplicaciones multiplataforma en iOS y Android, a menudo se utilizan marcos como Flutter o React Native para esta tarea. En este artículo, hablamos sobre las características de trabajar con geolocalización en React Native usando el ejemplo de nuestro caso.



La confiabilidad, la velocidad y la madurez de React Native a veces son criticadas por los desarrolladores, y hace aproximadamente tres años tales dudas podrían llamarse justificadas. Sin embargo, durante este tiempo, la tecnología se ha vuelto más avanzada, y React Native ha sido reconocido como una herramienta práctica para crear una amplia gama de aplicaciones. En particular, React Native es adecuado para aplicaciones que utilizan coordenadas geográficas, por ejemplo, varios rastreadores, aplicaciones para correos, etc.

También en las tiendas se desarrollan aplicaciones React Native de tiendas en línea, menús de restaurantes, canales de noticias, aplicaciones de entrega, clientes para redes sociales, por lo tanto, una gran cantidad de React Native usa constantemente, sin siquiera pensarlo. Ejemplos simples son Facebook, Instagram, Skype, Uber Eats, Wallmart. Según las previsiones, Microsoft puede reponer esta lista y transferir sus aplicaciones móviles a React Native, especialmente después de que haya implementado el soporte para la plataforma Windows. Existe soporte de React Native para Qt , macOS , aplicaciones weechat " incorporadas " , aunque el soporte y la documentación para estas plataformas sigue siendo bastante escasa.

React Native puede hacer casi todo lo mismo que una aplicación nativa. Por ejemplo, reciba información de los sensores del dispositivo, como lo hacen las aplicaciones Java / Kotlin u ObjC / Swift, o envíe datos en segundo plano mediante el Servicio en primer plano o la búsqueda en segundo plano. La única diferencia es que en React Native necesita implementar una interfaz para la interacción entre la parte nativa y Javascript. Para las tareas cotidianas, estas interfaces a menudo ya están implementadas. Esto también se aplica al seguimiento de la ubicación y el funcionamiento de Javascript en segundo plano: ya existen soluciones en forma de bibliotecas independientes de código abierto. Dio la casualidad de que la comunidad "jala" JavaScript de forma independiente, tanto los programadores como las empresas están utilizando activamente soluciones de código abierto. Pocas comunidades lingüísticas cuentan con el mismo número de bibliotecas, marcos,Utilidades de calidad. Y, sin embargo, en React Native, algunas características que existen en el desarrollo nativo siguen siendo limitadas, y esto debe recordarse.

Trabaja con React Native


Considere varios factores clave que aseguran la velocidad de desarrollo de aplicaciones multiplataforma en React Native:

Código base común


Una vez escrita la lógica, las pantallas de diseño y los componentes en diferentes plataformas funcionan y tienen el mismo aspecto posible (por ejemplo, en Android, en lugar de las sombras habituales, utilizan la noción de euforia). Prácticamente no hay dolor de cabeza eterno para un desarrollador con versiones antiguas; por ejemplo, es fácil agregar soporte incluso para Android 4.4, aunque en la práctica la implementación de esta tarea también depende del uso de módulos nativos adicionales.

Flujo de trabajo óptimo


A menudo, React proporciona un flujo de trabajo óptimo que hace que el desarrollo de nuevas funciones sea varias veces más rápido que en los idiomas nativos. Esto se aplica al diseño, enfoque de componentes, instalación de dependencia, soluciones arquitectónicas comunes para React.

Recarga en caliente


El desarrollador no necesita reconstruir la aplicación cada vez para ver los cambios. Gracias a Hot Reload, lleva solo un par de segundos actualizar la aplicación al estado actual. Y en la versión 0.61, Live Reload (ahora es Fast Refresh) también se trajo a la mente, ahora cuando se editan los cambios de composición tipográfica "al vuelo", sin restablecer el estado actual de los componentes.

Al crear una aplicación, varias áreas clave requieren atención especial:

1) Javascript

React Native tiene como objetivo trabajar con Javascript, lo que le permite describir rápidamente la lógica y las interfaces. Hay muchos módulos listos para usar del mundo de Web y Node.js que se pueden usar de la manera habitual (naturalmente, si no están conectados al DOM o al lado del servidor). A pesar de su alta velocidad, Javascript a veces es inferior a los idiomas nativos. No hay multihilo. En React Native, no podemos acceder directamente a la API nativa, aunque esta restricción puede eliminarse pronto. Javascript describe principalmente lo que debe hacerse y representarse en la parte nativa.

2) puente

Un bus que acepta llamadas Javascript a través de interfaces especiales proporcionadas por la biblioteca react-native. Las llamadas son mensajes serializados regulares. Para cada componente, una vista simple, un campo de entrada o una llamada al cuadro de diálogo del sistema, hay una interfaz descrita en Javascript con la lógica implementada en la parte nativa. El bus es la parte más lenta, es asíncrono, la transferencia de datos entre Javascript y el nativo lleva tiempo (aparentemente, Facebook puede deshacerse de él). A menudo, los problemas de rendimiento de las aplicaciones en React Native son causados ​​precisamente por la operación del puente, pero si lo usa correctamente (reduzca la transferencia de datos de un lado a otro al mínimo necesario), el rendimiento en las aplicaciones de React Native no diferirá significativamente.

3) La parte nativa

Una aplicación en React Native es inicialmente una aplicación nativa ordinaria. La peculiaridad es que todas las bibliotecas necesarias ya están conectadas en él para que pueda escribir toda la lógica en React JS. Aquí podemos escribir nuestra propia lógica nativa para usarla (o no usarla) en JS, agregar bibliotecas nativas comunes (por ejemplo, para admitir TLS v1.2 en KitKat y versiones anteriores). En aplicaciones nativas listas para usar, puede agregar soporte para React Native.

Trabajar con seguimiento geográfico en React Native


En uno de los proyectos, necesitábamos desarrollar un "lugar de trabajo móvil" para los empleados de nuestros clientes, en particular, para garantizar la transferencia de sus coordenadas geográficas en segundo plano.

Hay varias herramientas para trabajar con geolocalización en React Native. Por ejemplo, este es un paquete de la comunidad React Native @ react-native-community / geolocation , que cubre la mayoría de los casos de uso, sin embargo, no funciona en segundo plano.

Para implementar nuestra tarea, utilizamos varias soluciones, incluida una biblioteca con el nombre de habla @ mauron85 / react-native-background-geolocation. Inicialmente, esta biblioteca era un complemento para Cordova, pero luego el autor separó la base e hizo envoltorios separados para React Native. También hay una biblioteca paga del mismo nombre de transistorsoft, pero en el momento de nuestro trabajo en el proyecto, solo ganó con su documentación.

La biblioteca nos permitió establecer configuraciones flexibles para el seguimiento de la ubicación. Por ejemplo, con qué frecuencia interrogar a un servicio del sistema, cómo trabajar en segundo plano, en qué radio la posición se considerará inmóvil. La configuración y los métodos para enviar estas coordenadas al servidor podrían usarse "fuera de la caja", pero decidimos no enviar solicitudes de spam, sino agregar las coordenadas recibidas en el repositorio y enviarlas con un intervalo grande. Al mismo tiempo, la biblioteca nos permitió lanzar nuestra aplicación como actividad en primer plano, lo que nos salvó de dolores de cabeza innecesarios, ya que en muchos dispositivos Android las aplicaciones en segundo plano solo pueden funcionar con configuraciones adicionales ( Huawei, MIUI, Samsung recientemente ).

Después de la instalación, puede crear un componente o simplemente un ayudante que administre el servicio. Decidimos usar el componente para montarlo con las condiciones del enrutador y conectarlo fácilmente a redux. Configura nuestro servicio:

import BackgroundGeolocation, {
  Location,
} from '@mauron85/react-native-background-geolocation';
 
class ForegroundService extends PureComponent<Props> {
//...
startBackgroundService = (config: GeotrackerConfig) => {
     //    
	BackgroundGeolocation.configure({
  	desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY,
  	stationaryRadius: 50,
  	distanceFilter: config.distance,
  	notificationTitle: Strings.Geolocation.NOTIFICATION_TITLE,
  	notificationText: Strings.Geolocation.NOTIFICATION_DESCRIPTION,
  	debug: false,
  	startOnBoot: false,
  	stopOnTerminate: true,
  	locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER,
  	interval: this.runnerInterval,
  	fastestInterval: 10000,
  	activitiesInterval: 30000,
  	stopOnStillActivity: false,
  	notificationIconColor: Colors.primary,
  	notificationIconSmall: 'notification_icon',
	});
 
     //    start()      
                    	BackgroundGeolocation.on('authorization', status => {
  	if (status !== BackgroundGeolocation.AUTHORIZED) {
    	//   
  	} else if (status.hasPermissions) {
        // hasPermission -  ,    
  	}
	});
 
     //  
                    	BackgroundGeolocation.start();
};


Vemos que aquí también puede establecer configuraciones para la notificación, un ícono (de activos nativos). ¿Qué pasa con los permisos? Para Android, después de instalar el paquete, no se requiere nada, la biblioteca se hará cargo de las solicitudes de acceso a la geolocalización del sistema. Pero para el funcionamiento normal en iOS en Xcode, también debe habilitar el procesamiento en segundo plano y las actualizaciones de ubicación en la pestaña Firma y capacidades del proyecto.



Implementamos el método principal para guardar y enviar coordenadas en el evento on ('ubicación') en el mismo método. Funcionará tanto con la aplicación activa como en el estado minimizado:

BackgroundGeolocation.on('location', location => {
    BackgroundGeolocation.startTask(async taskKey => {
     //       ,
     //     iOS-
      const batteryLevel = this.isSimulator
        ? 100
        : (await DeviceInfo.getBatteryLevel()) * 100;
      const updateDelta = location.time - this.lastUpdateAt;

     //      
      this.props.locationUpdate(location);
      this.props.locationAddTrackerData({
        altitude: location.altitude,
        batteryChargeLevel: batteryLevel,
        latitude: location.latitude,
        longitude: location.longitude,
        course: location.bearing,
        accuracy: location.accuracy,
        speed: location.speed,
        timestamp: Number(String(location.time).substr(0, 10)),
        isAlertOn: false,
      });

     //  ?
      if (updateDelta / 1000 > config.sendInterval) {
        this.syncDataWithInterval();
        this.lastUpdateAt = location.time;
      }

     //    AsyncStorage,    
      Storage.setLastKnownLocation(location);
      BackgroundGeolocation.endTask(taskKey);  //   !
    });
});


Aquí llamamos a la acción desde la tienda, donde transferimos los datos de coordenadas en un formato personalizado, almacenando adicionalmente datos en las lecturas de la batería, usando la biblioteca react-native-device-info. Todo esto funciona igualmente bien en Android e iOS cuando la aplicación está activa o en segundo plano.

Además, existen métodos para obtener la ubicación actual (pero esto solo funciona cuando el servicio se está ejecutando), suscribiéndose a las transiciones del estado de la aplicación de activo a segundo plano, cambiando a la configuración del sistema de la aplicación. Sin embargo, en general, lo más necesario se da en estos ejemplos.

El resultado es un componente que se puede montar, por ejemplo, solo para la parte autorizada:

class ForegroundService extends PureComponent<Props> {
	//...
	componentDidMount() {
		this.startBackgroundService(this.props.config);
	}

	componentWillUnmount() {
    BackgroundGeolocation.stop();
    BackgroundGeolocation.removeAllListeners();
  }

	startBackgroundService = (config: GeotrackerConfig) => {
    BackgroundGeolocation.configure({
		// ...
	};

	render() {
    return null;
  }
} 


Si se utiliza react-navigation, puede crear navegación para la parte autorizada de la siguiente manera:

//  StackNavigator   
const Navigator = createStackNavigator(RouteConfigs, NavigatorConfig);


class AppNavigator extends PureComponent<Props> {
  static router: NavigationRouter = Navigator.router;

  componentDidMount(): void {
    SplashScreen && SplashScreen.hide();
  }

  render() {
    return (
      <>
        <ForegroundService navigation={this.props.navigation} />
        <Navigator {...this.props} />
      </>
    );
  }
}

export default AppNavigator;


Además, este navegador se puede usar de la manera habitual en el navegador raíz:

const RootNavigator = createSwitchNavigator(
  {
    Auth: AuthNavigator,
    App: AppNavigator,
  },
  {
    initialRouteName: 'Auth',
  },
);

export default createAppContainer(RootNavigator);


Por lo tanto, el servicio de geolocalización e intercambio de datos solo funcionará en la parte autorizada de la aplicación.

Para resumir


En este artículo, examinamos las características del uso de React Native en aplicaciones de geolocalización. Como descubrimos, utilizando este marco, los desarrolladores ahora pueden rastrear fácilmente las coordenadas geográficas del dispositivo, por ejemplo, en rastreadores de bicicletas, aplicaciones para correos y reenviadores, aplicaciones para elegir bienes raíces, etc. La biblioteca cubre la mayoría de los casos relacionados con el geotracking, en particular, le permite ajustar los intervalos y guardar la carga del dispositivo, funciona de manera estable en segundo plano en ambas plataformas y admite la ejecución automática en Android. Al mismo tiempo, para aplicaciones complejas, por regla general, el desarrollo nativo es más adecuado (por ejemplo, para trabajar con cálculos y widgets, como ya escribimos en el artículo anterior ).

Gracias por su atención, ¡esperamos que el artículo le haya sido útil!

All Articles