如何检索距离我的范围0.5公里范围内的帖子?

时间:2016-07-15 06:27:05

标签: android firebase firebase-realtime-database geofire

我正在保存用户发布的帖子的坐标。我正在生成推送ID,然后使用它来保存帖子的数据和地理位置坐标。

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

以下是我如何生成推送ID:

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

以下是我如何使用它来保存地理位置坐标以及帖子的数据:

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

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

它会像这样保存:

enter image description here

问题在于,当我试图仅获取距离我达到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();
                }
            });

        }

这是错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference

请告诉我如何仅检索用户0.5公里范围内的那些帖子?

3 个答案:

答案 0 :(得分:0)

您只需更改queryAtLocation()

的第二个参数即可
double radius = 0.5; // in km
geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLatDouble, currentLngDouble), radius);

您确定要检索距离用户超过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) + "");
    }

答案 1 :(得分:0)

不太了解这一点我无法提供太多帮助,但是从GeoFire 2.0页面here查看您的代码这个摘录,可以在javascript(而不是java)中给出一个很好的概述。 #39;正在寻找。

  

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

var geoQuery = geoFire.query({
  center: [37.4, -122.6],
  radius: 1.609 //kilometers
});
  

查询本身并不是很有用。但是,GeoFire允许您添加在重要查询事件发生时触发的回调函数。由于您希望显示符合查询条件的每个自​​行车商店,请侦听key_entered事件。每当一个键(即自行车商店)输入查询时,您定义的回调将被调用有关该位置的数据:

geoQuery.on("key_entered", function(key, location, distance) {
  console.log("Bicycle shop " + key + " found at " + location + " (" + distance + " km away)");
});
  

重要的是要意识到key_entered事件就像典型的Firebase事件一样。也就是说,它将针对GeoFire中与查询条件匹配的每个密钥触发,两个密钥已经在GeoFire中,而且在将来的任何一点都添加了。感谢Firebase,您可以实时收到这些活动。

     

GeoFire非常了解它如何在查询中查找密钥。它不需要将所有GeoFire数据加载到内存中。如果您的用户正在旧金山寻找自行车商店,GeoFire将不会为纽约的地点加载数据,只是意识到他们位于该国的另一边。它只检查实际附近的位置。无论您的数据集有多大,这都可以使您的应用程序保持轻盈和响应。

     

如果您的用户在寻找商店参观时骑自行车,那么距离他们不到一英里的商店可能会更远。为了解决这个问题,GeoFire将为每个离开查询的键触发key_exited事件:

geoQuery.on("key_exited", function(key, location, distance) {
  console.log("Bicycle shop " + key + " left query to " + location + " (" + distance + " km away)");
});
  

这就是让您的应用运行所需的一切。

可用于Java的详细信息似乎比较稀疏,但是对于您要做的事情,这似乎就是这样:

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

参考here

答案 2 :(得分:0)

还有一种方法可以在Java的地理查询中找到匹配项。 该代码与UI非常相似。 请在下面的链接中查看有效的代码段。 https://youtu.be/M9d526OyG54 搜索驱动程序::系列教程15。