【问题标题】:Store Android user location in Firebase database and display it on map using Geofire将 Android 用户位置存储在 Firebase 数据库中并使用 Geofire 在地图上显示
【发布时间】:2016-07-07 00:14:03
【问题描述】:

我创建了一个 Android 应用,它的用户登录和注册链接到我的 Firebase 数据库。

我正在尝试使用 Geofire 来存储和显示在地图上登录的用户,我使用了 SF 车辆示例,老实说我不太了解它。我已经使用完全相同的代码进行测试,看看它是否有效,我在提供的图像中得到了错误。

我正在寻求帮助,编写一个函数来检测登录用户的位置并将其实时显示在地图上,随着用户的移动而更新,我现在被困在这几周了,并且已经尝试了所有的方法那里(不是很多)。

我们将不胜感激,如果需要任何进一步的信息,请询问。

这是我正在使用的 SF Vehicle 示例中的代码,原始代码连接到 San Fransisco 巴士部门并显示它们,所以我需要代码将位置写入我的数据库并以相同的方式显示它们.

package nixer.nixer;

import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.firebase.geofire.GeoQuery;
import com.firebase.geofire.GeoQueryEventListener;
import com.firebase.geofire.LocationCallback;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.*;
import java.util.HashMap;
import java.util.Map;


public class MapActivity extends AppCompatActivity implements   GeoQueryEventListener, GoogleMap.OnCameraChangeListener {

private Firebase mRef;
private String mUserId;
private String itemsUrl;
private static final GeoLocation INITIAL_CENTER = new GeoLocation(53.349805,  -6.260309 );
private static final int INITIAL_ZOOM_LEVEL = 14;
private static final String GEO_FIRE_REF = "https://nixer.firebaseio.com/";
private GoogleMap map;
private Circle searchCircle;
private GeoFire geoFire;
private GeoQuery geoQuery;

private Map<String,Marker> markers;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    // setup map and camera position
    SupportMapFragment mapFragment =  (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
    this.map = mapFragment.getMap();
    LatLng latLngCenter = new LatLng(INITIAL_CENTER.latitude,  INITIAL_CENTER.longitude);
    this.searchCircle = this.map.addCircle(new CircleOptions().center(latLngCenter).radius(1000));
    this.searchCircle.setFillColor(Color.argb(66, 255, 0, 255));
    this.searchCircle.setStrokeColor(Color.argb(66, 0, 0, 0));
     this.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngCenter,   INITIAL_ZOOM_LEVEL));
    this.map.setOnCameraChangeListener(this);

    Firebase.setAndroidContext(this);

    // setup GeoFire
    this.geoFire = new GeoFire(new Firebase(GEO_FIRE_REF));
    // radius in km
    this.geoQuery = this.geoFire.queryAtLocation(INITIAL_CENTER, 1);

    // setup markers
    this.markers = new HashMap<String, Marker>();       




    // Check Authentication
    mRef = new Firebase(Constants.FIREBASE_URL);
    if (mRef.getAuth() == null) {
        loadLoginView();
    }


    try {
        mUserId = mRef.getAuth().getUid();
    } catch (Exception e) {
        loadLoginView();
    }

}




@Override
protected void onStop() {
    super.onStop();
    // remove all event listeners to stop updating in the background
    this.geoQuery.removeAllListeners();
    for (Marker marker: this.markers.values()) {
        marker.remove();
    }
    this.markers.clear();
}

@Override
protected void onStart() {
    super.onStart();
    // add an event listener to start updating locations again
    this.geoQuery.addGeoQueryEventListener(this);
}

@Override
public void onKeyEntered(String key, GeoLocation location) {
    // Add a new marker to the map
    Marker marker = this.map.addMarker(new MarkerOptions().position(new   LatLng(location.latitude, location.longitude)));
    this.markers.put(key, marker);
}

@Override
public void onKeyExited(String key) {
    // Remove any old marker
    Marker marker = this.markers.get(key);
    if (marker != null) {
        marker.remove();
        this.markers.remove(key);
    }
}

@Override
public void onKeyMoved(String key, GeoLocation location) {
    // Move the marker
    Marker marker = this.markers.get(key);
    if (marker != null) {
        this.animateMarkerTo(marker, location.latitude, location.longitude);
    }
}

@Override
public void onGeoQueryReady() {
}

@Override
public void onGeoQueryError(FirebaseError error) {
    new AlertDialog.Builder(this)
            .setTitle("Error")
            .setMessage("There was an unexpected error querying GeoFire: " + error.getMessage())
            .setPositiveButton(android.R.string.ok, null)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .show();
}

// Animation handler for old APIs without animation support
private void animateMarkerTo(final Marker marker, final double lat, final double lng) {
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final long DURATION_MS = 3000;
    final Interpolator interpolator = new AccelerateDecelerateInterpolator();
    final LatLng startPosition = marker.getPosition();
    handler.post(new Runnable() {
        @Override
        public void run() {
            float elapsed = SystemClock.uptimeMillis() - start;
            float t = elapsed/DURATION_MS;
            float v = interpolator.getInterpolation(t);

            double currentLat = (lat - startPosition.latitude) * v +   startPosition.latitude;
            double currentLng = (lng - startPosition.longitude) * v +   startPosition.longitude;
            marker.setPosition(new LatLng(currentLat, currentLng));

            // if animation is not finished yet, repeat
            if (t < 1) {
                handler.postDelayed(this, 16);
            }
        }
    });
}

private double zoomLevelToRadius(double zoomLevel) {
    // Approximation to fit circle into view
    return 16384000/Math.pow(2, zoomLevel);
}

@Override
public void onCameraChange(CameraPosition cameraPosition) {
    // Update the search criteria for this geoQuery and the circle on the map
    LatLng center = cameraPosition.target;
    double radius = zoomLevelToRadius(cameraPosition.zoom);
    this.searchCircle.setCenter(center);
    this.searchCircle.setRadius(radius);
    this.geoQuery.setCenter(new GeoLocation(center.latitude,  center.longitude));
    // radius in km
    this.geoQuery.setRadius(radius/1000);
}

更新:

Firebase 规则:

{
"rules": {
  "users": {
    "$uid": {
      ".read": "auth != null && auth.uid == $uid",
      ".write": "auth != null && auth.uid == $uid",
      "items": {
        "$item_id": {
          "title": {
            ".validate": "newData.isString() && newData.val().length > 0"
            }
        }
      }
    }
  }

  }
}

【问题讨论】:

  • 从您附加的图片中,该错误与 Firebase 安全和规则有关。如果您想了解更多信息,请在问题中添加规则。
  • @adolfosrs 我自己也这么认为,但我不确定从哪里开始。我希望代码自动将位置添加到该数据库中,而不必手动执行,有什么想法吗?干杯。我添加了规则
  • @adolfosrs 我添加了规则。
  • 解决了这个问题?如果是,请发布答案,我也处于类似状态。无法正确理解规则
  • @Shivaraj 不幸不是伴侣

标签: java android firebase firebase-realtime-database geofire


【解决方案1】:
{
    "rules": {
        "users": {
            "$uid": {
                ".read": true,
                ".write": true,
                "items": {
                    "$item_id": {
                        "title": {
                            ".validate": "newData.isString() && newData.val().length > 0"
                        }
                    }
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2017-04-18
    • 2012-12-17
    • 2019-04-18
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多