2017-06-17 63 views
0

我正嘗試將位置表單Firebase數據庫更新爲我的Android應用程序中的Google地圖。我已經使用firebase的onDataChange方法來實現這一點。我的問題是,即使Firebase數據庫中的高度和經度位置已更改,我仍無法更新Google地圖上的位置。以下是我的MapsActivity.java類的代碼。無法使用Firebase更新Google地圖位置

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)); 
    } 
} 
+0

您是否確認調用了'onDataChange'並且它正確解析經緯度值?可能與您的問題沒有關係,但會建議您使用調用'dataSnapshot.getValue()'與包含緯度/長度值的java類...它將使用'gson'從您返回的json字符串中反序列化(雖然從您的描述數據如何在db中結構化)。 –

+0

是的,我通過在日誌中打印出來確認了這些值。 –

+0

另一個可能的問題可能出現在'mMap'可用的時間點(即'onMapChange'回調後發生'onMapReady')...儘管如果發生這種情況,您應該得到NPE ......無論如何,您應該等待您的Firebase查詢,直到已設置「mMap」。 –

回答

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()時,您也無法控制。 正如現在寫的,在您有一個有效的GoogleMap對象之前,您的FirebaseDatabase調用可能會返回。所以在通話添加ValueEventListeneronMapReady()

    @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) { 
    
          } 
        }); 
    } 
    

希望這有助於顯示存儲和檢索地圖標記到您的數據庫。這應該在「位置」下存儲一個標記。您必須對多個標記的數據庫結構進行調整。此外,請務必刪除所有添加的聽衆:)

相關問題