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

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

0 голосов
/ 10 сентября 2018

Как я могу получить все местоположения, которые находятся рядом с пройденным 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");
}

А это мои данные из базы: enter image description here

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

Журналы

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'
....

UPDATE

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

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

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

Вы должны использовать geofire и отдельную «коллекцию» (назовите ее usersLocations )

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

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

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

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

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

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

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

0 голосов
/ 15 сентября 2018

Проблема в том, что вы прошли радиус По выпуску 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 километров.

0 голосов
/ 12 сентября 2018

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

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

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

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

так вот рабочий 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 {
    ...
    implementation "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());
            }
        });
    }
}

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

...