4 votes

Comment récupérer les publications qui se trouvent à moins de 0,5 km de ma portée ?

Je suis en train de sauvegarder les coordonnées de la publication des utilisateurs. Je génère un identifiant de poussée et l'utilise ensuite pour sauvegarder à la fois les données de la publication et les coordonnées géographiques avec GeoFire.

Je veux afficher seulement les publications qui se trouvent dans un rayon de 0,5 km. J'utilise la bibliothèque GeoFire pour cela mais je n'arrive pas à accomplir la tâche.

Voici comment je génère l'identifiant de poussée:

itemID = databaseReferenceRequests.push().getKey();

Voici comment je l'utilise pour sauvegarder les coordonnées géographiques ainsi que les données des publications:

geoFire.setLocation(itemID, 
        new GeoLocation(Double.parseDouble(currentLat.getText().toString()), 
        Double.parseDouble(currentLng.getText().toString())));

databaseReferenceRequests.child(itemID).setValue(hRequest);

Il est sauvegardé comme ceci:

enter image description here

Le problème est que lorsque j'essaie de récupérer seulement les publications qui se trouvent dans un rayon de 0,5 km, cela ne se produit pas et toutes les publications, qu'elles soient proches ou éloignées, sont récupérées.

Voici comment je le récupère:

public void retrieveHelpRequests() {

            geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLatDouble, currentLngDouble), 0.5);

            geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
                @Override
                public void onKeyEntered(String key, GeoLocation location) {
                    databaseReference.child("help-requests").addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        Map newRequest = (Map) dataSnapshot.getValue();
                        imageUID = newRequest.get("imageUIDh");
                        homelessDescription = newRequest.get("homelessDescription");
                        currentLat = newRequest.get("currentLat");
                        currentLng = newRequest.get("currentLng");
                        postedBy = newRequest.get("postedBy");
                        postedAtTime = newRequest.get("postedAtTime");
                        postedOnDate = newRequest.get("postedOnDate");
                        utcFormatDateTime = newRequest.get("utcFormatDateTime");

                        String timeStr = utcFormatDateTime;
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        df.setTimeZone(TimeZone.getTimeZone("UTC"));
                        Date date = null;
                        try {
                            // erreur à la ligne ci-dessous
                            date = df.parse(timeStr);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        df.setTimeZone(TimeZone.getDefault());
                        final String persisted = df.format(date);

                        // Analyser la chaîne de la DB - fuseau horaire UTC
                        Date parsed = null;
                        try {
                            parsed = df.parse(persisted);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }

                        // Maintenant convertir en n'importe quel fuseau horaire à des fins d'affichage
                        final SimpleDateFormat displayFormat = new SimpleDateFormat("h:mm a");
                        displayFormat.setTimeZone(TimeZone.getDefault());

                        formattedTime = displayFormat.format(parsed);

                        prepareDataForRequests();
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        Snackbar snackbar = Snackbar
                                .make(coordinatorLayout, databaseError.getMessage(), Snackbar.LENGTH_LONG);
                        snackbar.setDuration(Snackbar.LENGTH_SHORT);
                        snackbar.show();
//                helpRequestsLoadingDialog.dismiss();
                        progressBarLoadingRequests.setVisibility(View.INVISIBLE);
                    }
                });

                    databaseReference.child("help-requests").addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(final DataSnapshot dataSnapshot) {
    //                adView.loadAd(request);
                            card_ads2.setVisibility(View.VISIBLE);
                            adView2.loadAd(request2);
                            if (snackbar != null) {
                                snackbar.dismiss();
                            }
                            progressBarLoadingRequests.setVisibility(View.INVISIBLE);

                            if (fastItemAdapter.getAdapterItemCount() == 0) {
                                emptyRVtext.setVisibility(View.VISIBLE);
                                emptyRVtexthh.setVisibility(View.VISIBLE);
                                card_ads2.setVisibility(View.INVISIBLE);
                            } else {
                                emptyRVtext.setVisibility(View.INVISIBLE);
                                emptyRVtexthh.setVisibility(View.INVISIBLE);
                            }

    //                progressBarLoadingRequests.setVisibility(View.INVISIBLE);
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Snackbar snackbar = Snackbar
                                    .make(coordinatorLayout, databaseError.getMessage(), Snackbar.LENGTH_LONG);
                            snackbar.setDuration(Snackbar.LENGTH_SHORT);
                            snackbar.show();
    //                hRequestsLoadingDialog.dismiss();
                            progressBarLoadingRequests.setVisibility(View.INVISIBLE);
                        }
                    });
                }

                @Override
                public void onKeyExited(String key) {

                }

                @Override
                public void onKeyMoved(String key, GeoLocation location) {

                }

                @Override
                public void onGeoQueryReady() {

                }

                @Override
                public void onGeoQueryError(DatabaseError error) {
                    Toast.makeText(getBaseContext(), "Erreur lors de la récupération de la géo-requête", Toast.LENGTH_SHORT).show();
                }
            });

        }

