使用Firebase

时间:2017-06-06 22:51:42

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

假设我有一些数据如下:

{
  "rallye" : {
    "positions" : {
      "ATYFOP8lNRThzrEC83" : {
        ".priority" : "u1q04dmvuq",
        "g" : "u1q04dmvuq",
        "l" : [ -116.04463242, 19.55545101 ]
      },
      "AZYF2P8lNSThzrEC63" : {
        ".priority" : "u1q04dtcbk",
        "g" : "u1q04dtcbk",
        "l" : [ 116.045306, 17.555276 ]
      }

在我的firebase实时数据库中,

和这个Android类:

package com.sherdle.universal.rallye;

import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.os.*;

import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;

import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.firebase.geofire.GeoQuery;
import com.firebase.geofire.GeoQueryEventListener;

import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;


import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;

import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.SupportMapFragment;

import com.sherdle.universal.R;

import java.util.HashMap;
import java.util.Map;

public class rallye_activity extends FragmentActivity implements GeoQueryEventListener, MapboxMap.OnCameraChangeListener {

    // in welchem Suchradius sollen andere Teams auf der Karte angezeigt werden?
    private static final int TEAMSIMRADIUS = 100;
    private static final GeoLocation INITIAL_CENTER = new GeoLocation(52.543535, 8.55123);
    private static final int INITIAL_ZOOM_LEVEL = 14;
    private static final String GEO_FIRE_REF = "/rallye/positions";

    private MapboxMap map;
    private GeoFire geoFire;
    private GeoQuery geoQuery;

    private Map<String,Marker> markers;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_rallye_activity);

        Mapbox.getInstance(this, getString(R.string.mapbox_access_token));

        SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.container);
        this.map = mapFragment.getMap();

        LatLng latLngCenter = new LatLng(INITIAL_CENTER.latitude, INITIAL_CENTER.longitude);
        this.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngCenter, INITIAL_ZOOM_LEVEL));
        this.map.setOnCameraChangeListener(this);

        DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/rallye/positions");
        final GeoFire geoFire = new GeoFire(ref);

        // radius in km
        this.geoQuery = this.geoFire.queryAtLocation(INITIAL_CENTER, 1);

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

    }

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

    @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
    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(DatabaseError 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.getLatitude()) * v + startPosition.getLatitude();
                double currentLng = (lng - startPosition.getLongitude()) * v + startPosition.getLongitude();
                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.geoQuery.setCenter(new GeoLocation(center.getLatitude(), center.getLongitude()));
        // radius in km
        this.geoQuery.setRadius(radius/1000);
    }
}

这是我的布局XML

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.mapbox.mapboxsdk.maps.SupportMapFragment"/>

事实上:我想在此Mapbox地图上实时显示我的地理位置数据和多个标记。

但是我得到了这个错误

this.map = mapFragment.getMap();

然后我使用“new”函数:getMapAsync()

this.map = mapFragment.getMapAsync(this);

如果没有这些功能,我会收到此错误:

FATAL EXCEPTION: main
Process: com.foo.bar, PID: 12380
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.foo.bar/com.sherdle.universal.rallye.rallye_activity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2689)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2754)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
at android.view.LayoutInflater.inflate(LayoutInflater.java:483)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
at android.transition.Scene.enter(Scene.java:175)
at com.android.internal.policy.impl.PhoneWindow.transitionTo(PhoneWindow.java:483)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:426)
at android.app.Activity.setContentView(Activity.java:2267)
at com.sherdle.universal.rallye.rallye_activity.onCreate(rallye_activity.java:54)

1 个答案:

答案 0 :(得分:0)

您使用错误的ID来查找片段。 XML中定义的ID为map。您正在搜索container

变化:

SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager()
    .findFragmentById(R.id.container);

为:

SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager()
    .findFragmentById(R.id.map);