Fermer

septembre 25, 2019

Suivi d'emplacement en temps réel avec React Native et PubNub –


Avec l'utilisation croissante des applications mobiles, les fonctionnalités de géolocalisation et de suivi sont présentes dans la majorité des applications. Le suivi en temps réel de la géolocalisation joue un rôle important dans de nombreux services à la demande, tels que ceux-ci:

  • services de taxi comme Uber, Lyft ou Ola
  • services de livraison de produits alimentaires tels que Uber Eats, Foodpanda ou Zomato
  • drones

Dans ce guide, nous allons utiliser React Native pour créer des applications de suivi de localisation en temps réel. Nous allons créer deux applications natives React. L'une agira comme une application de suivi (appelée «application de suivi») et l'autre sera celle qui est suivie («application Trackee»).

Voici à quoi ressemblera le résultat final de ce tutoriel:

apprendre Réagir Autochtone à partir de zéro? Cet article est un extrait de notre bibliothèque Premium. Obtenez une collection complète de livres natifs de React couvrant les bases, les projets, les astuces, les outils et plus avec SitePoint Premium. Inscrivez-vous maintenant pour seulement 9 $ par mois .

Prérequis

Ce tutoriel nécessite une connaissance de base de React Native. Pour configurer votre machine de développement, suivez le guide officiel ici .

Mis à part React Native, nous utiliserons également PubNub un service tiers fournissant des informations réelles. transfert de données de temps et mises à jour. Nous utiliserons ce service pour mettre à jour les coordonnées de l'utilisateur en temps réel.

Enregistrez-vous pour un compte PubNub gratuit ici .

Puisque nous allons utiliser Google Maps sur Android, nous allons également vous avez besoin d’une clé d’API Google Maps, que vous pouvez obtenir sur la page Google Maps Obtenir la clé d’API .

