【问题标题】:Unable to update google maps location using firebase无法使用 Firebase 更新谷歌地图位置
【发布时间】:2017-06-17 13:55:48
【问题描述】:

我正在尝试在我的 android 应用程序中将位置从 firebase 数据库更新为谷歌地图。我已经使用了 firebase 的 onDataChange 方法来做到这一点。我的问题是,即使在 Firebase 数据库中更改了海拔和经度的位置,我仍然无法更新谷歌地图上的位置。下面是 MapsActivity.java 类的代码。

import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    String value;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference myRef = database.getReference("Location");

      //  myRef.setValue("Hello, World!");

        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
              value = dataSnapshot.getValue(String.class);
                String [] separated = value.split(",");
                String latiPos= separated[0].trim();
                String longiPos =separated[1].trim();
                String TAG ="VAL";
                double dLat = Double.parseDouble(latiPos);
                double dLong = Double.parseDouble(longiPos);
                // Add a marker in Sydney and move the camera
                LatLng sydney = new LatLng(dLat, dLong);
                mMap.addMarker(new MarkerOptions().position(sydney).title(latiPos+" "+longiPos));


            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
     //   LatLng sydney = new LatLng(-34, 151);
      //  mMap.addMarker(new MarkerOptions().position(sydney).title(value));
        //mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}

【问题讨论】:

  • 您是否确认正在调用onDataChange 并且它正确解析了纬度/经度值?可能与您的问题无关,但建议您将调用 dataSnapshot.getValue() 与包含 lat/long 值的 java 类一起使用...这将使用 gson 从您返回的 json 字符串中反序列化(尽管从您的描述中不确定数据是如何的在 db 中结构化)。
  • 是的,我确实通过在日志中打印出来确认了这些值。
  • 另一个可能的问题可能是mMap 可用的时间(即onMapReady 发生在onDataChange 回调之后)......尽管如果发生这种情况你应该得到NPE......在任何如果您可能应该等到设置mMap 后再进行firebase 查询。
  • 我的想法完全一样,但是当我在 Firebase 中更新纬度和经度值时,值的变化应该执行 onDataChange 方法,该方法最终应该将标记位置更改为新的 lat、long 值,但它没有发生.

标签: android google-maps firebase firebase-realtime-database


【解决方案1】:

我建议有两件事来解决您的问题:

  1. 将存储在FirebaseDatabase 中的数据包装在Java 对象中,以便轻松存储和检索数据。现在 您正在做很多工作来处理存储在数据库中的数据。所以, 定义一个类,它代表您作为 Java 对象存储的数据。然后你的读/写 到数据库会容易得多。这是可用于表示地图标记的类的示例 根据我在上面的代码中看到的。您可以对其进行自定义以满足您的需求:

    public class LocationMarker {
    
        double latitude;
        double longitude;
    
    
        /**
         * Required Empty Constructor used by Firebase
         */
        public LocationMarker() {
        }
    
        public LocationMarker(double latitude, double longitude) {
            this.latitude = latitude;
            this.longitude = longitude;
    
        }
    
        public double getLatitude() {
            return latitude;
        }
    
        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }
    
        public double getLongitude() {
            return longitude;
        }
    
        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }
    
    
        /**
         * These getters will be ignored when the object is serialized into a JSON object.
         * Since they will be ignored this means that they don't need a corresponding property (field)
         * in the Database. This is how we can return a value without having them declared as an instance variable.
         */
    
        @Exclude
        public LatLng getPosition(){
            return new LatLng(latitude, longitude);
        }
    
        @Exclude
        public String getTitle(){
            return Double.toString(latitude) + " " + Double.toString(longitude);
        }
    }
    

    现在您可以更轻松地将位置写入数据库。

    DatabaseReference myRef = FirebaseDatabase.getInstance().getReference();
    double latitude = -34;
    double longitude = 151;
    LocationMarker locationMarker = new LocationMarker(latitude,longitude);
    myRef.child("Location").setValue(locationMarker);
    

    然后阅读:

    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
    
             LocationMarker locationMarker = dataSnapshot.getValue(LocationMarker.class);
    
             if(locationMarker != null){
                 LatLng sydney = locationMarker.getPosition();
                 mMap.addMarker(new MarkerOptions()
                                        .position(sydney)
                                        .title(locationMarker.getTitle));
             }
         }
    
         @Override
         public void onCancelled(DatabaseError databaseError) {
    
         }
    });
    
  2. onMapReady()onDataChange() 的调用是异步发生的。 这意味着您的挑战是您无法控制何时调用 onMapReady()。 您也无法控制您的ValueEventListener 何时调用onDataChange()。 正如现在所写,对 FirebaseDatabase 的调用可能会在您拥有有效的 GoogleMap 对象之前返回。所以在对onMapReady()的调用中添加你的ValueEventListener

    @Override
    public void onMapReady(GoogleMap googleMap) {
         mMap = googleMap;
         addValueEventListener();
    }
    
    //....
    
    private void addValueEventListener(){
    
        if(mMap == null) return;
    
         myRef.addValueEventListener(new ValueEventListener() {
              @Override
              public void onDataChange(DataSnapshot dataSnapshot) {
    
                   LocationMarker locationMarker = dataSnapshot.getValue(LocationMarker.class);
    
                   if(locationMarker != null){
                   LatLng sydney = locationMarker.getPosition();
                   mMap.addMarker(new MarkerOptions()
                                        .position(sydney)
                                        .title(locationMarker.getTitle));
                   }
              }
    
              @Override
              public void onCancelled(DatabaseError databaseError) {
    
              }
         });
    }
    

希望这有助于向您的数据库显示存储和检索地图标记。这应该在“位置”下存储一个标记。您必须针对多个标记对数据库结构进行调整。另外,请务必删除所有添加的侦听器:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    相关资源
    最近更新 更多