Rastreamento geográfico no React Native

Um aplicativo móvel pode atuar como o "local de trabalho" de um funcionário, enquanto pode ser necessário transferir coordenadas geográficas e outros dados. No desenvolvimento de aplicativos de plataforma cruzada no iOS e Android, estruturas como Flutter ou React Native são frequentemente usadas para esta tarefa. Neste artigo, falamos sobre os recursos de trabalho com geolocalização no React Native usando o exemplo do nosso caso.



A confiabilidade, velocidade e maturidade do React Native são algumas vezes criticadas pelos desenvolvedores e, cerca de três anos atrás, essas dúvidas poderiam ser justificadas. No entanto, durante esse período, a tecnologia se tornou mais avançada e o React Native foi reconhecido como uma ferramenta prática para criar uma ampla variedade de aplicativos. Em particular, o React Native é adequado para aplicativos que usam coordenadas geográficas - por exemplo, vários rastreadores, aplicativos para correios, etc.

Também nas lojas são desenvolvidas aplicações React Native de lojas on-line, menus de restaurantes, feeds de notícias, aplicativos de entrega, clientes para redes sociais - assim, um grande número de React Native usa constantemente, sem sequer pensar nisso. Exemplos simples são Facebook, Instagram, Skype, Uber Eats, Wallmart. De acordo com as previsões, a Microsoft pode reabastecer esta lista e transferir seus aplicativos móveis para o React Native, especialmente depois de implementar o suporte para a plataforma Windows. Há Reagir O suporte nativo para Qt , MacOS , "built-in" weechat aplicações , apesar de suporte e documentação para essas plataformas permanece bastante escassos.

O React Native pode fazer quase tudo igual a um aplicativo nativo. Por exemplo, receba informações de sensores de dispositivo, como fazem os aplicativos Java / Kotlin ou ObjC / Swift, ou envie dados em segundo plano usando o Serviço em primeiro plano ou a busca em segundo plano. A única diferença é que no React Native você precisa implementar uma interface para a interação entre a parte nativa e o Javascript. Para tarefas diárias, essas interfaces já estão frequentemente implementadas. Isso também se aplica ao rastreamento da localização e operação do Javascript em segundo plano: já existem soluções na forma de bibliotecas de código aberto independentes. Aconteceu que a comunidade "puxa" o Javascript de forma independente, programadores e empresas estão usando ativamente soluções de código aberto. Poucas comunidades de idiomas possuem o mesmo número de bibliotecas, estruturas,utilitários de qualidade. E, no entanto, no React Native, alguns recursos existentes no desenvolvimento nativo ainda são limitados, e isso deve ser lembrado.

Trabalhar com o React Native


Considere vários fatores principais que garantem a velocidade de desenvolvimento de aplicativos de plataforma cruzada no React Native:

Base de código comum


Uma vez escrita a lógica, as telas e os componentes de layout em diferentes plataformas funcionam e têm a mesma aparência possível (por exemplo, no Android, em vez das sombras usuais, eles usam a noção de exaltação). Praticamente não há dor de cabeça eterna para um desenvolvedor com versões antigas - por exemplo, é fácil adicionar suporte até para o Android 4.4, embora na prática a implementação dessa tarefa também dependa do uso de módulos nativos adicionais.

Fluxo de trabalho ideal


Freqüentemente, o React fornece um fluxo de trabalho ideal que torna o desenvolvimento de novos recursos várias vezes mais rápido do que nos idiomas nativos. Isso se aplica ao layout, abordagem de componentes, instalação de dependências, soluções arquiteturais comuns para o React.

Recarga a quente


O desenvolvedor não precisa recriar o aplicativo todas as vezes para ver as alterações. Graças ao Hot Reload, são necessários apenas alguns segundos para atualizar o aplicativo para o estado atual. E na versão 0.61 Live Reload (agora é Atualização Rápida) foi lembrada adicionalmente, agora, quando as alterações de edição de texto são editadas "on the fly", sem redefinir o estado atual dos componentes.

Ao criar um aplicativo, várias áreas importantes requerem atenção especial:

1) Javascript

O React Native visa trabalhar com Javascript, permitindo que você descreva rapidamente a lógica e as interfaces. Existem muitos módulos prontos do mundo da Web e do Node.js. que podem ser usados ​​da maneira usual (naturalmente, se não estiverem conectados ao DOM ou ao lado do servidor). Apesar de sua alta velocidade, o Javascript às vezes é inferior aos idiomas nativos. Não há multithreading. No React Native, não podemos acessar diretamente a API nativa, embora essa restrição possa ser removida em breve. Javascript descreve principalmente o que precisa ser feito e renderizado na parte nativa.

2) Ponte

Um barramento que aceita chamadas Javascript por meio de interfaces especiais fornecidas pela biblioteca react-native. As chamadas são mensagens serializadas regulares. Para cada componente - uma Visualização simples, um campo de entrada ou uma chamada para a caixa de diálogo do sistema - existe uma interface descrita em Javascript com a lógica implementada na parte nativa. O barramento é a parte mais lenta, é assíncrono, a transferência de dados entre o Javascript e o nativo leva tempo (provavelmente, o Facebook pode se livrar completamente dele). Freqüentemente, os problemas de desempenho dos aplicativos no React Native são causados ​​precisamente pela operação da ponte, mas se você os usar corretamente (reduza a transferência de dados para o mínimo necessário), o desempenho nos aplicativos React Native não diferirá significativamente.

