【问题标题】:how to retrieve continuous updated location data from the GeoFire and put it on Google map?如何从 GeoFire 中检索持续更新的位置数据并将其放在 Google 地图上?
【发布时间】:2020-03-10 15:02:30
【问题描述】:

我正在开发一个儿童位置跟踪应用程序。我正在使用 geoFire 将孩子的位置发送到数据库中,该位置会在一定时间后更新。但问题是,在父母活动中,位置标记不会根据孩子的更新位置而改变......那么,我怎样才能从数据库中检索连续的位置更新并根据位置移动标记?

【问题讨论】:

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


    【解决方案1】:

    这取决于您要显示的信息。

    在下面的代码示例中,我将ParentModelChildModelLocationModelCheckInModel 类的实现留给您来开发。下面的代码也不处理初始化活动、Firebase 或GoogleMaps 对象。

    不用说,您必须极其小心地保护这些敏感数据。

    场景 1:仅显示/存储最后一个已知位置。

    在这种情况下,数据库只为每个孩子保存一个位置。服务器上没有位置历史的概念。

    这可以通过在单个位置监听存储在数据库中的数据的更新来实现(请参阅Listen for Value Events)。在下面的代码中,我还添加了一个可选的Polyline,显示地图打开时存储在客户端设备上的最近位置更新。每次在服务器上更新数据时,都会执行监听器并更新地图的本地副本。

    private DatabaseReference mDatabase;
    private DatabaseReference mTrackedLocationRef;
    private ParentModel mParent;
    private ChildModel mSelectedChild;
    private GoogleMap mMap;
    private Polyline mCurrentLine;
    private Marker mLastKnownLocationMarker;
    
    // ...
    mDatabase = FirebaseDatabase.getInstance().getReference();
    
    // initialize a tracking line
    mCurrentLine = mMap.addPolyline((new PolylineOptions())
                    .clickable(true);
    
    
    // TODO: download parent's user profile to mParent
    mSelectedChild = mParent.children[0]; // select first child
    
    mTrackedLocationRef = mDatabase.child("locations").child(mSelectedChild.uid).child("lastKnownLocation");
    
    ValueEventListener locationUpdateListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // location was updated
            LocationModel locModel = dataSnapshot.getValue(LocationModel.class);
    
            LatLng pos = locModel.getLatLng(); // getLatLng() returns a LatLng object.
    
            // if enabled, add position to traced line
            if (mCurrentLine != null) {
              mCurrentLine.add(pos);
            }
    
            // update/create marker for last detected location
            if (mLastKnownLocationMarker != null) {
              mLastKnownLocationMarker.setPosition(pos);
            } else {
              mLastKnownLocationMarker = mMap.addMarker(new MarkerOptions().position(pos)
                    .title(mSelectedChild.firstName + "'s current location"));
            }
    
            // move camera to new position
            googleMap.moveCamera(CameraUpdateFactory.newLatLng(pos));
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {
            // Getting location update failed, log a message
            Log.w(TAG, "locUpdate:onCancelled", databaseError.toException());
            Toast.makeText(mContext, "Failed to load last known location.",
                    Toast.LENGTH_SHORT).show();
        }
    };
    mTrackedLocationRef.addValueEventListener(locationUpdateListener);
    

    场景 2:显示最后 5 个位置。

    在这种情况下,位置“签入”的历史记录保存在使用push() 操作上传到服务器的数据库中。在这种情况下,监听器只会使用 5 个最近的位置更新来更新地图。每次向服务器添加新位置时,都会将新位置添加到地图中,并删除 5 个位置中最旧的位置。

    private DatabaseReference mDatabase;
    private DatabaseReference mTrackedLocationRef;
    private ParentModel mParent;
    private ChildModel mSelectedChild;
    private GoogleMap mMap;
    private Polyline mCurrentLine;
    private final Map<String, Marker> mMarkers = new ConcurrentHashMap<String, Marker>();
    
    // initialize a tracking line
    mCurrentLine = mMap.addPolyline((new PolylineOptions())
                    .clickable(true);
    
    
    // TODO: download parent's user profile to mParent
    mSelectedChild = mParent.children[0]; // select first child
    
    mTrackedLocationRef = mDatabase.child("locations").child(mSelectedChild.uid).child("checkins").limitToLast(5);
    
    ChildEventListener locationUpdateListener = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
            // this location update is one of the five most-recent entries
            String keyName = dataSnapshot.getKey();
            Log.d(TAG, "onChildAdded:" + keyName);
    
            CheckInModel checkin = dataSnapshot.getValue(CheckInModel.class);
    
            LatLng pos = checkin.getLatLng(); // getLatLng() returns a LatLng object.
    
            // remove title of previous marker
            mMarkers.get(previousChildName).setTitle("");
    
            // add new marker
            Marker marker = mMap.addMarker(new MarkerOptions().position(pos)
                    .title(mSelectedChild.firstName + "'s current location"));
    
            marker.setTag(keyName); // store key name in marker's metadata
    
            // store marker by its key name for easy removal
            mMarkers.put(keyName, marker);
        }
    
        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
            Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
    
            // todo: handle edited data?
        }
    
        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            // this location update is no longer one of the five most-recent entries
            Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
    
            // find and remove existing marker
            mMarkers.get(dataSnapshot.getKey()).remove();
        }
    
        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
            Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
    
            // todo: handle reordered data?
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w(TAG, "locUpdate:onCancelled", databaseError.toException());
            Toast.makeText(mContext, "Failed to load location history.",
                    Toast.LENGTH_SHORT).show();
        }
    };
    mTrackedLocationRef.addChildEventListener(locationUpdateListener);
    


    由于这些数据本质上是敏感的,因此请确保您还具有以快速简单的方式完全删除有关父母及其子女的所有数据的流程。

    【讨论】:

    • 抱歉我没听懂?您的示例是否适用于 GeoFire?因为我已经使用 GeoFire 存储了我的位置..
    猜你喜欢
    • 2017-04-18
    • 2011-05-18
    • 1970-01-01
    • 2020-07-03
    • 2017-05-20
    • 2022-01-02
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多