Android 如何检索距离我可达0.5公里以内的帖子?

Android 如何检索距离我可达0.5公里以内的帖子?,android,firebase,firebase-realtime-database,geofire,Android,Firebase,Firebase Realtime Database,Geofire,我正在保存用户发布的帖子的坐标。我正在生成一个推id,然后使用它来保存post和geofire坐标的数据 我只想显示那些在0.5公里半径范围内的帖子。我使用的是GeoFire库,但我无法完成任务 下面是我如何生成推送id的: itemID=databaseReferenceRequests.push().getKey() 下面是我如何使用它来保存geofire坐标以及帖子的数据: geoFire.setLocation(itemID, new GeoLocation(Doubl

我正在保存用户发布的帖子的坐标。我正在生成一个推id,然后使用它来保存post和geofire坐标的数据

我只想显示那些在0.5公里半径范围内的帖子。我使用的是
GeoFire
库,但我无法完成任务

下面是我如何生成推送id的:

itemID=databaseReferenceRequests.push().getKey()

下面是我如何使用它来保存geofire坐标以及帖子的数据:

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

databaseReferenceRequests.child(itemID).setValue(hRequest);
它是这样保存的:

问题是,当我试图只获取那些距离我可达0.5公里以内的帖子时,它不会发生,所有的帖子,无论是近的还是远的,都会被检索到

下面是我如何检索它的:

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<String, String> newRequest = (Map<String, String>) 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 {
                            // error on line below
                            date = df.parse(timeStr);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        df.setTimeZone(TimeZone.getDefault());
                        final String persisted = df.format(date);

                        // Parse string from DB - UTC timezone
                        Date parsed = null;
                        try {
                            parsed = df.parse(persisted);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }

                        // Now convert to whatever timezone for display purposes
                        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(), "Error retriving geoquery", Toast.LENGTH_SHORT).show();
                }
            });

        }

请让我知道如何仅检索距离用户0.5公里以内的帖子?

您只需更改
queryLocation()的第二个参数

您确定已检索到距离用户0.5公里以上的所有项目吗? 下面是如何验证它们

Location userLocation = new Location("userLocation");
userLocation.setLatitude(currentLatDouble);
userLocation.setLongitude(currentLngDouble);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        Location itemLocation = new Location("itemLocation");
        itemLocation.setLatitude(location.latitude);
        itemLocation.setLongitude(location.longitude);
        Log.d("distance to " + key" is", userLocation.distanceTo(itemLocation) + "");
    }

对此我不太了解,但看看您的代码,这篇摘自GeoFire 2.0页面的摘录用javascript(而不是java)很好地概括了您所寻找的内容

GeoFire的真正实用程序通过创建GeoQuery来展示。假设您正在为骑自行车的人制作一个应用程序,该应用程序显示用户当前位置一英里(1.609公里)内的自行车商店。你需要做的第一件事是将你关心的自行车店添加到GeoFire中。然后,创建一个以用户当前位置为中心的查询(假设它们位于[37.4,-122.6]):

查询本身不是很有用。但是,GeoFire允许您添加回调函数,这些函数在发生重要查询事件时被激发。由于要显示与查询条件匹配的每个自行车店,请侦听输入的按键事件。每次钥匙(即自行车店)进入查询时,您定义的回调将被调用,其中包含有关该位置的数据:

重要的是要认识到,按键输入事件的工作方式与典型的Firebase事件类似。也就是说,它将为GeoFire中与查询条件匹配的每个键触发,这两个键都是GeoFire中已经存在的键,也都是将来在任何时候添加的键。感谢Firebase,您可以实时接收这些事件

GeoFire在如何在查询中查找关键字方面很聪明。它不需要将所有GeoFire数据加载到内存中。如果你的用户在旧金山寻找自行车商店,GeoFire不会为纽约的地点加载数据,而是意识到他们在这个国家的另一边。它只检查实际上在附近的位置。无论你的数据集有多大,这都能让你的应用程序轻巧、响应迅速

如果您的用户在寻找要访问的商店时骑着自行车四处走动,那么可能距离他们一英里以内的商店现在已经更远了。为了解决这个问题,GeoFire将为每个离开查询的键触发key_exited事件:

这就是让你的应用程序工作所需要的一切

Java可用的详细信息似乎比较少,但对于您正在尝试做的事情来说,这似乎是一件非常重要的事情:

GeoQuery geoQuery = geoFire.queryAtLocation(currentUserLocation, 1.6);

参考。

还有一种方法可以在Java的Geo Query中查找匹配项。。 代码与UI非常相似。 请在下面的链接中查找工作代码段。
搜索驱动程序::本系列第15篇教程。

很抱歉,我忘记更改该参数。在我的原始代码中,它被设置为0.5。它仍然没有恢复!您确定已检索到距离用户0.5公里以上的所有项目吗?看看我最新的答案,如何验证它们不,兄弟。我无法实现我想要的。我正在写一道题。你能从头开始编码吗?问题是“假设我在某个地方看到一种稀有物种。我上传了它和它的当前位置坐标。现在我想要的是,我想要的是,只有那些在发现稀有物种地点0.5公里半径范围内的用户才能看到我发布的帖子。不是每个应用程序的用户,只是那些距离该地点0.5公里以内的用户。“我希望你明白我的问题。请用解决上述问题的代码编辑您的答案。谢谢!:)我不确定你这里有什么问题,我一直在使用GeoFire进行我的项目,它工作得很好。根据您的示例,要保存稀有物种位置,可以调用
geoFire.setLocation()
,只需调用
geoFire.queryAtLocation()
,即可获取稀有物种。
queryAtLocation
方法的第一个参数是用户的位置,因此需要使用位置提供程序获取他们的位置,第二个参数是以km为单位的半径。GeoFire将只返回第一个参数提供的用户位置半径范围内的位置。我认为您需要为错误创建一个新问题,这已经超出主题。“在0.5公里内取回帖子”对你有效吗?你必须解释你真正的问题是什么,并简化你的代码,你的代码很混乱。您的答案在
javascript
中有代码。你能让我知道这方面准确的
java
代码吗?我希望我添加的内容对你有所帮助,似乎对java的关注较少,可能只是我没有找对地方。Firebase geofire js:如何获取近静态(固定)位置的密钥列表:
用户发布的帖子
。哪些用户?哪个网站的?@greenapps我的应用程序的用户。。
var geoQuery = geoFire.query({
  center: [37.4, -122.6],
  radius: 1.609 //kilometers
});
geoQuery.on("key_entered", function(key, location, distance) {
  console.log("Bicycle shop " + key + " found at " + location + " (" + distance + " km away)");
});
geoQuery.on("key_exited", function(key, location, distance) {
  console.log("Bicycle shop " + key + " left query to " + location + " (" + distance + " km away)");
});
GeoQuery geoQuery = geoFire.queryAtLocation(currentUserLocation, 1.6);