3) A parte nativa

Um aplicativo no React Native é inicialmente um aplicativo nativo comum. A peculiaridade é que todas as bibliotecas necessárias já estão conectadas nela para que você possa escrever toda a lógica no React JS. Aqui, podemos escrever nossa própria lógica nativa para usar (ou não usá-la) em JS, adicionar bibliotecas nativas comuns (por exemplo, para suportar o TLS v1.2 no KitKat e versões anteriores). Em aplicativos nativos prontos, você pode adicionar suporte ao React Native.

Trabalhando com rastreamento geográfico no React Native


Em um dos projetos, precisávamos desenvolver um "local de trabalho móvel" para os funcionários de nossos clientes, em particular, para garantir a transferência de suas coordenadas geográficas em segundo plano.

Existem várias ferramentas para trabalhar com geolocalização no React Native. Por exemplo, este é um pacote da comunidade React Native @ react-native-community / geolocation , que cobre a maioria dos casos de uso, no entanto, não funciona em segundo plano.

Para implementar nossa tarefa, usamos várias soluções, incluindo uma biblioteca com o nome falante @ mauron85 / react-native-background-geolocation. Inicialmente, essa biblioteca era um plug-in para o Cordova, mas depois o autor separou a base e criou wrappers separados para o React Native. Também existe uma biblioteca paga com o mesmo nome da transistorsoft, mas no momento do nosso trabalho no projeto, ela ganhou apenas com a documentação.

A biblioteca nos permitiu definir configurações flexíveis para rastrear a localização. Por exemplo, com que frequência interrogar um serviço do sistema, como exatamente trabalhar em segundo plano, em que raio a posição será considerada imóvel. As configurações e os métodos para enviar essas coordenadas para o servidor podem ser usados ​​"prontos para uso", mas decidimos não enviar solicitações de spam, mas agregar as coordenadas recebidas no repositório e enviá-las com um grande intervalo. Ao mesmo tempo, a biblioteca nos permitiu lançar nosso aplicativo como atividade em primeiro plano, poupando-nos de dores de cabeça desnecessárias, pois em muitos dispositivos Android os aplicativos em segundo plano podem funcionar apenas com configurações adicionais ( Huawei, MIUI, Samsung recentemente ).

Após a instalação, você pode criar um componente ou apenas um auxiliar que gerencia o serviço. Decidimos usar o componente para montá-lo com as condições do roteador e conectá-lo facilmente ao redux. Configure nosso serviço:

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();
};


Vimos que aqui também é possível definir configurações para a notificação, um ícone (de ativos nativos). E as permissões? Para o Android, depois de instalar o pacote, nada é necessário, a biblioteca assume os pedidos de acesso à geolocalização do sistema. Mas, para operação normal no iOS no Xcode, você também precisa habilitar o processamento em segundo plano e as atualizações de local na guia Assinatura e recursos do projeto.



Implementamos o método principal para salvar e enviar coordenadas no evento on ('location') no mesmo método. Ele funcionará tanto com o aplicativo ativo quanto no 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);  //   !
    });
});


Aqui chamamos ação da loja, onde transferimos os dados das coordenadas em um formato personalizado, além de armazenar dados nas leituras da bateria, usando a biblioteca react-native-device-info. Tudo isso funciona igualmente bem no Android e iOS quando o aplicativo está ativo ou em segundo plano.

Além disso, existem métodos para obter o local atual (mas isso só funciona quando o serviço está sendo executado), assinando transições do estado do aplicativo de ativo para segundo plano, alternando para as configurações do sistema do aplicativo. No entanto, em geral, o mais necessário é dado nesses exemplos.

O resultado é um componente que pode ser montado, por exemplo, apenas para a peça 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;
  }
} 


Se a navegação de reação for usada, você poderá criar a navegação para a peça autorizada da seguinte maneira:

//  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;


Além disso, este navegador pode ser usado da maneira usual no navegador raiz:

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

export default createAppContainer(RootNavigator);


Assim, o serviço de geolocalização e troca de dados funcionará apenas na parte autorizada do aplicativo.

Resumir


Neste artigo, examinamos os recursos do uso do React Native em aplicativos de geolocalização. Como descobrimos, usando essa estrutura, os desenvolvedores agora podem rastrear facilmente as coordenadas geográficas do dispositivo - por exemplo, em rastreadores de bicicleta, aplicativos para correios e despachantes, aplicativos para escolher imóveis etc. A biblioteca cobre a maioria dos casos relacionados ao rastreamento geográfico, em particular, permite ajustar os intervalos e economizar energia do dispositivo, funciona de forma estável em segundo plano nas duas plataformas e suporta a execução automática no Android. Ao mesmo tempo, para aplicativos complexos, como regra, o desenvolvimento nativo é mais adequado (por exemplo, para trabalhar com cálculos e widgets, como já escrevemos no artigo anterior ).

Agradecemos sua atenção. Esperamos que o artigo tenha sido útil para você!

All Articles