I've recently been working on simple speed calculations for an application I'm working on, but the code I have takes far too long to retrieve the location, and I know that questions like this have been asked before, but none of the answers seem to retrieve the results I'm looking for. So, how can I make this code have gps fixes within a matter of seconds, and is it even possible?
My LocationListener:
package me.dylan.acf;
import java.text.DecimalFormat;
import java.util.ArrayList;
import android.app.NotificationManager;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.text.format.Time;
import android.widget.TextView;
public class GPSManager implements LocationListener {
ArrayList<Double> avgspeeds = new ArrayList<Double>();
TextView debug;
NotificationManager mngr;
double avgspeed;
long lastTime = 0;
GraphView view;
Location lastloc;
int earthRadius = 6371;
long delaytime = 30;
ArrayList<Double> allspeeds = new ArrayList<Double>();
public GPSManager(TextView view) {
debug = view;
Location location = ACF.instance.lmanager
.getLastKnownLocation(ACF.instance
.getProperLocationsServices(ACF.instance
.getApplicationContext()));
if (location != null) {
double speed = location.getSpeed();
lastloc = location;
debug.setText("Average Speed: " + avgspeed + "\nCurrent speed: "
+ speed + "\nLocation updates: " + avgspeeds.size());
}
}
#Override
public void onLocationChanged(Location location) {
// DecimalFormat format = new DecimalFormat("0.00");
double speed = location.getSpeed();
if (lastloc != null) {
double latDist = Math.toRadians(location.getLatitude()
- lastloc.getLatitude());
double lonDist = Math.toRadians(location.getLongitude()
- lastloc.getLongitude());
double lat1 = Math.toRadians(location.getLatitude());
double lat2 = Math.toRadians(lastloc.getLatitude());
double a = Math.sin(latDist / 2) * Math.sin(latDist / 2)
+ Math.sin(lonDist / 2) * Math.sin(lonDist / 2)
* Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
speed = (dist * 0.621371) / Math.abs(System.currentTimeMillis() - lastTime * 60 * 60 * 60);
lastTime = System.currentTimeMillis();
}
allspeeds.add(speed);
if (allspeeds.size() > 30) {
allspeeds.remove(0);
}
avgspeed = 0;
for (double d : allspeeds) {
avgspeed += d;
}
avgspeed /= allspeeds.size();
// avgspeed = Double.parseDouble(format.format(avgspeed));
avgspeeds.add(avgspeed);
lastloc = location;
debug.setText("Average Speed: " + avgspeed + "\nCurrent speed: "
+ speed + "\nLocation updates: " + avgspeeds.size());
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
Where I call it:
public void updateWithProperService() {
lmanager.requestSingleUpdate(
getProperLocationsServices(getApplicationContext()), GPSmngr,
null);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
updateWithProperService();
}
}, 10000);
}
public String getProperLocationsServices(Context context) {
if (lmanager == null)
lmanager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
int minTime = 3000;
/*
* boolean isGPS = false; boolean isNetwork = false; try { isGPS =
* lmanager.isProviderEnabled(LocationManager.GPS_PROVIDER); } catch
* (Exception e) { e.printStackTrace(); } try { isNetwork = lmanager
* .isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch
* (Exception e) { e.printStackTrace(); }
*/
List<String> matchingProviders = lmanager.getAllProviders();
Location bestResult = null;
long bestTime = 0;
for (String provider : matchingProviders) {
Location location = lmanager.getLastKnownLocation(provider);
if (location != null) {
// float accuracy = location.getAccuracy();
long time = location.getTime();
// float bestAccuracy;
/*
* if ((time > minTime && accuracy < bestAccuracy )) {
* bestResult = location; bestTime = time; } else
*/if (time < minTime &&
/* bestAccuracy == Float.MAX_VALUE && */time < bestTime) {
bestResult = location;
bestTime = time;
}
}
}
if (bestResult != null)
return bestResult.getProvider();
else
return LocationManager.NETWORK_PROVIDER;
}
google has released a nice API on their recent Google IO 2013 event:
https://developers.google.com/events/io/sessions/324498944
you should check it out and see how you can minimize your code.
do note that it requires that the device would have the play store app for this to work.
this method has many advantages over using the normal location sensors (battery, speed , accuracy,...) .
gps needs about 15 seconds if it was disabled before and when using Assisted GPS.
you cannot improve that.
Whitout AGPS it needs 25-35 seconds, under good conditions.
The term is called "Time to First fix" (TTF).
Related
I'm using Unity3D and I created simple distance, speed and acceleration calculator using latitude and longitude of last position. I'm calculating last distance, speed and acceleration in each GPS update (approximately once per second). But sometimes (2-3 second interval) latitude and longitude values changes rapidly (in clear weather and no obstacles). That's why speed and acceleration values gets unreal results. For example, at stable 40 km/h speed, speed value becomes 60 km/h and returns to 40 km/h within 2-3 second. I'm here to ask how can I avoid this inaccurate and rapid GPS data changes?
I'm using Nexus 5 device
There is my code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
public Text longitude, latitude, lonAText, latAText, lonBText, latBText;
public Text result, overallResult, speedText, lastTimeText, timerText, accelerationText, speed0Text;
float lonA, lonB, latA, latB, overallDistance, lastDistance, timer, lastTime, speed, speed0, acceleration;
bool firstTime, allowTimer;
public AudioSource audio;
void Awake()
{
overallDistance = 0;
lastDistance = 0;
timer = 0;
lastTime = 0;
speed = 0;
speed0 = 0;
firstTime = true;
allowTimer = true;
}
IEnumerator Start()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
yield break;
// Start service before querying location
Input.location.Start(1, 1);
// Wait until service initializes
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
// Service didn't initialize in 20 seconds
if (maxWait < 1)
{
print("Timed out");
yield break;
}
// Connection has failed
if (Input.location.status == LocationServiceStatus.Failed)
{
print("Unable to determine device location");
yield break;
}
else
{
// Access granted and location value could be retrieved
print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
}
// Stop service if there is no need to query location updates continuously
//Input.location.Stop();
}
void Update()
{
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
timer += Time.deltaTime;
timerText.text = timer.ToString();
if (lonA != Input.location.lastData.longitude || latA != Input.location.lastData.latitude)
{
audio.Play();
CalculateDistances(lonA, latA, Input.location.lastData.longitude, Input.location.lastData.latitude); // last distance and overall distanceS
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
lastTime = timer;
lastTimeText.text = lastTime.ToString();
timer = 0;
speed0 = speed;
speed0Text.text = speed0.ToString();
CalculateSpeed();
CalculateAcceleration();
}
}
public static float Radians(float x)
{
return x * Mathf.PI / 180;
}
public void CalculateDistances(float firstLon, float firstLat, float secondLon, float secondLat)
{
lonAText.text = firstLon.ToString();
latAText.text = firstLat.ToString();
lonBText.text = secondLon.ToString();
latBText.text = secondLat.ToString();
float dlon = Radians(secondLon - firstLon);
float dlat = Radians(secondLat - firstLat);
float distance = Mathf.Pow(Mathf.Sin(dlat / 2), 2) + Mathf.Cos(Radians(firstLat)) * Mathf.Cos(Radians(secondLat)) * Mathf.Pow(Mathf.Sin(dlon / 2), 2);
float c = 2 * Mathf.Atan2(Mathf.Sqrt(distance), Mathf.Sqrt(1 - distance));
lastDistance = 6371 * c * 1000;
result.text = lastDistance.ToString() + " meters";
overallDistance += lastDistance; // bu 1 anliq 6.000.000-dan boyuk qiymet ala biler
StartCoroutine(Overall());
}
IEnumerator Overall()
{
if (firstTime)
{
firstTime = false;
yield return new WaitForSeconds(2);
if (overallDistance > 6000000)
{
overallDistance = 0;
lastDistance = 0;
}
}
overallDistance += lastDistance;
overallResult.text = overallDistance.ToString() + " meters";
}
void CalculateSpeed()
{
speed = lastDistance / lastTime * 3.6f;
speedText.text = speed.ToString();
}
void CalculateAcceleration()
{
acceleration = (speed - speed0) / lastTime;
accelerationText.text = acceleration.ToString();
}
}
I get an error when I click on my action button . I take two coordinates from a class called " GPSTracker " and I return to my class with methods " getLatitude " and " getLongitude " . If I click on my action button I get this error :
09-12 17:07:46.898 24575-24575/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.application.marcoopsone.centrocommercialecampania, PID: 24575
java.lang.NumberFormatException: Invalid double: "4782877,28"
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.initialParse(StringToReal.java:164)
at java.lang.StringToReal.parseDouble(StringToReal.java:282)
at java.lang.Double.parseDouble(Double.java:301)
at com.application.marcoopsone.centrocommercialecampania.FragmentCar.getFila(FragmentCar.java:177)
at com.application.marcoopsone.centrocommercialecampania.FragmentCar$1.onClick(FragmentCar.java:95)
at android.view.View.performClick(View.java:5254)
at android.view.View$PerformClick.run(View.java:21174)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6862)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
if I do run the application on the emulator genymotion , all right ! if I use my samsung tablet I get the error . how do I fix ?
GPSTracker
import ...
public class GPSTracker extends Service implements LocationListener {
private final Context context;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.context = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
public void stopUsingGPS() {
if (locationManager != null) {
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude() {
if(location != null) {
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude() {
if(location != null) {
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation() {
return this.canGetLocation;
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("GPS is settings");
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Fragment Car
public class FragmentCar extends android.support.v4.app.Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private TextView textFila;
private Button btn;
//VARIABILI GPS
GPSTracker gps;
static final int RAGGIO = 6371;
static final double PIGRECO = Math.PI;
double f1_latitudine = 41.00413;
double f1_longitudine = 14.32642;
double f2_latitudine = 41.00399;
double f2_longitudine = 14.32643;
double f3_latitudine = 41.00385;
double f3_longitudine = 14.32645;
double f4_latitudine = 41.0037;
double f4_longitudine = 14.32647;
double f5_latitudine = 41.00359;
double f5_longitudine = 14.32648;
double p_latitudine = 41.00388;
double p_longitudine = 14.32584;
double ps_latitudine = 41.00402;
double ps_longitudine = 14.3248;
private FloatingActionButton mFAB;
public FragmentCar() {
// Required empty public constructor
}
public static android.support.v4.app.Fragment newInstance(String param1, String param2) {
FragmentCar fragment = new FragmentCar();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View layout = inflater.inflate(R.layout.fragment_car, container, false);
//setupFAB();
textFila = (TextView) layout.findViewById(R.id.textFila);
btn = (Button) layout.findViewById(R.id.buttonSavePosition);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFila();
}
});
return layout;
}
private void setupFAB() {
//define the icon for the main floating action button
ImageView iconFAB = new ImageView(getActivity());
iconFAB.setImageResource(R.drawable.ic_action_new);
//set the appropriate background for the main floating action button along with its icon
mFAB = new FloatingActionButton.Builder(getActivity())
.setContentView(iconFAB)
.setBackgroundDrawable(R.drawable.selector_button_red)
.build();
mFAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFila();
}
});
}
public void getFila(){
gps = new GPSTracker(getActivity());
if(gps.canGetLocation()) {
double latitude = 0;
double longitude = 0;
latitude = new Double(gps.getLatitude());
longitude = new Double(gps.getLongitude());
DecimalFormat df = new DecimalFormat("0.000000");
double lat = Double.parseDouble(df.format(latitude));
double lon = Double.parseDouble(df.format(longitude));
double laRadianti = (lat * PIGRECO) / 180;
double loRadianti = (lon * PIGRECO) / 180;
double f1_latitudineRadianti = (f1_latitudine * PIGRECO) / 180;
double f1_longitudineRadianti = (f1_longitudine * PIGRECO) / 180;
double f2_latitudineRadianti = (f2_latitudine * PIGRECO) / 180;
double f2_longitudineRadianti = (f2_longitudine * PIGRECO) / 180;
double f3_latitudineRadianti = (f3_latitudine * PIGRECO) / 180;
double f3_longitudineRadianti = (f3_longitudine * PIGRECO) / 180;
double f4_latitudineRadianti = (f4_latitudine * PIGRECO) / 180;
double f4_longitudineRadianti = (f4_longitudine * PIGRECO) / 180;
double f5_latitudineRadianti = (f5_latitudine * PIGRECO) / 180;
double f5_longitudineRadianti = (f5_longitudine * PIGRECO) / 180;
double p_latitudineRadianti = (p_latitudine * PIGRECO) / 180;
double p_longitudineRadianti = (p_longitudine * PIGRECO) / 180;
double distanzaUno = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(f1_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(f1_latitudineRadianti) * Math.cos((loRadianti - f1_longitudineRadianti))))) * 1000;
double distanzaDue = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(f2_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(f2_latitudineRadianti) * Math.cos((loRadianti - f2_longitudineRadianti))))) * 1000;
double distanzaTre = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(f3_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(f3_latitudineRadianti) * Math.cos((loRadianti - f3_longitudineRadianti))))) * 1000;
double distanzaQuattro = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(f4_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(f4_latitudineRadianti) * Math.cos((loRadianti - f4_longitudineRadianti))))) * 1000;
double distanzaCinque = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(f5_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(f5_latitudineRadianti) * Math.cos((loRadianti - f5_longitudineRadianti))))) * 1000;
double distanzaPunto = ((RAGGIO * Math.acos(Math.sin(laRadianti) * Math.sin(p_latitudineRadianti) +
Math.cos(laRadianti) * Math.cos(p_latitudineRadianti) * Math.cos((loRadianti - p_longitudineRadianti))))) * 1000;
DecimalFormat df1 = new DecimalFormat("0.00");
double distanzaFilaUno = Double.parseDouble(df1.format(distanzaUno));
double distanzaFilaDue = Double.parseDouble(df1.format(distanzaDue));
double distanzaFilaTre = Double.parseDouble(df1.format(distanzaTre));
double distanzaFilaQuattro = Double.parseDouble(df1.format(distanzaQuattro));
double distanzaFilaCinque = Double.parseDouble(df1.format(distanzaCinque));
double distanzaFilaPunto = Double.parseDouble(df1.format(distanzaPunto));
if(distanzaFilaUno < distanzaFilaDue && distanzaFilaUno < distanzaFilaTre && distanzaFilaUno < distanzaFilaQuattro && distanzaFilaUno < distanzaFilaCinque){
if(distanzaFilaUno > 110 && distanzaFilaUno < 300){
textFila.setText("fila uno");
} else if (distanzaFilaCinque > 300){
textFila.setText("Ops!");
} else {
textFila.setText("1");
}
} else if (distanzaFilaDue < distanzaFilaUno && distanzaFilaDue < distanzaFilaTre && distanzaFilaDue < distanzaFilaQuattro && distanzaFilaDue < distanzaFilaCinque){
if(distanzaFilaDue > 110 && distanzaFilaDue < 300){
textFila.setText("fila due");
} else if (distanzaFilaCinque > 300){
textFila.setText("Ops!");
} else {
textFila.setText("2");
}
} else if (distanzaFilaTre < distanzaFilaUno && distanzaFilaTre < distanzaFilaDue && distanzaFilaTre < distanzaFilaQuattro && distanzaFilaTre < distanzaFilaCinque){
if(distanzaFilaTre > 110 && distanzaFilaTre < 300){
textFila.setText("fila tre");
} else if (distanzaFilaCinque > 300){
textFila.setText("Ops!");
} else {
textFila.setText("3");
}
} else if (distanzaFilaQuattro < distanzaFilaUno && distanzaFilaQuattro < distanzaFilaDue && distanzaFilaQuattro < distanzaFilaTre && distanzaFilaQuattro < distanzaFilaCinque){
if(distanzaFilaQuattro > 110 && distanzaFilaQuattro < 300){
textFila.setText("fila quattro");
} else if (distanzaFilaCinque > 300){
textFila.setText("Ops!");
} else {
textFila.setText("4");
}
} else if (distanzaFilaCinque < distanzaFilaUno && distanzaFilaCinque < distanzaFilaDue && distanzaFilaCinque < distanzaFilaTre && distanzaFilaCinque < distanzaFilaQuattro){
if(distanzaFilaCinque > 110 && distanzaFilaCinque < 300){
textFila.setText("fila cinque");
} else if (distanzaFilaCinque > 300){
textFila.setText("Ops!");
} else {
textFila.setText("5");
}
}
} else {
gps.showSettingsAlert();
}
}
}
the problem is in your line no 177.you are getting comma there,SO you need to replace it by(.)dot to parse it as a double.
Change the line
double distanzaFilaQuattro = Double.parseDouble(df1.format(distanzaQuattro));
to
double distanzaFilaQuattro = Double.parseDouble((df1.format(distanzaQuattro)).replace(",","."));
I am trying to calculate distance using gps lat and long data.
but i can't get accurate result .when i am given a static data ,then distance formula work perfect ,
public class NWDService extends Service implements LocationListener {
private LocationManager myLocationManager;
private LocationProvider myLocationProvider;
NotificationManager myNotificationManager;
private long frequency;
private Handler handler;
private double total_distance = 0;
private Location currentLocation;
public void onLocationChanged(Location newLocation) {
try {
System.out.println("latitude current :"+currentLocation.getLatitude());
System.out.println("latitude current :"+currentLocation.getLongitude());
System.out.println("latitude new :"+newLocation.getLatitude());
System.out.println("latitude new :"+newLocation.getLongitude());
System.out.println("distance total :"+total_distance);
//System.out.println(distance(22.306813, 73.180239,22.301016, 73.177986, 'K') + " Kilometers\n");
double diff = 0.0;
diff = currentLocation.getLatitude()- newLocation.getLatitude();
System.out.println("difference ::"+diff);
if(diff != 0){
total_distance = total_distance + distance(currentLocation.getLatitude(), currentLocation.getLongitude(), newLocation.getLatitude(), newLocation.getLatitude(), 'K');
//total_distance = distance(22.307309,73.181098,23.030000,72.580000,'K');
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Total Distance:"+total_distance, Toast.LENGTH_LONG).show();
}
});
}
currentLocation = newLocation;
} catch (Exception e) {
currentLocation = newLocation;
e.printStackTrace();
}
}
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts decimal degrees to radians :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts radians to decimal degrees :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
private void myNotify(String text) {
Notification notif = new Notification(R.drawable.ic_launcher, text, System
.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Home.class), 0);
notif.setLatestEventInfo(this, "NotWhileDriving", text, contentIntent);
// notif.defaults = Notification.DEFAULT_VIBRATE;
myNotificationManager.notify((int) System.currentTimeMillis(), notif);
}
#Override
public void onCreate() {
super.onCreate();
handler = new Handler();
android.util.Log.d("NWD", "creating");
myLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
System.out.println("location manager:"+myLocationManager.getAllProviders());
myLocationProvider = myLocationManager.getProvider("gps");
myNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
updatePreferences();
}
public void updatePreferences() {
// sync local variables with preferences
android.util.Log.d("NWD", "updating preferences");
frequency = 10;
// update the LM with the new frequency
myLocationManager.removeUpdates(this);
myLocationManager.requestLocationUpdates(myLocationProvider.getName(),frequency, 0, this);
}
#Override
public void onDestroy() {
super.onDestroy();
android.util.Log.d("NWD", "destroying");
myLocationManager.removeUpdates(this);
myNotify("stopping");
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
android.util.Log.d("NWD", "starting");
currentLocation = myLocationManager
.getLastKnownLocation(myLocationProvider.getName());
myNotify("starting");
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
#Override
public IBinder onBind(Intent arg0) {
return null; // this is for heavy IPC, not used
}
}
Please help me what is the problem in my code...
Just use Location.distanceTo(Location) it will give you a really distance between two different Locations.
First, I don't believe this code works on different parts of the earth. I don't see the WGS 84 parameters, only some magic numbers in
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
Where did you get that from? Do you understand it?
Second, if your data is noisy, you're adding up this noise by summing totalDistance. You might want to check if the distance is above some threshold and only add totalDistance if the distance threshold is exceeded.
You can use Google Distance matrix API for find accurate result of distance between two place.
for detail study you can refer from:
https://developers.google.com/maps/documentation/distancematrix/
I am calculating the speed using the Distance / Time however when onlocation changed it goes up to infinity and decrease gradually.
package water.Spill;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.util.FloatMath;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import water.Spill.LatLon;
import android.hardware.Camera;
public class GPS2 extends Activity implements SurfaceHolder.Callback {
LocationManager locationManager;
LocationListener locationListener;
//text views to display latitude and longitude
TextView latituteField;
TextView longitudeField;
TextView currentSpeedField;
TextView kmphSpeedField;
TextView avgSpeedField;
TextView avgKmphField;
TextView gpsOnOff;
//objects to store positional information
protected double lat;
protected double lon;
ArrayList<LatLon> myList = new ArrayList<LatLon>();
//objects to store values for current and average speed
protected double currentSpeed;
protected double kmphSpeed;
protected double avgSpeed;
protected double avgKmph;
protected double totalSpeed;
protected double totalKmph;
//Camera
private SurfaceView mSurfaceView ;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
private boolean mPreviewRunning;
boolean gps_enabled = false;
boolean network_enabled = false;
//counter that is incremented every time a new position is received, used to calculate average speed
int counter = 0;
double totalDistance=0;
//timer
TextView text3;
TextView secondLabel;
TextView minutesLabel;
TextView hourLabel;
long starttime = 0;
long spdstarttime = 0;
Handler h2 = new Handler();
Runnable run = new Runnable() {
public void run() {
long spdmillis = System.currentTimeMillis() - spdstarttime;
long millis = System.currentTimeMillis() - starttime;
int spdseconds = (int) (spdmillis / 1000);
int spdhours = spdseconds/60/60;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
int hours = minutes/60;
seconds = seconds % 60;
minutes = minutes % 60;
currentSpeedField = (TextView) findViewById(R.id.speed);
secondLabel = (TextView) findViewById(R.id.seconds);
minutesLabel = (TextView) findViewById(R.id.minutes);
hourLabel = (TextView) findViewById(R.id.hour);
secondLabel.setText(String.valueOf(seconds) + "s");
minutesLabel.setText(String.valueOf(minutes)+ "m");
hourLabel.setText(String.valueOf(hours)+ "h");
if(myList.size() > 1){
LatLon ll1 = myList.get(myList.size()-2);
LatLon ll2 = myList.get(myList.size()-1);
double distance = 0;
distance = distFrom(ll1.getLat(), ll1.getLon(), ll2.getLat(), ll2.getLon());
if(ll1.getLat()== ll2.getLat() && ll1.getLon() == ll2.getLon()){
currentSpeed = 0;
}
else{
distance = round(distance,3,BigDecimal.ROUND_HALF_UP);
currentSpeed = (distance*1000)/spdseconds;
double test12 = spdseconds;
System.out.println("distance " + (distance*1000));
System.out.println("time " + test12);
//currentSpeed = round(currentSpeed,3,BigDecimal.ROUND_HALF_UP);
}
currentSpeedField.setText(String.valueOf(currentSpeed) + "km/h");
}
h2.postDelayed(this, 500);
}
};
Timer timer = new Timer();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gps2);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
text3 = (TextView)findViewById(R.id.text3);
Button b = (Button)findViewById(R.id.button);
b.setText("stop");
timer = new Timer();
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Button b = (Button)v;
b.setText("stop");
if(b.getText().equals("stop")){
timer.cancel();
timer.purge();
h2.removeCallbacks(run);
stop();
Button bStop = (Button)findViewById(R.id.button4);
bStop.setEnabled(true);
b.setEnabled(false);
}
}
});
run();
Button b2 = (Button)findViewById(R.id.button4);
b2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getLocation();
h2.postDelayed(run, 0);
starttime = System.currentTimeMillis();
Button bStart = (Button)findViewById(R.id.button4);
bStart.setEnabled(false);
Button b = (Button)findViewById(R.id.button);
b.setEnabled(true);
}
});
}
private void getLocation() {
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0,locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,locationListener);
}
}
public void stop(){
locationManager.removeUpdates(locationListener);
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
locationManager.removeUpdates(locationListener);
super.onPause();
}
private void run(){
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setSpeedRequired(true);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
//Acquire a reference to the system Location Manager
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try{network_enabled=locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
try{gps_enabled=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
// Define a listener that responds to location updates
locationListener = new MyLocationListener();
String Results="Unavailable";
Button bStart = (Button)findViewById(R.id.button4);
bStart.setEnabled(false);
TextView gpsOnOff = (TextView) findViewById(R.id.gpsOnOff);
if(network_enabled)
{
Results="Available";
Button bStartGot = (Button)findViewById(R.id.button4);
bStartGot.setEnabled(true);
}
else if(gps_enabled)
{
Results="Available";
Button bStartGot = (Button)findViewById(R.id.button4);
bStartGot.setEnabled(true);
gpsOnOff.setText(Results);
}
}
//Method to round the doubles to a max of 3 decimal places
public static double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 6371;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2 -lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(Location newLocation)
{
//current speed fo the gps device
spdstarttime = System.currentTimeMillis();
//kmphSpeed = round((currentSpeed*3.6),3,BigDecimal.ROUND_HALF_UP);
//all speeds added together
totalSpeed = totalSpeed + currentSpeed;
totalKmph = totalKmph + kmphSpeed;
//calculates average speedss
//avgSpeed = round(totalSpeed/counter,3,BigDecimal.ROUND_HALF_UP);
//avgKmph = round(totalKmph/counter,3,BigDecimal.ROUND_HALF_UP);
//gets position
lat = round(((double) (newLocation.getLatitude())),9,BigDecimal.ROUND_HALF_UP);
lon = round(((double) (newLocation.getLongitude())),9,BigDecimal.ROUND_HALF_UP);
latituteField = (TextView) findViewById(R.id.lat);
longitudeField = (TextView) findViewById(R.id.lon);
TextView distanceField = (TextView) findViewById(R.id.distance);
LatLon ll = new LatLon(lat, lon);
myList.add(ll);
if(myList.size() > 1){
LatLon ll2 = myList.get(myList.size()-2);
double dist = distFrom( ll2.getLat(), ll2.getLon(), ll.getLat(), ll.getLon());
dist = round(dist,3,BigDecimal.ROUND_HALF_UP);
totalDistance += dist;
totalDistance = round(totalDistance,3,BigDecimal.ROUND_HALF_UP);
distanceField.setText("Distance: " + String.valueOf(totalDistance)+ "km");
Context context = getApplicationContext();
CharSequence text = "Location Changed , Distance Accumulated";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lon));
}
public void onProviderDisabled(String provider)
{
}
public void onProviderEnabled(String provider)
{
}
public void onStatusChanged(String provider, int status, Bundle extras) {
if(status==LocationProvider.OUT_OF_SERVICE)
{
gpsOnOff.setText("OFF");
}
else
{
if(status==LocationProvider.TEMPORARILY_UNAVAILABLE)
{
gpsOnOff.setText("OFF");
}
else
{
if(status==LocationProvider.AVAILABLE)
{
gpsOnOff.setText("ON");
}
}
}
}
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
/*if (imageData != null) {
Intent mIntent = new Intent();
StoreByteImage(mContext, imageData, 50,
"ImageName");
mCamera.startPreview();
setResult(FOTO_MODE, mIntent);
finish();
}*/
}
};
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// TODO Auto-generated method stub
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
List<Camera.Size> list = p.getSupportedPreviewSizes ();
Camera.Size size = list.get(0);
p.setPreviewSize(size.width, size.height);
mCamera.setParameters(p);
//p.setPreviewSize(w, h);
//p.setPreviewSize(300, 200);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
mCamera = Camera.open();
}
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
}
Sometimes the time between two locations is less than one second. Hence dist/time => infinity. (Are you using a float variable for speed calculations?)
Anyway you don't need to do that to calculate speed.
Use:
Location.getSpeed();
Problem solved.
Note: You have to be moving to see a non-zero speed. Also accuracy of this value depends on the GPS chipset used in your phone. Some devices use other sensors to calculate this speed.
i have researched this for hours and the only answers i see point me to
http://developer.android.com/reference/android/location/Location.html
and to use the Method
public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)
i need help understanding how this works in relation to my app. this is how i am retrieving my location.
LocationManager locationManager;
String context = Context.LOCATION_SERVICE;
locationManager = (LocationManager)getSystemService(context);
String provider = LocationManager.GPS_PROVIDER;
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
}
private void updateWithNewLocation(Location location) {
String latLongString;
TextView myLocationText;
myLocationText = (TextView)findViewById(R.id.myLocationText);
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
latLongString = "Lat:" + lat + "\nLong:" + lng;
} else {
latLongString = "No location found";
}
myLocationText.setText("Your Current Position is:\n" +
latLongString);
}
Can someone please help me out a little in understanding how to import my current location into this equation and then having the distance shown in my app?
thank you
public double calcdist()
{
int MILLION = 1000000;
int EARTH_RADIUS_KM = 6371;
double lat1 = la1 / MILLION;// latitude of location 1
double lon1 = lo1 / MILLION; //longitude of location 1
double lat2 = la2 / MILLION; //latitude of location 2
double lon2 = lo2 / MILLION;//longitude of location 2
double lat1Rad = Math.toRadians(lat1);
double lat2Rad = Math.toRadians(lat2);
double deltaLonRad = Math.toRadians(lon2 - lon1);
double dist = Math.acos(Math.sin(lat1Rad) * Math.sin(lat2Rad) + Math.cos(lat1Rad) * Math.cos(lat2Rad)
* Math.cos(deltaLonRad))
* EARTH_RADIUS_KM;
return dist;
}
You can use this code if you already got latitude and longitude of both the locations.
Create a location listener
Method isAccurateForUse is a custom method that simply checks accuracy of a location.
This should work:
public boolean locChanged = false;
public LocationManager locMgr = null;
public Location referenceL = null; // Your reference location
public Location currentKL = null; // Current known location
public Location currentLKL = null; // Current last known location
//Initialise the GPS listener
locMgr = (LocationManager) appCtx.getSystemService(Context.LOCATION_SERVICE);
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, fixGpsListener);
currentLKL = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//Define the GPS listener
LocationListener fixGpsListener = new LocationListener()
{
public void onLocationChanged(Location location)
{
locChanged = true;
if (currentKL == null)
currentKL = location;
else if (isAccurateForUse())
{
currentLKL = currentKL;
currentKL = location;
updateDistance(meterToKilometer(currentKL.distanceTo(referenceL)));
}
}
public void onProviderDisabled(String provider)
{}
public void onProviderEnabled(String provider)
{}
public void onStatusChanged(String provider, int status, Bundle extras)
{}
};
currentKL.distanceTo(referenceL) >> gives the distance in meters
meterToKilometer >> converts meters to kilo-meters
updateDistance >> this method takes a string and updates a text-view that shows distance.
Cheers