首页 > 解决方案 > 实时位置跟踪更新延迟

问题描述

我正在为一组用户创建一个用于实时 gps 跟踪的应用程序。我设法在地图上用标记显示每个用户位置(地图活动 - 使用谷歌地图),并且每 5 秒更新一次地图上的位置(我更新用户的“经度”和“纬度”字段Firebase 数据库每 3 秒一次,然后每 5 秒读取一次此字段并更新地图上的所有标记)。

我试着用 3 部不同的手机四处走动,并注意到并非所有的标记(它并不总是相同的标记,但如果某个标记卡在一部手机上,则相同的标记卡在其他手机上)随着我一起移动走。他们开始移动一小段时间,然后完全停止移动。在我继续走一会儿之后,它们突然更新(跳到当前位置)然后又卡住了......或者换句话说,一些标记的更新发生了很大的延迟。

这种延迟的原因可能是什么,我该如何解决?

我的 Firebase 数据库(经理和用户)的图片:

我的 Firebase 数据库的图片 - 经理

我的 Firebase 数据库的图片 - 用户

(我创建了一个代表一个组的经理,经理有一个在他的组中的用户列表,然后我浏览经理的用户列表并更新他们在 Firebase 数据库上的位置。然后当用户点击“地图”按钮通过 GroupMapActivity 并在那里我每 5 秒从 Firebase 数据库读取位置并更新标记)。

使用服务更新 Firebase 数据库位置的代码:

package com.example.lidor.findmygroup;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

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;

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

public class FindMeService extends IntentService
{
    FirebaseDatabase firebaseDatabase;
    DatabaseReference databaseReference;
    String userEmail = "", key = "";
    LocationTrack locationTrack;
    double longitude, latitude;
    User user;

