我正在保存用户发布的帖子的坐标。我正在生成推送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);
它会像这样保存:
问题在于,当我试图仅获取距离我达到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公里范围内的那些帖子?
答案 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。