Pour vous assurer que la page est bien identique, voici les versions utilisées dans ce tutoriel: 19659014] Nœud v10.15.0

  • npm 6.4.1
  • fil 1.16.0
  • réactif natif 0.59.9
  • réact-natif-maps 0.24.2
  • pubnub-réact 1.2.0 [19659020] Pour commencer

    Si vous souhaitez consulter immédiatement le code source de nos applications Tracker et Trackee, voici leurs liens GitHub:

    Commençons par l'application Trackee:

    L'application Trackee [19659009] Pour créer un nouveau projet utilisant react-native-cli tapez ceci dans le terminal:

     $ react-native init trackeeApp
    
     $ cd trackeeApp
    

    Passons maintenant à la partie amusante – le codage.

    Ajoutez React Native Maps

    Comme nous allons utiliser Maps dans notre application, nous avons besoin d’une bibliothèque pour cela. Nous utiliserons réagissent-natif-cartes .

    Installez réactif-natif-cartes en suivant les instructions d’installation ici .

    Ajouter PubNub [AjoutparPubNub[19659029] Outre les cartes, nous allons également installer le SDK PubNub React pour transférer nos données en temps réel:

     $ yarn add pubnub-react
    

    Après cela, vous pouvez maintenant lancer l'application:

     $ react-native run-ios
    $ react-native run-android
    

    Vous devriez voir quelque chose comme ceci sur votre simulateur / émulateur:

     Application Trackee

    Code Trackee

    Ouvrez maintenant le fichier App.js et les importations suivantes:

     import Réagit de "réagit";
    importer {
      Feuille de style,
      Vue,
      Plate-forme,
      Dimensions,
      SafeAreaView
    } de "react-native";
    importer MapView, {Marker, AnimatedRegion} de "react-native-maps";
    import PubNubReact de "pubnub-react";
    

    Outre MapView, qui rendra la carte dans notre composant, nous avons importé les marqueurs et de la région animée de react-native-mas . [19659006] Le marqueur identifie un emplacement sur une carte. Nous l'utilisons pour identifier l'emplacement de l'utilisateur sur la carte.

    AnimatedRegion nous permet d'utiliser l'API animée pour contrôler le centre et le zoom de la carte.

    Après avoir importé le composant nécessaire, nous allons définir des constantes et des valeurs initiales pour nos cartes:

     const {width, height} = Dimensions.get ("window");
    
    const ASPECT_RATIO = largeur / hauteur;
    const LATITUDE = 37,78825;
    const LONGITUDE = -122,4324;
    const LATITUDE_DELTA = 0.0922;
    const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
    

    Ensuite, nous définirons notre composant de classe avec certains états, méthodes de cycle de vie et méthodes d’aide personnalisées:

     La classe par défaut d’exportation App étend React.Component {
      constructeur (accessoires) {
        super (accessoires);
    
        this.state = {
          latitude: LATITUDE,
          longitude: LONGITUDE,
          coordonne: new AnimatedRegion ({
            latitude: LATITUDE,
            longitude: LONGITUDE,
            latitudeDelta: 0,
            longitudeDelta: 0
          })
        };
    
        this.pubnub = new PubNubReact ({
          publishKey: "X",
          subscribeKey: "X"
        });
        this.pubnub.init (this);
      }
    
      composantDidMount () {
        this.watchLocation ();
      }
    
      composantDidUpdate (prevProps, prevState) {
        if (this.props.latitude! == prevState.latitude) {
          this.pubnub.publish ({
            message: {
              latitude: this.state.latitude,
              longitude: this.state.longitude
            },
            canal: "emplacement"
          });
        }
      }
    
      composantWillUnmount () {
        navigator.geolocation.clearWatch (this.watchID);
      }
    
      watchLocation = () => {
        const {coordonnée} = this.state;
    
        this.watchID = navigator.geolocation.watchPosition (
          position => {
            const {latitude, longitude} = position.coords;
    
            const newCoordinate = {
              latitude,
              longitude
            };
    
            if (Platform.OS === "android") {
              if (this.marker) {
                this.marker._component.animateMarkerToCoordinate (
                  nouveauCoordinate,
                  500 // 500 est la durée pour animer le marqueur
                )
              }
            } autre {
              Coordinate.timing (newCoordinate) .start ();
            }
    
            this.setState ({
              latitude,
              longitude
            });
          },
          error => console.log (erreur),
          {
            enableHighAccuracy: true,
            délai d'attente: 20000,
            maximumAge: 1000,
            distanceFilter: 10
          }
        )
      };
    
      getMapRegion = () => ({
        latitude: this.state.latitude,
        longitude: this.state.longitude,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA
      });
    
      render () {
        revenir (
          
            
              
                  {
                    this.marker = marqueur;
                  }}
                  Coordinate = {this.state.coordinate}
                />
              
            
          
        );
      }
    }
    
    const styles = StyleSheet.create ({
      récipient: {
        ... StyleSheet.absoluteFillObject,
        justifierContent: "flex-end",
        alignItems: "center"
      },
      carte: {
        ... StyleSheet.absoluteFillObject
      }
    });
    

    Ouf! C’est beaucoup de code, parcourons-le donc petit à petit.

    Premièrement, nous avons initialisé un état local dans notre constructeur () . Nous allons également initialiser une instance de PubNub:

     constructor (props) {
      super (accessoires);
    
      this.state = {
        latitude: LATITUDE,
        longitude: LONGITUDE,
        coordonne: new AnimatedRegion ({
          latitude: LATITUDE,
          longitude: LONGITUDE,
          latitudeDelta: 0,
          longitudeDelta: 0,
        }),
      };
    
      // Initialiser PubNub
      this.pubnub = new PubNubReact ({
        publishKey: 'X',
        subscribeKey: 'X',
      });
    
      this.pubnub.init (this);
    }
    

    Vous devrez remplacer "X" par vos propres clés de publication et d’abonnement PubNub. Pour obtenir vos clés, connectez-vous à votre compte PubNub et accédez au tableau de bord.

    Vous y trouverez une application Demo Project déjà disponible. Vous êtes libre de créer une nouvelle application, mais nous allons utiliser ce projet Demo

    pour copier et coller les clés dans l'instance du constructeur PubNub.

    Après cela, nous ' Vous utiliserez la composantDidMount () Lifecycle pour appeler la méthode watchLocation :

     composantDidMount () {
      this.watchLocation ();
    }
    
    watchLocation = () => {
      const {coordonnée} = this.state;
    
      this.watchID = navigator.geolocation.watchPosition (
        position => {
          const {latitude, longitude} = position.coords;
    
          const newCoordinate = {
            latitude,
            longitude,
          };
    
          if (Platform.OS === 'android') {
            if (this.marker) {
              this.marker._component.animateMarkerToCoordinate (newCoordinate, 500); // 500 est la durée pour animer le marqueur
            }
          } autre {
            Coordinate.timing (newCoordinate) .start ();
          }
    
          this.setState ({
            latitude,
            longitude,
          });
        },
        error => console.log (erreur),
        {
          enableHighAccuracy: true,
          délai d'attente: 20000,
          maximumAge: 1000,
          distanceFilter: 10,
        }
      )
    };
    

    watchLocation utilise l’API de géolocalisation pour observer les changements de coordonnées de localisation de l’utilisateur. Ainsi, chaque fois que l'utilisateur se déplace et que ses coordonnées de position changent, watchPosition renvoie les nouvelles coordonnées de l'utilisateur.

    La watchPosition accepte deux paramètres: options et callback .

    Comme options, nous allons définir enableHighAccuracy à true pour une grande précision, et distanceInterval à 10 pour recevoir des mises à jour uniquement lorsque l'emplacement a changé d'au moins dix mètres. Si vous voulez une précision maximale, utilisez 0 mais sachez qu'il utilisera davantage de bande passante et de données.

    Dans le callback nous obtenons les coordonnées de position et nous les appelons use this coordonnées pour définir les variables d'état locales.

     const {latitude, longitude} = position.coords;
    
    this.setState ({
      latitude,
      longitude
    });
    

    Maintenant que nous avons les coordonnées de l'utilisateur, nous les utiliserons pour ajouter un marqueur sur la carte, puis le mettrons à jour en permanence, au fur et à mesure que les coordonnées de l'utilisateur changeront de position.

    Pour cela, nous allons utiliser . ] animateMarkerToCoordinate () pour Android et Coordinated.timing () pour iOS. Nous allons passer un objet nouveauCoordinate avec latitude et longitude en tant que paramètre pour ces méthodes:

     if (Platform.OS === "android" ) {
      if (this.marker) {
        this.marker._component.animateMarkerToCoordinate (newCoordinate, 500); // 500 est la durée pour animer le marqueur
      }
    } autre {
      Coordinate.timing (newCoordinate) .start ();
    }
    

    Nous souhaitons également que les coordonnées de l’utilisateur soient envoyées en continu à notre application Tracker. Pour ce faire, nous allons utiliser la méthode du cycle de vie du composant [14909023] de React:

    : 

     componentDidUpdate (prevProps, prevState) {
      if (this.props.latitude! == prevState.latitude) {
        this.pubnub.publish ({
          message: {
            latitude: this.state.latitude,
            longitude: this.state.longitude,
          },
          canal: 'emplacement',
        });
      }
    }
    

    Le composantDidUpdate est invoqué immédiatement après la mise à jour. Ainsi, il sera appelé chaque fois que les coordonnées de l'utilisateur sont modifiées.

    Nous utilisons également une condition si pour publier les coordonnées uniquement lorsque la latitude est modifiée.

    Nous avons ensuite appelé PubNub [ publier méthode pour publier les coordonnées, ainsi que le nom du canal localisation nous souhaitons publier ces coordonnées.

    Remarque: assurez-vous que le nom du canal est bien est la même dans les deux applications. Sinon, vous ne recevrez aucune donnée.

    Maintenant que nous avons terminé avec toutes les méthodes requises, rendons notre MapView . Ajoutez ce code dans votre méthode de rendu :

     return (
      
        
          
              {
                this.marker = marqueur;
              }}
              Coordinate = {this.state.coordinate}
            />
          
        
      
    );
    

    Nous avons utilisé Marker.Animated qui se déplacera de manière animée à mesure que les utilisateurs se déplacent et que leurs coordonnées changent.

     composantWillUnmount () {
      navigator.geolocation.clearWatch (this.watchID);
    }
    

    Nous allons également effacer toute méthode de surveillance de géolocalisation dans ComponentWillUnmount () pour éviter toute fuite de mémoire.

    Terminons l'application Trackee en ajoutant quelques styles:

     const styles = StyleSheet.create ({
      récipient: {
        ... StyleSheet.absoluteFillObject,
        justifierContent: "flex-end",
        alignItems: "center"
      },
      carte: {
        ... StyleSheet.absoluteFillObject
      }
    });
    

    Puisque nous voulons que notre carte couvre tout l'écran, nous devons utiliser le positionnement absolu et régler chaque côté à zéro ( position: 'absolute', gauche: 0, droite: 0, haut: 0, bas: 0 ).

    La feuille de style fournit absoluteFill qui peut être utilisée à des fins pratiques et pour réduire la duplication de ces styles répétés.

    Exécution de l'application Trackee

    nous allons plus loin, c'est toujours une bonne idée de tester notre application. Pour ce faire, procédez comme suit:

    Sur iOS

    Si vous utilisez un simulateur iOS, vous avez de la chance. Il est très facile de tester cette fonctionnalité dans iOS par rapport à Android.

    Dans les paramètres de votre simulateur iOS, accédez à Debug > Emplacement > Freeway Drive et actualisez-le votre application ( Cmd + R ). Vous devriez voir quelque chose comme ceci:

     Application Trackee

    sur Android

    Malheureusement pour Android, il n’existe aucun moyen simple de tester cette fonctionnalité.

    Vous pouvez utiliser des applications tierces pour imiter la localisation GPS. applications. J'ai trouvé le GPS Joystick très utile

    . Vous pouvez également utiliser Genymotion qui dispose d'un utilitaire permettant de simuler l'emplacement.

    Testing on PubNub

    Pour vérifier si PubNub reçoit des données, vous pouvez activer l'analyse en temps réel, qui indique le nombre de messages que votre application reçoit ou envoie.

    Dans l'onglet Clés allez au bas de la page et tournez sur Analyse en temps réel . Ensuite, allez dans Real-time Analytics pour vérifier si les données sont reçues.

    Ceci est tout ce que l'application Trackee doit faire, alors passons à l'application Tracker.

    Tracker App

    Suivez le même processus. Suivez les mêmes étapes que pour l'application Trackee et créez un nouveau projet React Native appelé trackerApp .

    Les applications Tracker et Trackee partagent la majorité de leur code.

    La seule différence est que dans trackerApp nous obtiendrons les coordonnées de localisation de trackeeApp via PubNub.

    Ajoutez le pubnub-react SDK, importez et initialisez comme nous l'avons fait dans l'application Trackee.

    Dans composantDidMount () ajoutez ce qui suit:

     // mêmes importations que trackeeApp
    
    composantDidMount () {
      /* retirer
        watchLocation = () => {}
      * /
    
     // ajouter:
      this.subscribeToPubNub ();
    }
    
    // ajouter:
    subscribeToPubNub = () => {
      this.pubnub.subscribe ({
        canaux: ['location'],
        withPresence: true,
      });
      this.pubnub.getMessage ('location', msg => {
        const {coordonnée} = this.state;
        const {latitude, longitude} = msg.message;
        const newCoordinate = {latitude, longitude};
    
        if (Platform.OS === 'android') {
          if (this.marker) {
            this.marker._component.animateMarkerToCoordinate (newCoordinate, 500);
          }
        } autre {
          Coordinate.timing (newCoordinate) .start ();
        }
    
        this.setState ({
          latitude,
          longitude,
        });
      });
    };
    
    /* retirer
    watchLocation = () => {
    }
    * /
    

    Voici l'aperçu du code mis à jour de l'application Tracker

    . Dans le code ci-dessus, nous utilisons la méthode de souscription de PubNub pour souscrire à notre . ] emplacement dès que le composant est monté.

    Après cela, nous utilisons getMessage pour obtenir les messages reçus sur ce canal.

    Nous utiliserons ces coordonnées pour mettre à jour la MapView de l'application Tracker.

    Puisque les deux applications partagent le même jeu de coordonnées, nous devrions pouvoir voir les coordonnées de l'application Trackee dans l'application Tracker.

    Lancer les deux applications ensemble

    Enfin, nous sommes à la dernière étape. Il n'est pas simple de tester les deux applications sur la même machine en mode de développement.

    Pour tester les deux applications sur une machine iOS, je vais suivre ces étapes:

    1. Nous allons exécuter l'application Trackee sur le simulateur iOS depuis, il a le mode débogage où je peux simuler un véhicule en mouvement. Je vais aussi le lancer en mode release car il est impossible d’exécuter deux paquets en même temps:

       $ react-native run-ios --configuration Release
      

      Maintenant, allez à Débogage > Emplacement > de Freeway Drive .

    2. Nous allons exécuter l’application Tracker sur l’émulateur Android:

       $ react-native run-android
      

    L'application Tracker devrait maintenant être en mesure de voir le Marker se déplacer comme dans l'application Trackee

    Vous pouvez trouver le code source des deux applications sur GitHub

    . Conclusion

    Ceci est juste une implémentation très basique des services de localisation en temps réel. Nous ne faisons que gratter la surface avec ce que nous pouvons réaliser avec le suivi de localisation. En réalité, les possibilités sont infinies. Par exemple:

    • Vous pouvez créer un service de repérage comme Uber, Lyft, etc.
    • À l'aide du suivi de l'emplacement, vous pouvez suivre vos commandes telles que des aliments ou des produits d'épicerie auprès du vendeur local.
    • Vous pouvez également suivre l'emplacement de vos enfants (utile pour les parents ou les enseignants).
    • Vous pouvez suivre les animaux dans un parc national protégé.

    Si vous utilisez ceci pour créer votre propre implémentation du suivi de localisation, j'aimerais voir les résultats. Faites-moi savoir sur Twitter .






  • Source link