    public FindMeService()
    {
        super("FindMeService");
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        firebaseDatabase = FirebaseDatabase.getInstance();
        if (intent.hasExtra("email"))
            userEmail = intent.getStringExtra("email").toString();

        databaseReference = firebaseDatabase.getReference("USERS");
        databaseReference.addValueEventListener(new ValueEventListener()
        {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot)
            {
                for (DataSnapshot d : dataSnapshot.getChildren())
                {
                    User curUser = d.getValue(User.class);
                    if (userEmail.equals(curUser.Email))
                    {
                        key = d.getKey();
                        user = curUser;
                        break;
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

        while (true)
        {
            try
            {
                Thread.sleep(3000);

                locationTrack = new LocationTrack(FindMeService.this);
                if (locationTrack.canGetLocation())
                {
                    longitude = locationTrack.getLongitude();
                    latitude = locationTrack.getLatitude();

                    databaseReference.child("USERS").child(key).
                            addListenerForSingleValueEvent(new ValueEventListener()
                            {
                                @Override
                                public void onDataChange(DataSnapshot dataSnapshot)
                                {
                                    Map<String, Object> updates = new HashMap<>();
                                    for (DataSnapshot s : dataSnapshot.getChildren())
                                    {
                                        updates.put(s.getKey(), s.getValue());
                                    }
                                    updates.put("UserName", user.UserName);
                                    updates.put("Age", user.Age);
                                    updates.put("Phone", user.Phone);
                                    updates.put("City", user.City);
                                    updates.put("Email", user.Email);
                                    updates.put("longitude", longitude);
                                    updates.put("latitude", latitude);
                                    updates.put("Is_In_Group", user.Is_In_Group);
                                    updates.put("ManagerEmail", user.ManagerEmail);
                                    updates.put("Is_Manager", user.Is_Manager);
                                    updates.put("Is_Connected", user.Is_Connected);

                                    databaseReference.child(key).updateChildren(updates);
                                }

                                @Override
                                public void onCancelled(DatabaseError databaseError) {
                                }
                            });
                }
                else
                {
                    locationTrack.showSettingsAlert();
                    Toast.makeText(FindMeService.this, "No GPS signal",
                            Toast.LENGTH_LONG).show();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }
}

组图活动:

package com.example.lidor.findmygroup;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdate;
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.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.firebase.auth.FirebaseAuth;
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;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class GroupMapActivity extends FragmentActivity implements OnMapReadyCallback
{
    private GoogleMap mMap;
    Handler handler;
    String email = "", managerEmail = "", managerKey = "";
    int i = 0;
    Marker marker;

    FirebaseAuth firebaseAuth;
    FirebaseDatabase firebaseDatabase, firebaseDatabase1, firebaseDatabase2;
    DatabaseReference databaseReference, databaseReference1, databaseReference2;

    Boolean endFor = false, endFor1 = false, endFor2 = false;

    ProgressDialog progressDialog;

    HashMap<String, Marker> markers;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_map);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        firebaseAuth = FirebaseAuth.getInstance();
        firebaseDatabase = FirebaseDatabase.getInstance();
        firebaseDatabase1 = FirebaseDatabase.getInstance();
        firebaseDatabase2 = FirebaseDatabase.getInstance();
        //builder = new LatLngBounds.Builder();

        Intent intent = getIntent();
        if (intent.hasExtra("email")) email = intent.getStringExtra("email").toString();
        markers = new HashMap<>();

        progressDialog = new ProgressDialog(GroupMapActivity.this);
        progressDialog.setMessage("Map Loading Please Wait...");
        progressDialog.show();
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        mMap = googleMap;

        handler = new Handler();
        handler.postDelayed(new Runnable()
        {
            public void run()
            {
                Real_Time_Group_Map();
                progressDialog.dismiss();
                handler.postDelayed(this, 1000);
            }
        }, 1000);
    }

    public void Real_Time_Group_Map()
    {
        // 1# -------------------------------------------------------------------------------------

        databaseReference = firebaseDatabase.getReference("USERS");
        databaseReference.addValueEventListener(new ValueEventListener()
        {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot)
            {
                for (DataSnapshot d : dataSnapshot.getChildren())
                {
                    if (endFor) continue;

                    User curUser = d.getValue(User.class);
                    if (email.equals(curUser.Email))
                    {
                        endFor = true;
                        managerEmail = curUser.ManagerEmail;

                        databaseReference = firebaseDatabase.getReference("MANAGERS");
                        databaseReference.addValueEventListener(new ValueEventListener()
                        {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot)
                            {
                                for (DataSnapshot d : dataSnapshot.getChildren())
                                {
                                    if (endFor1) continue;

                                    Manager curManager = d.getValue(Manager.class);
                                    if (managerEmail.equals(curManager.Email))
                                    {
                                        endFor1 = true;
                                        managerKey = d.getKey();

                                        databaseReference1 = firebaseDatabase1.getReference("MANAGERS").
                                                child(managerKey).child("Group Users");
                                        databaseReference1.addValueEventListener(new ValueEventListener()
                                        {
                                            @Override
                                            public void onDataChange(DataSnapshot dataSnapshot)
                                            {

                                                for (DataSnapshot d : dataSnapshot.getChildren())
                                                {
                                                    final String curFriend = d.getValue().toString();

                                                    databaseReference2 = firebaseDatabase2.getReference("USERS");
                                                    databaseReference2.addValueEventListener(new ValueEventListener()
                                                    {
                                                        @Override
                                                        public void onDataChange(DataSnapshot dataSnapshot)
                                                        {
                                                            for (DataSnapshot d : dataSnapshot.getChildren())
                                                            {
                                                                User curUser = d.getValue(User.class);
                                                                String emailUser = curUser.Email;

                                                                if (curFriend.equals(emailUser))
                                                                {
                                                                    LatLng location = new LatLng(
                                                                            curUser.latitude, curUser.longitude);

                                                                    Marker delMarker = markers.get(emailUser);
                                                                    if (delMarker != null) delMarker.remove();
                                                                    markers.remove(emailUser);

                                                                    if (curUser.Is_Manager)
                                                                    {
                                                                        marker = mMap.addMarker(new MarkerOptions()
                                                                                      .position(location).title(curUser.UserName).icon(
                                                                                       BitmapDescriptorFactory.defaultMarker(
                                                                                       BitmapDescriptorFactory.HUE_BLUE)).
                                                                                       snippet(emailUser));
                                                                    }

                                                                    else
                                                                    {
                                                                        marker = mMap.addMarker(new MarkerOptions()
                                                                                     .position(location).title(curUser.UserName)
                                                                                     .snippet(emailUser));

                                                                    }

                                                                    markers.put(emailUser, marker);
                                                                    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location,18));
                                                                }
                                                            }
                                                        }

                                                        @Override
                                                        public void onCancelled(DatabaseError databaseError) {
                                                        }
                                                    });
                                                }

                                                mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener()
                                                {
                                                    @Override
                                                    public boolean onMarkerClick(Marker marker)
                                                    {
                                                        Intent intent = new Intent(GroupMapActivity.this, MemberActivity.class);
                                                        intent.putExtra("email", marker.getSnippet());
                                                        startActivity(intent);
                                                        return false;
                                                    }
                                                });
                                            }

                                            @Override
                                            public void onCancelled(DatabaseError databaseError) {
                                            }
                                        });

                                        break;
                                    }
                                }
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {
                            }
                        });

                        break;
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    }
}

标签: androidgoogle-mapsfirebaseandroid-studiofirebase-realtime-database

解决方案


推荐阅读