Geofire - не найдены места

Как я могу получить все места, которые находятся рядом с пройденным GeoLocation(double lat, double lng) используя Geo Queries. У меня есть следующий код (и ничего не происходит):

public void setCurrentLatLng(double lat, double lng){
    this.lat = lat;
    this.lng = lng;
    GeoLocation geoLocation = new GeoLocation(lat, lng);
    updateCurrenLocation(geoLocation);
    GeoQuery geoQuery = geoFire.queryAtLocation(geoLocation, 8f);
    geoQuery.addGeoQueryDataEventListener(new GeoQueryDataEventListener() {

        @Override
        public void onDataEntered(DataSnapshot dataSnapshot, GeoLocation location) {
            Log.d("geoQuery","onDataEntered "+dataSnapshot.toString());
            // ...
        }

        @Override
        public void onDataExited(DataSnapshot dataSnapshot) {
            Log.d("geoQuery","onDataExited "+dataSnapshot.toString());
            // ...
        }

        @Override
        public void onDataMoved(DataSnapshot dataSnapshot, GeoLocation location) {
            Log.d("geoQuery","onDataMoved "+dataSnapshot.toString());
            // ...
        }

        @Override
        public void onDataChanged(DataSnapshot dataSnapshot, GeoLocation location) {
            Log.d("geoQuery","onDataChanged "+dataSnapshot.toString());
            // ...
        }

        @Override
        public void onGeoQueryReady() {
            // ...
            Log.d("geoQuery","onGeoQueryReady");
        }

        @Override
        public void onGeoQueryError(DatabaseError error) {
            Log.d("geoQuery","onGeoQueryError");
            // ...
        }

    });
    this.setChanged();
    notifyObservers();
    this.clearChanged();
    Log.d("update","clearChanged");
}

И это мои данные о базе данных: введите описание изображения здесь

Я думаю, что я открыт для изменения структуры данных, если это необходимо.

бревна

09-12 08:55:33.818 17710-17710/es.rchampa.weirdo D/geoQuery: lat=40.4430883 lng=-3.721805
09-12 08:55:33.982 17710-17710/es.rchampa.weirdo D/geoQuery: lat=40.4430883 lng=-3.721805
09-12 08:55:33.986 17710-17710/es.rchampa.weirdo D/geoQuery: onGeoQueryReady
09-12 08:55:34.025 17710-17710/es.rchampa.weirdo D/geoQuery: onGeoQueryReady

Gradle файл

....
// Firebase
implementation 'com.google.firebase:firebase-database:16.0.1'
implementation 'com.google.firebase:firebase-storage:16.0.1'
implementation 'com.google.firebase:firebase-auth:16.0.3'
implementation 'com.google.firebase:firebase-crash:16.2.0'
implementation 'com.google.firebase:firebase-core:16.0.3'

// Firebase UI
implementation 'com.firebaseui:firebase-ui-database:1.2.0'

//Firebase GeoFire
implementation 'com.firebase:geofire-android:2.3.1'

// Google Play Services
implementation 'com.google.android.gms:play-services-auth:16.0.0'
implementation 'com.google.android.gms:play-services-maps:15.0.1'
implementation 'com.google.android.gms:play-services-location:15.0.1'
....

ОБНОВИТЬ

Я могу предоставить доступ к своему личному репо, если хотите.

3 ответа

Решение

Вы передаете значение 8f (плавать) как radius там, в то время как radius должно быть 8.0d или же Double.valueOf(8.0), где MAX_SUPPORTED_RADIUS равняется 8587 километров.

в то время как фактическая проблема заключается в том, что GeoFire уже нужно было бы знать о .child("location"), но это невозможно представить с Reference; только DataSnapshot имеет getChildren(),

нижняя строка:

вам придется создать отдельные места Reference, чтобы избежать вложения. тем не менее вы все еще можете использовать связанные uid ключ для этих узлов (или, по крайней мере, добавить его как дочерний узел), чтобы иметь возможность искать в пользователях Reference, это 1:1 отношение между двумя References.

так вот рабочая Java Например, только потому, что...

мы предполагаем следующую структуру (как описано выше):

{
  "locations" : {
    "CR88aa9gnDfJYYGq5ZTMwwC38C12" : {
      ".priority" : "9q8yywdgue",
      "g" : "9q8yywdgue",
      "l" : [ 37.7853889, -122.4056973 ]
    }
  },
  "users" : {
    "CR88aa9gnDfJYYGq5ZTMwwC38C12" : {
      "displayName" : "user 01",
      ...
    }
  }
}

