问题
My android application function is to track the user location when it walk/run or when he never moves(then location should not change)First, the location is inaccurate and red marker keeps popping out on the map even if i never move. the position where it pops out is also inaccurate.
For those who did similar location tracking app before, the blue dot should be the same place as the latest red marker right? but my blue dot is always away most of the time. red marker shows a more accurate position(although still inaccurate)
i have tested it in my house, outside, in a vehicle. when it is in my house, sometimes location keeps changing, sometimes location never change. i cannot predict it. usually gps don't work well in-house so i leave it first when i test it outside, sometimes it is better but it is still inaccurate. when i never move/move or move slow it update on the wrong location. althought it is sometimes little better then in roof. but in the end it is still unuseable. when i test it in the car, it is better as it won't pop out so much location should be more accurate blue dot and red marker are sometimes together. although there are still inaccurate sometimes. but it does not matter as my app is supposed to use when the user is walking/running not in a moving vehicle.
for all three, red marker appears(no matter how frequently) around the correct environment(house, road, certain building) sometimes, but the blue dot is not, most of the times it is wrong. but i wanted the blue dot as a tracker for the user. user would not know which red marker is his current location even if it is accurate. the title "you are here" could appear on any marker when i tap on it, where it is new or old. so it is not effective. and when a new one appear, the title does not appear by itself.
the problem i am trying to solve is to ensure location accuracy, even if not good or perfect at lease be useable, and have the blue dot track the user continuously,or red marker as long as sometimes tell the where is he accurately(title only appears on the latest marker by itself).
i am research for a long time and i do not know what else i can implement to make it more accurate. the distance calculation i believe should be accurate but it depends on the location so it will becomes inaccurate too. sorry for the large text i just thought i should explain myself clearer...
public class MainActivity extends FragmentActivity implements LocationListener{
protected LocationManager locationManager;
private GoogleMap googleMap;
Button btnStartMove,btnPause,btnResume,btnStop;
static double n=0;
Long s1,r1;
double dis=0.0;
Thread t1;
EditText userNumberInput;
boolean bool=false;
int count=0;
double speed = 1.6;
double lat1,lon1,lat2,lon2,lat3,lon3,lat4,lon4;
double dist = 0.0;
double time = 0.0;
double velocity = 0.0;
TextView distance;
Button btnDuration;
float[] result;
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES =1; // in Meters
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 4000; //in milliseconds
boolean startDistance = false;
boolean startButtonClicked = false;
MyCount counter;
int timer = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MINIMUM_TIME_BETWEEN_UPDATES,MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, this);
if(isGooglePlay())
{
setUpMapIfNeeded();
}
distance=(TextView)findViewById(R.id.Distance);
btnDuration=(Button)findViewById(R.id.Duration);
btnStartMove=(Button)findViewById(R.id.Start);//start moving
btnStop=(Button)findViewById(R.id.Stop);
//prepare distance...........
Log.d("GPS Enabled", "GPS Enabled");
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String provider = locationManager.getBestProvider(criteria, true);
Location location=locationManager.getLastKnownLocation(provider);
btnStartMove.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
Log.d("GPS Enabled", "GPS Enabled");
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String provider = locationManager.getBestProvider(criteria, true);
Location location=locationManager.getLastKnownLocation(provider);
lat3 = location.getLatitude();
lon3 = location.getLongitude();
startButtonClicked=true;
startDistance=true;
counter= new MyCount(30000,1000);
counter.start();
btnStartMove.setText("Started...");
}
});
btnStop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
startButtonClicked=false;
startDistance=false;
//Double.valueOf(distance.getText().toString()
Double value=dist;
Double durationValue=time;
Double speedValue=velocity;
Intent intent = new Intent(MainActivity.this, FinishActivity.class);
intent.putExtra("dist", value);
intent.putExtra("time",durationValue);
intent.putExtra("velocity",speedValue);
startActivity(intent);
counter.cancel();
n=0;
r1=null;
time=0.0;
btnStartMove.setText("Start Move");
finish();
}
});
btnDuration.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
if(startButtonClicked=true)
{
time=n*30+r1;
velocity=dist/time;
DecimalFormat df = new DecimalFormat("#.##");
Toast.makeText(MainActivity.this,"Duration :"+String.valueOf(time) + "Speed :"+String.valueOf(df.format(velocity)),Toast.LENGTH_LONG).show();
}
}
});
if(location!= null)
{
//Display current location in Toast
String message = String.format(
"Current Location \n Longitude: %1$s \n Latitude: %2$s",
location.getLongitude(), location.getLatitude()
);
Toast.makeText(MainActivity.this, message,
Toast.LENGTH_LONG).show();
}
else if(location == null)
{
Toast.makeText(MainActivity.this,
"Location is null",
Toast.LENGTH_LONG).show();
}
}
private void setUpMapIfNeeded() {
if(googleMap == null)
{
googleMap =((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.displayMap)).getMap();
if(googleMap != null)
{
setUpMap();
}
}
}
private void setUpMap()
{
//Enable MyLocation Layer of Google Map
googleMap.setMyLocationEnabled(true);
//Get locationManager object from System Service LOCATION_SERVICE
//LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
//Create a criteria object to retrieve provider
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//Get the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
if(provider == null)
{
onProviderDisabled(provider);
}
//set map type
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//Get current location
Location myLocation = locationManager.getLastKnownLocation(provider);
if(myLocation != null)
{
double latitude = myLocation.getLatitude();
//Get longitude of the current location
double longitude = myLocation.getLongitude();
//Create a LatLng object for the current location
LatLng latLng = new LatLng(latitude, longitude);
//Show the current location in Google Map
googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//Zoom in the Google Map
googleMap.animateCamera(CameraUpdateFactory.zoomTo(20));
googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).snippet("You are here!").title("You are here!"));
}
locationManager.requestLocationUpdates(provider, 0, 0, this);
}
private boolean isGooglePlay()
{
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (status == ConnectionResult.SUCCESS)
{
Toast.makeText(MainActivity.this, "Google Play Services is available",
Toast.LENGTH_LONG).show();
return(true);
}
else
{
GooglePlayServicesUtil.getErrorDialog(status, this, 10).show();
}
return (false);
}
@Override
public void onLocationChanged(Location myLocation) {
System.out.println("speed " + myLocation.getSpeed());
//show location on map.................
//Get latitude of the current location
double latitude = myLocation.getLatitude();
//Get longitude of the current location
double longitude = myLocation.getLongitude();
//Create a LatLng object for the current location
LatLng latLng = new LatLng(latitude, longitude);
//Show the current location in Google Map
googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//Zoom in the Google Map
googleMap.animateCamera(CameraUpdateFactory.zoomTo(20));
googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).snippet("You are here!").title("You are here!"));
//show distance............................
if(startDistance == true)
{
Toast.makeText(MainActivity.this,
"Location has changed",
Toast.LENGTH_LONG).show();
if(myLocation != null)
{
//latitude.setText("Current Latitude: " + String.valueOf(loc2.getLatitude()));
//longitude.setText("Current Longitude: " + String.valueOf(loc2.getLongitude()));
float[] results = new float[1];
Location.distanceBetween(lat3, lon3, myLocation.getLatitude(), myLocation.getLongitude(), results);
System.out.println("Distance is: " + results[0]);
dist += results[0];
DecimalFormat df = new DecimalFormat("#.##"); // adjust this as appropriate
if(count==1)
{
distance.setText(df.format(dist) + "meters");
}
lat3=myLocation.getLatitude();
lon3=myLocation.getLongitude();
count=1;
}
}
if(startButtonClicked == true)
{
startDistance=true;
}
}
@Override
public void onProviderDisabled(String provider) {
Toast.makeText(MainActivity.this,
"Provider disabled by the user. GPS turned off",
Toast.LENGTH_LONG).show();
}
@Override
public void onProviderEnabled(String provider) {
Toast.makeText(MainActivity.this,
"Provider enabled by the user. GPS turned on",
Toast.LENGTH_LONG).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Toast.makeText(MainActivity.this, "Provider status changed",
Toast.LENGTH_LONG).show();
}
@Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
@Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MINIMUM_TIME_BETWEEN_UPDATES,MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, this);
}
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onFinish() {
counter= new MyCount(30000,1000);
counter.start();
n=n+1;
}
@Override
public void onTick(long millisUntilFinished) {
s1=millisUntilFinished;
r1=(30000-s1)/1000;
}
}}
来源:https://stackoverflow.com/questions/21655553/ensure-location-accuracy-and-track-user-on-google-map