5

ユーザーが投稿した投稿の座標を保存しています。プッシュ ID を生成し、それを使用して投稿のデータと geofire 座標の両方を保存しています。

半径 0.5 km 以内にある投稿のみを表示したい。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 km 以内にある投稿のみを取得しようとすると、それが行われず、近くまたは遠くにあるすべての投稿が取得されることです。

これが私がそれを取得する方法です:

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 km 以内にある投稿のみを取得する方法を教えてください。

4

3 に答える 3

1

の2番目のパラメータを変更するだけですqueryAtLocation()

double radius = 0.5; // in km
geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLatDouble, currentLngDouble), radius);

ユーザーから 0.5km を超えるすべてのアイテムが取得されますか? それらを検証する方法は次のとおりです

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) + "");
    }
于 2016-07-15T06:44:35.517 に答える
1

これについてあまり知らないので、私はあまり役に立ちませんが、ここのGeoFire 2.0ページから抽出したコードを見ると、探しているもののJavaScript(Javaではなく)の概要がわかります。

GeoFire の真の有用性は、GeoQuery を作成することによって示されます。ユーザーの現在地から 1 マイル (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 はニューヨークの場所のデータを読み込まず、それらが国の反対側にあることを認識するだけです。実際に近くにある場所のみをチェックします。これにより、データ セットのサイズに関係なく、アプリの軽量化と応答性が維持されます。

ユーザーが行きたい店を探しながら自転車で走り回っている場合、1 マイル以内にあった店が遠くにある可能性があります。これに対処するために、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);

ここを参照してください。

于 2016-07-15T06:55:30.097 に答える