правила базы данных должны иметь .indexOn за locations поле g задавать:

{
  "rules": {
    ...
    "locations": {
      ".indexOn": "g"
    }
  }
}

зависимости в модуле build.gradle:

dependencies {
    ...
    api "com.firebase:geofire-android:2.3.1"
}

и это демонстрирует, как получить снимок пользователя GeoQuery результат;

обратите внимание на GeoQueryEventListener вместо GeoQueryDataEventListener:

public class GeofireActivity extends AppCompatActivity {

    private static final String LOG_TAG = GeofireActivity.class.getSimpleName();

    private DatabaseReference refBase     = null;
    private DatabaseReference refLocation = null;
    private DatabaseReference refUser     = null;

    private GeoFire geoFire = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.fragment_geofire);
        this.setReferences();
    }

    private void setReferences() {
        this.refBase = FirebaseDatabase.getInstance().getReference();
        this.refUser = refBase.child("users");
        this.refLocation = refBase.child("locations");
        this.geoFire = new GeoFire(this.refLocation);
    }

    private void searchNearby(double latitude, double longitude, double radius) {
        this.searchNearby(new GeoLocation(latitude, longitude), radius);
    }

    private void searchNearby(GeoLocation location, double radius) {

        GeoQuery geoQuery = this.geoFire.queryAtLocation(location, radius);
        geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {

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

                String loc = String.valueOf(location.latitude) + ", " + String.valueOf(location.longitude);
                Log.d(LOG_TAG, "onKeyEntered: " + key + " @ " + loc);

                /* once the key is known, one can lookup the associated record */
                refUser.child(key).addListenerForSingleValueEvent(new ValueEventListener() {

                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        Log.d(LOG_TAG, "onDataChange: " + dataSnapshot.toString());
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError firebaseError) {
                        Log.e(LOG_TAG, "onCancelled: " + firebaseError.getMessage());
                    }
                });
            }

            @Override
            public void onKeyExited(String key) {
                Log.d(LOG_TAG, "onKeyExited: " + key);
            }

            @Override
            public void onKeyMoved(String key, GeoLocation location) {
                Log.d(LOG_TAG, "onKeyMoved: " + key);
            }

            @Override
            public void onGeoQueryReady() {
                Log.d(LOG_TAG, "onGeoQueryReady");
            }

            @Override
            public void onGeoQueryError(DatabaseError error) {
                Log.e(LOG_TAG, "onGeoQueryError" + error.getMessage());
            }
        });
    }
}

чтобы сохранить целостность, при удалении пользовательской записи необходимо будет удалить соответствующую запись о местоположении, иначе это приведет к ключам, которые больше не могут быть найдены.

Как оно стоит сейчас geofire своего рода служит в качестве индекса для создания гео-запросов и предоставляет ключ документа, который вы хотите (который будет храниться в отдельной "коллекции").

Вы должны использовать geofire и отдельная "коллекция" (назовите ее usersLocations)

DatabaseReference ref = FirebaseDatabase.getInstance().getReference("usersLocations");
GeoFire geoFire = new GeoFire(ref);

Теперь вы можете использовать его в качестве индекса для своих пользователей, и можете добавлять элементы в него следующим образом.

geoFire.setLocation('QymlMpC0Zc', new GeoLocation(40.2334983, -3.7185183));

Ваш RTDB Firebase теперь будет выглядеть так:

{
   'users': {
        'QymlMpC0Zc': {
            // All your data here
        }
    },
   'usersLocations': {
        'QymlMpC0Zc': {
            'g': 'ezjkgkk305',
            'l': {
                '0': 40.2334983,
                '1': -3.7185183
            }
        }
    }
}

Итак, наконец, когда вы делаете запрос на вашем geoFire Вы закончите тем, что уволите любых своих слушателей.

В качестве небольшой заметки... Я не Java-разработчик, но я использую / знаю geofire в общем. Надеюсь, мои советы / мысли будут полезны.

Проблема в том, когда вы прошли радиус в соответствии с проблемой https://github.com/firebase/geofire-java/issues/72

    double radius = 8589; // Fails
//  double radius = 8587.8; //Passes

попытаться передать значение, как это может помочь

//GeoQuery geoQuery = geoFire.queryAtLocation(geoLocation, 8f);
GeoQuery geoQuery = geoFire.queryAtLocation(geoLocation, radius);

передавая значение 8f (float) как радиус, в то время как радиус должен быть 8.0d или Double.valueOf(8.0), где MAX_SUPPORTED_RADIUS равен 8587 километрам.

Другие вопросы по тегам