Voici l'erreur:

java.lang.NullPointerException: Tentative d'invoquer la méthode 'int java.lang.String.length()' sur une référence d'objet null

Veuillez me faire savoir comment récupérer seulement les publications qui se trouvent dans un rayon de 0,5 km de l'utilisateur?

0voto

Wilik Points 5713

Vous avez juste besoin de changer le deuxième paramètre de queryAtLocation()

double rayon = 0.5; // en km
geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLatDouble, currentLngDouble), rayon);

Êtes-vous sûr que tous les éléments qui sont à plus de 0.5km de l'utilisateur sont récupérés? Voici comment les valider

Location emplacementUtilisateur = new Location("emplacementUtilisateur");
emplacementUtilisateur.setLatitude(currentLatDouble);
emplacementUtilisateur.setLongitude(currentLngDouble);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        Location emplacementItem = new Location("emplacementItem");
        emplacementItem.setLatitude(location.latitude);
        emplacementItem.setLongitude(location.longitude);
        Log.d("distance jusqu'à " + key" est", emplacementUtilisateur.distanceTo(emplacementItem) + "");
    }

0voto

Malachi Prior Points 19

Ne sachant pas grand-chose à ce sujet, je ne peux pas beaucoup aider, mais en regardant votre code, cet extrait de la page GeoFire 2.0 ici donne un bon aperçu en javascript (plutôt qu'en java) de ce que vous cherchez.

L'utilité réelle de GeoFire est démontrée en créant une GeoQuery. Disons que vous créez une application pour les cyclistes qui montre les magasins de vélos dans un rayon d'un mile (1,609 kilomètres) de la position actuelle de l'utilisateur. La première chose à faire est d'ajouter les magasins de vélos qui vous intéressent à GeoFire. Ensuite, créez une requête centrée sur la position actuelle de l'utilisateur (disons qu'ils se trouvent à [37,4, -122,6]):

var geoQuery = geoFire.query({
  center: [37,4, -122,6],
  radius: 1,609 //kilomètres
});

Une requête seule n'est pas très utile. Cependant, GeoFire vous permet d'ajouter des fonctions de rappel qui sont déclenchées lors d'événements importants de la requête. Comme vous souhaitez afficher chaque magasin de vélos correspondant aux critères de la requête, écoutez l'événement key_entered. Chaque fois qu'une clé (c'est-à-dire, un magasin de vélos) entre dans la requête, le rappel que vous avez défini sera appelé avec des données sur cet emplacement:

geoQuery.on("key_entered", function(key, location, distance) {
  console.log("Magasin de vélos " + key + " trouvé à " + location + " (" + distance + " km de distance)");
});

Il est important de réaliser que l'événement key_entered fonctionne comme des événements Firebase typiques. C'est-à-dire qu'il sera déclenché pour chaque clé dans GeoFire qui correspond aux critères de la requête, à la fois les clés qui se trouvent déjà dans GeoFire et ceux qui sont ajoutés à tout moment à l'avenir. Grâce à Firebase, vous recevez ces événements en temps réel.

GeoFire est intelligent sur la manière dont il recherche des clés dans la requête. Il n'a pas besoin de charger toutes les données de GeoFire en mémoire. Si votre utilisateur recherche des magasins de vélos à San Francisco, GeoFire ne chargera pas les données pour les emplacements à New York seulement pour se rendre compte qu'ils sont de l'autre côté du pays. Il vérifie uniquement les emplacements qui sont réellement à proximité. Cela permet à votre application de rester légère et réactive, quel que soit la taille de votre ensemble de données.

Si votre utilisateur se déplace en vélo tout en cherchant un magasin à visiter, il est possible que des magasins qui étaient à moins d'un mile d'eux soient maintenant plus éloignés. Pour faire face à cela, GeoFire déclenchera l'événement key_exited pour chaque clé qui quitte la requête:

geoQuery.on("key_exited", function(key, location, distance) {
  console.log("Magasin de vélos " + key + " a quitté la requête vers " + location + " (" + distance + " km de distance)");
});

C'est vraiment tout ce dont vous avez besoin pour faire fonctionner votre application.

Les détails disponibles pour Java semblent être plus succincts mais pour ce que vous essayez de faire, cela semble être la chose à faire:

GeoQuery geoQuery = geoFire.queryAtLocation(currentUserLocation, 1,6);

Référence ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X