Hi I am trying to fetch location in every 5 seconds and calculate the speed and total distance or the trip but it is not giving exact distance and speed, below is my code please help. TIA
public class LocationUpdater extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private double latitude ;
private double longitude ;
Session session;
Context context;
LocationRequest mLocationRequest;
private static final int MILLISECONDS_PER_SECOND = 1000;
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
private static final long UPDATE_INTERVAL =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 10;
private static final long FASTEST_INTERVAL =
MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
private static final int DESIRED_ACCURACY = 10;
private static final float SMALLEST_DISPLACEMENT = 10f;
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
public LocationUpdater() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = LocationUpdater.this;
session = Session.getSession(context);
buildGoogleApiClient();
mGoogleApiClient.connect();
return START_STICKY;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onConnected(Bundle bundle) {
try{
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(SMALLEST_DISPLACEMENT);
requestLocationUpdate();
}catch (SecurityException ex){
ex.printStackTrace();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mGoogleApiClient.connect();
}
#Override
public void onDestroy() {
super.onDestroy();
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started))
startService(new Intent(LocationUpdater.this,LocationUpdater.class));
}
I am able to get results but updates and not accurate and not smooth at all. Please let me know if it is the correct way of doing it or I should try something else.
Below is my location updater code
private void fetchMyLocation(){
try{
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.wtf("ankit","accuracy "+location.getAccuracy());
if (location.hasAccuracy() && location.getAccuracy() <= DESIRED_ACCURACY) {
// This is your most accurate location.
Log.wtf("ankit","latitude:::"+latitude);
Log.wtf("ankit","longitude:::"+longitude);
session.setCurrentLatitude(""+latitude);
session.setCurrentLongitude(""+longitude);
if(session.getTrip_status().equalsIgnoreCase(Utils.trip_status_started)){
updateDistanceAndSpeed(latitude,longitude);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"");
}
}
}
}
});
}catch (SecurityException ex){
ex.printStackTrace();
}
}
and this is how i calculate speed and distance
// update speed and distance
private void updateDistanceAndSpeed(double latitude,double longitude){
long currentTimeMills = System.currentTimeMillis();
if (session.getLastLatitude().equalsIgnoreCase("")
&& session.getLastLongitude().equalsIgnoreCase("")) {
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
}else {
synchronized (this){
try{
String lat = ""+latitude;
String lng = ""+longitude;
double speed = 0;
if(!lat.equalsIgnoreCase(session.getLastLatitude())
&& !lng.equalsIgnoreCase(session.getLastLongitude())){
Location locationA = new Location("point A");
locationA.setLatitude(latitude);
locationA.setLongitude(longitude);
Location locationB = new Location("point B");
locationB.setLatitude(Double.parseDouble(session.getLastLatitude()));
locationB.setLongitude(Double.parseDouble(session.getLastLongitude()));
if(session.getDistance().equalsIgnoreCase(""))
session.setDistance("0");
Log.wtf("ankit","total distance:"+session.getDistance());
float lastDistance = Float.parseFloat(session.getDistance());
float distance[] = new float[1];
Location.distanceBetween(latitude, longitude,
Double.parseDouble(session.getLastLatitude()),
Double.parseDouble(session.getLastLongitude()), distance);
if(!session.getLastTimeStamp().equalsIgnoreCase("")){
long lastTime = Long.parseLong(session.getLastTimeStamp());
long timeDifference = currentTimeMills - lastTime;
long diffInSec = TimeUnit.MILLISECONDS.toSeconds(timeDifference);
speed = distance[0]/diffInSec;
} else {
speed = 0;
}
speed = speed*3.6;
speed = Utils.round(speed,2);
float roundDistance = Utils.round(distance[0],2);
Log.wtf("ankit","roundDistance"+roundDistance);
float final_distance = lastDistance+roundDistance;
UpdateLocationListner.getInstance().changeState(latitude,longitude,""+speed+"/"+final_distance);
session.setDistance(""+final_distance);
} else {
UpdateLocationListner.getInstance().changeState(latitude,longitude,"0/0");
}
// send speed
}catch (Exception ex){
ex.printStackTrace();
}
}
session.setLastLatitude(""+latitude);
session.setLastLongitude(""+longitude);
session.setLastTimeStamp(""+currentTimeMills);
}
}
You just need to pass latitudes and longitude
public void setLatLng(LatLng origins, LatLng destinations) {
url = "http://maps.googleapis.com/maps/api/distancematrix/json?" +
"origins=" + origins.latitude + "," + origins.longitude + "" +
"&destinations=" + destinations.latitude + "," + destinations.longitude + "" +
"&mode=driving" +
"&language=en-EN" +
"&sensor=false";
}
Handle the response of this URL here give the distance and time between two latitudes and longitude so now you need to calculate speed and for the speed you use
speed = distance / time
Related
In my application there is provision to track how much distance a person is travelled.There is a Service class for getting the current lat and long perodically.Some times the points getting is fine.Othertimes it is not.I started from a point and walked around 500m and came back to the samepoint ,but the distance calculated was 3.5 k.m.
For finding the distance travelled ,I take the difference in between Current and previous location.The values are added with new value and goes on until last.The problem occurs ,Some times the gps point getting is very far from previous one(Some times getting point would be more than 700 meters from previous).
Here is my class.Please enlighten me if i do anything wrong.
public class LocationUpdateService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected static final String TAG = "LocationUpdateService";
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 3; // 10 meters
public static Boolean mRequestingLocationUpdates;
protected String mLastUpdateTime;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected Location mCurrentLocation;
protected Location mLastLocation;
Location currentLocation, previousLocation;
public static boolean isEnded = false;
private Context mContext;
ServiceListener listener;
SharedPreferences sharedPreferences;
double latitude; // latitude
double longitude; // longitude
private String locationProvider; // source of fetched location
LocationManager locationManager;
private IBinder mBinder = new MyBinder();
public LocationUpdateService() {
super();
}
public void setListener(ServiceListener listener) {
this.listener = listener;
}
#Override
public void onCreate() {
super.onCreate();
// Kick off the process of building a GoogleApiClient and requesting the LocationServices
mContext = getApplicationContext();
//locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
sharedPreferences = mContext.getSharedPreferences(WebServiceHelper.PREFS_NAME, 0);
System.out.println("GPS TRACKER STARTED");
deletefile("asap_distance.csv");
}
// #Override
// public IBinder onBind(Intent intent) {
// return null;
// }
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
System.out.println(TAG + "onStartCommand");
Log.d("LOC", "Service init...");
isEnded = false;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
buildGoogleApiClient();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
return Service.START_REDELIVER_INTENT;
}
#Override
public void onConnected(Bundle bundle) {
System.out.println(TAG + "onConnected");
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended==");
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
System.out.println(TAG + "onLocationChanged");
if (location == null) {
getLastKnownLocation();
} else {
mCurrentLocation = location;
if (mCurrentLocation.hasAccuracy() && mCurrentLocation.getAccuracy() > MIN_DISTANCE_CHANGE_FOR_UPDATES)
setLocationData(mCurrentLocation);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
}
//
// updateUI();
// Toast.makeText(this, "Location changed",
// Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient===");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
public void setLocationData(Location location) {
if (location != null) {
currentLocation = location;
double previous_latitude, previous_longitude, current_lat, current_long;
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(mContext, "Current lattitude:" + latitude + "Current Longitude:" + longitude, Toast.LENGTH_LONG).show();
previous_latitude = previousLocation.getLatitude();
previous_longitude = previousLocation.getLongitude();
current_lat = currentLocation.getLatitude();
current_long = currentLocation.getLongitude();
Log.d(TAG, "Previous lattitude:" + previous_latitude + "Previous Longitude:" + previous_longitude);
Log.d(TAG, "Current lattitude:" + current_lat + "Current Longitude:" + current_long);
sharedPreferences.edit().putFloat("lastSavedLat", (float) current_lat).apply();
sharedPreferences.edit().putFloat("lastSavedLon", (float) current_long).apply();
if (previousLocation != null && sharedPreferences.contains("sdeMarkedStartLocLat")) {
if (current_lat == previous_latitude && current_long == previous_longitude) {
Log.d(TAG, "No Displacement");
} else {
Log.d(TAG, "Device Displaced");
// double d = getDistance(previous_latitude, previous_longitude, current_lat, current_long);
double d = ((int) (previousLocation.distanceTo(currentLocation) * 1000)) / 1000;
Log.d(TAG, "Distance calculated in between previousLocation and currentLocation is" + d);
if (d < 5000) {
d = d + sharedPreferences.getFloat("sum_dist", 0);
sharedPreferences.edit().putFloat("sum_dist", (float) d).apply();
// Toast.makeText(mContext, "Total Distance travelled is " + d + "km", Toast.LENGTH_LONG).show();
// Log.d("Distance Calculator ON", "distance" + d);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
writeToFile(sdf.format(new Date()) + "," + currentLocation.getLatitude() + "," + currentLocation.getLongitude() + ", " + d + " meters" + "\n", "asap.csv");
writeToFile(currentLocation.getLatitude() + "," + currentLocation.getLongitude() + "\n", "asap_distance.csv");
}
}
}
if (listener != null)
listener.onLocationReceived(location);
System.out.println("GPS TRACKER " + latitude + " " + longitude);
previousLocation = currentLocation;
} else {
Log.d(TAG, "Location is null");
return;
}
}
public double getDistance(double start_lat, double start_long, double dest_lat, double dest_long) {
double dist = 0;
Location locationA = new Location("point A");
locationA.setLatitude(start_lat);
locationA.setLongitude(start_long);
Location locationB = new Location("point B");
locationB.setLatitude(dest_lat);
locationB.setLongitude(dest_long);
dist = locationA.distanceTo(locationB);
if (dist != 0) {
dist = dist / 1000;
}
return dist;
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
Toast.makeText(this, "Latitude: =" + mCurrentLocation.getLatitude() + " Longitude:=" + mCurrentLocation
.getLongitude(), Toast.LENGTH_SHORT).show();
System.out.println("updateUI");
Log.d(TAG, "Latitude:==" + mCurrentLocation.getLatitude() + "\n Longitude:==" + mCurrentLocation.getLongitude
());
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p/>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p/>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(MIN_DISTANCE_CHANGE_FOR_UPDATES);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.i(TAG, " startLocationUpdates===");
isEnded = true;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
previousLocation = mLastLocation;
if (mLastLocation != null) {
onLocationChanged(mLastLocation);
}
}
/**
* Function to get latitude
*/
public double getLatitude() {
if (mCurrentLocation != null) {
latitude = mCurrentLocation.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (mCurrentLocation != null) {
longitude = mCurrentLocation.getLongitude();
}
// return longitude
return longitude;
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
if (mRequestingLocationUpdates) {
mRequestingLocationUpdates = false;
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
Log.d(TAG, "stopLocationUpdates();==");
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopLocationUpdates();
System.out.println("GPS TRACKER STOPPED");
}
public Location getLastKnownLocation() {
// locationProvider = LocationManager.GPS_PROVIDER;
Location lastKnownLocation = null;
// Or use LocationManager.GPS_PROVIDER
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return lastKnownLocation;
}
try {
//lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
lastKnownLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
return lastKnownLocation;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return lastKnownLocation;
}
#Override
public IBinder onBind(Intent intent) {
Log.v("GPS", "in onBind");
return mBinder;
}
#Override
public void onRebind(Intent intent) {
Log.v("GPS", "in onRebind");
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
Log.v("GPS", "in onUnbind");
return true;
}
public void deletefile(String filename) {
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
//Now delete the file in the above directory and write the contents into it
try {
File file = new File(directory.getAbsolutePath() + "/" + filename);
if (file.exists()) {
boolean deleted = file.delete();
System.out.println("deleted" + deleted);
} else {
System.out.println("File Doesnot Exists");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeToFile(String text, String filename) {
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
if (!directory.exists())
directory.mkdirs();
// String savedText = readFromFile(filename).toString();
//Now create the file in the above directory and write the contents into it
try {
File file = new File(directory.getAbsolutePath() + "/" + filename);
FileOutputStream fOut = new FileOutputStream(file, true);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.append(text);
osw.flush();
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class MyBinder extends Binder {
LocationUpdateService getService() {
return LocationUpdateService.this;
}
}
}
I have written a background service to insert latitude , longitude and some other details into my sqlite database based on the time limit set in my AlarmManager.
I am using GoogleApiClient to calculate latitude and longitude , but i am facing some problems.
Problem
When i am travelling outside without net , the latitude and longitude is not getting updated at regular intervals. The data is getting inserted in my sqlite at regular intervals but latitude and longitude remains same even after half an hour though i am travelling some about 10 kms.
I want the latitude and longitude to change while i am travelling like auto update.
I wanted to know if the FusedLocationApi calculates latitude longitude properly even if i am not connected to the internet , if yes then i need some suggestions to improve the code that i have tried.
Code i have tried.
AlarmManagerService.java
public class AlarmManagerService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "AlarmManagerService";
AlarmReceiver alarmReceiver;
DriverDbHelper driverDbHelper;
Handler handler;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 120000; // 2 mins
private static int FATEST_INTERVAL = 60000; // 1 min
private static int DISPLACEMENT = 10; // 10 meters
public Activity activity;
protected String mLastUpdateTime;
String areaName0, areaName1, areaName2, areaName3, fullAreaName,
sessionMobileNo, sessionDriverName, sessionDID, sessiondriverUserId,
date, time, dateTime, doc, trac_transId;
double latitude, longitude;
PowerManager.WakeLock mWakeLock;
SessionManager session;
ConnectionDetector cd;
Boolean isInternet = false;
String sync_no = "No";
String sync_yes = "Yes";
public AlarmManagerService() {
alarmReceiver = new AlarmReceiver();
driverDbHelper = new DriverDbHelper(this);
cd = new ConnectionDetector(this);
}
public void setActivity(Activity activity) {
this.activity = activity;
}
#Override
public void onCreate() {
super.onCreate();
try {
driverDbHelper.open(AlarmManagerService.this);
} catch (Exception e) {
e.printStackTrace();
}
Log.d("Service created", "Alarm Service Created");
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PowerManager mgr = (PowerManager)
getSystemService(Context.POWER_SERVICE);
if (this.mWakeLock == null) {
this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
}
if (!this.mWakeLock.isHeld()) {
this.mWakeLock.acquire();
}
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
Log.d("Service started", "Alarm Service Started");
handler = new Handler(Looper.myLooper());
handler.post(new Runnable() {
#Override
public void run() {
postDatabaseDetails();
}
});
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Service started", "Alarm Service Destroyed");
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
}
private void displayLocation() {
if (mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
List<Address> addressList = null;
try {
Geocoder gcd = new Geocoder(getBaseContext(),
Locale.getDefault());
addressList = gcd.getFromLocation(mLastLocation.getLatitude(),
mLastLocation.getLongitude(), 1);
if (addressList != null && addressList.size() > 0) {
Address address = addressList.get(0);
areaName0 = address.getLocality(); // city name
areaName1 = address.getSubLocality();
areaName2 = address.getAdminArea();// statename
//areaName3 = address.getFeatureName(); plot no
//areaName3 = address.getCountryCode();// IN
areaName3 = address.getThoroughfare();
fullAreaName = areaName3 + "\n" + areaName1 + "\n" +
areaName0 + "," + areaName2;
} else {
Log.i("Location ", "Location null");
}
} catch (IOException e1) {
Log.e("HomePage", "IO Exception in getFromLocation()");
e1.printStackTrace();
} catch (IllegalArgumentException e2) {
// Error message to post in the log
String errorString = "Illegal arguments " +
Double.toString(mLastLocation.getLatitude()) + " , " +
Double.toString(mLastLocation.getLongitude()) +
" passed to address service";
Log.e("HomePage", errorString);
e2.printStackTrace();
}
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
//mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, activity,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i("Google play services", "Device not supported");
activity.finish();
}
return false;
}
return true;
}
/**
* Starting the location updates
*/
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
#Override
public void onConnected(Bundle bundle) {
// Once connected with google api, get the location
//displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
if (mLastLocation == null) {
mLastLocation =
LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
displayLocation();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.d("Location changed ", "Location changed " + mLastLocation);
Log.d("Last updated time", "Last updated location " + mLastUpdateTime);
// Displaying the new location on UI
displayLocation();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ connectionResult.getErrorCode());
}
public void postDatabaseDetails() {
session = new SessionManager(getApplicationContext());
HashMap<String, String> user = session.getUserDetails();
sessionMobileNo = user.get(SessionManager.KEY_MOBILENO);
sessionDriverName = user.get(SessionManager.KEY_NAME);
sessionDID = user.get(SessionManager.KEY_DEVICEID);
sessiondriverUserId = user.get(SessionManager.KEY_DRIVERUSERID);
Calendar in = Calendar.getInstance();
Date dt = new Date();
in.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss");
date = sdf.format(dt);
time = stf.format(dt);
String timeval = time.toString();
String dateval = date.toString();
dateTime = date.toString() + " " + time.toString();
doc = sessionDID + "" + dateTime;
isInternet = cd.isConnectingToInternet();
if (isInternet) {
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
fullAreaName, dateTime, "DEMO", sync_no, dateval, timeval);
postDriverDetails();
Log.d("GPS", "Service started after 2 mins with internet");
} else {
Log.d("Internet status", "No internet available for service");
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
"NA", dateTime, "DEMO", sync_no, dateval, timeval);
Log.d("GPS", "Service started after 2 mins without internet");
}
}
I am calling this service from the activity HomePage.java , but from where do i have to call the below code , from onStart() or after setContentView(R.layout.home)?
try {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MINUTE, 2);
AlarmManager am = (AlarmManager)
getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(Home_Page.this, AlarmManagerService.class);
PendingIntent pi = PendingIntent.getService(Home_Page.this, 0, i,0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), EXEC_INTERVAL, pi);
} catch (Exception e) {
e.printStackTrace();
}
I hope i can get some suggestions to improve the above service code as i want it to run smoothly in background updating the latitude and longitude at regular intervals.
I am trying to find speed between two locations but found that GPS location is inaccurate. I am at the same location and it keeps on providing different location For e.g It provides me location that's far about 200KM from me.
public class LocationTracker extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, SensorEventListener {
// LogCat tag
private static final String TAG = "LocationTracker";
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private static int UPDATE_INTERVAL = 5000; // 5 sec
private static int FATEST_INTERVAL = 2000; // 2 sec
private static int DISPLACEMENT = 2; // 2 meters
private Context context;
private SharedPreferences sp;
// Location updates intervals in sec
private Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private double latitude, longitude;
private boolean firstLocation = false;
private float speed;
public LocationTracker(Context ctx, boolean firstLocation) {
context = ctx;
sp = context.getSharedPreferences(Utility.SHARED_PREFS, MODE_PRIVATE);
this.firstLocation = firstLocation;
// First we need to check availability of play services
if (checkPlayServices()) {
createLocationRequest();
buildGoogleApiClient();
if (mGoogleApiClient != null)
mGoogleApiClient.connect();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))
Utility.showLog(TAG, "Something went wrong with error code :" + resultCode);
else
Utility.showLog(TAG,
"This device is not supported.");
// stopLocationUpdates();
return false;
}
return true;
}
/**
* Creating location request object
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT); // 10 meters
}
/**
* Starting the location updates
*/
public void startLocationUpdates() {
Utility.showLog(TAG, "Starting Location Updates");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
public void stopLocationUpdates() {
Utility.showLog(TAG, "Stopping Location Updates");
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
}
stopSelf();
}
/**
* Function to get latitude
*/
public double getLatitude() {
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
// return longitude
return longitude;
}
#Override
public void onConnected(Bundle bundle) {
Utility.showLog(TAG, "Google API Connected");
// Once connected with google api, get the location
updateLocation();
startLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
updateLocation();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Method to display the location on UI
*/
private void updateLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
if (firstLocation) {
sp.edit().putString("last_latitude", String.valueOf(mLastLocation.getLatitude())).commit();
sp.edit().putString("last_longitude", String.valueOf(mLastLocation.getLongitude())).commit();
sp.edit().putLong("last_location_time", System.currentTimeMillis()).commit();
firstLocation = false;
Utility.showLog(TAG, "Last Latitude : " + mLastLocation.getLatitude());
Utility.showLog(TAG, "Last Longitude : " + mLastLocation.getLongitude());
}
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
heading = mLastLocation.getBearing();
altitude = mLastLocation.getAltitude();
Utility.showLog(TAG, " Latitude : " + latitude);
Utility.showLog(TAG, " Longitude : " + longitude);
Utility.showLog(TAG, "Heading :" + heading);
Utility.showLog(TAG, "Altitude :" + altitude);
} else
Utility.showLog(TAG, "Couldn't get the location. Make sure location is enabled on the device");
}
#Override
public void onDestroy() {
super.onDestroy();
Utility.showLog(TAG, "Location Tracker Stopped");
}
/**
* Function to get Speed
*/
public double getSpeed() {
double previousLatitude = Double.parseDouble(sp.getString("last_latitude", "0.0"));
double previousLongitude = Double.parseDouble(sp.getString("last_longitude", "0.0"));
Utility.showLog(TAG, "Old Latitude :" + previousLatitude);
Utility.showLog(TAG, "Old Longitude :" + previousLongitude);
Utility.showLog(TAG, "New Latitude :" + latitude);
Utility.showLog(TAG, "New Longitude :" + longitude);
Location sourceLocation = new Location("A");
sourceLocation.setLatitude(previousLatitude);
sourceLocation.setLongitude(previousLongitude);
Location destinationLocation = new Location("B");
destinationLocation.setLatitude(latitude);
destinationLocation.setLongitude(longitude);
double distance = sourceLocation.distanceTo(destinationLocation);
Utility.showLog(TAG, "Distance =" + distance);
float differenceInTime = (float) ((System.currentTimeMillis() - sp.getLong("last_location_time", 0)) / 1000);
Utility.showLog(TAG, "Current Time :" + System.currentTimeMillis());
Utility.showLog(TAG, "Last Time :" + sp.getLong("last_location_time", 0));
Utility.showLog(TAG, "Difference in Time " + differenceInTime);
double mps = distance / differenceInTime;
double kph = (mps * 3600) / 1000;
return kph;
}
}
Please check the accuracy of the location obtained. And if the accuracy value is high(high depends on your decision), then ignore it.
You can get Accuracy using
location.getAccuracy();
At times when you are inside a building, there are chances that your location accuracy will be around 2km sometimes. You can ignore in this case. This accuracy depends on the number of satellites that are providing the result.
Guys I am trying to create an app that logs your locations' coordinates using the location class and the service class, but it doesn't work !
I don't know how to start!!!
here is my sevice file:
public class LocationService extends Service {
private static final long ONE_MIN = 1000 * 60;
private static final long TWO_MIN = ONE_MIN * 2;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final long MEASURE_TIME = 1000 * 30;
private static final long POLLING_FREQ = 1000 * 10;
private static final float MIN_ACCURACY = 25.0f;
private static final float MIN_LAST_READ_ACCURACY = 500.0f;
private static final float MIN_DISTANCE = 10.0f;
private static final int NOTIFICATION_ID = 1;
// Current best location estimate
private Location mBestReading;
WIWDb db;
// Reference to the LocationManager and LocationListener
private LocationManager mLocationManager;
private LocationListener mLocationListener;
private final String TAG = "LocationGetLocationActivity";
private boolean mFirstUpdate = true;
#SuppressLint("NewApi") #Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"here");
db=new WIWDb(this);
// Acquire reference to the LocationManager
if (null == (mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE)))
Toast.makeText(getBaseContext(), "Error", Toast.LENGTH_LONG).show();
// Get best last location measurement
mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
// Display last reading information
if (null != mBestReading) {
updateDisplay(mBestReading);
} else {
Toast.makeText(getBaseContext(),"No Initial Reading Available",Toast.LENGTH_LONG).show();
//mAccuracyView.setText("No Initial Reading Available");
}
mLocationListener = new LocationListener() {
// Called back when location changes
public void onLocationChanged(Location location) {
// Determine whether new location is better than current best
// estimate
if (null == mBestReading
|| location.getAccuracy() < mBestReading.getAccuracy()) {
// Update best estimate
mBestReading = location;
// Update display
updateDisplay(location);
if (mBestReading.getAccuracy() < MIN_ACCURACY)
mLocationManager.removeUpdates(mLocationListener);
}
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// NA
}
public void onProviderEnabled(String provider) {
// NA
}
public void onProviderDisabled(String provider) {
// NA
}
};
// Create a notification area notification so the user
// can get back to the MusicServiceClient
final Intent notificationIntent = new Intent(getApplicationContext(),
MainActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
final Notification notification = new Notification.Builder(
getApplicationContext())
.setSmallIcon(android.R.drawable.ic_menu_compass)
.setOngoing(true).setContentTitle("Location tracking...")
.setContentText("Back to WIW")
.setContentIntent(pendingIntent).build();
// Put this Service in a foreground state, so it won't
// readily be killed by the system
startForeground(NOTIFICATION_ID, notification);
}
private Location bestLastKnownLocation(float minAccuracy, long maxAge) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestAge = Long.MIN_VALUE;
List<String> matchingProviders = mLocationManager.getAllProviders();
for (String provider : matchingProviders) {
Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();
if (accuracy < bestAccuracy) {
bestResult = location;
bestAccuracy = accuracy;
bestAge = time;
}
}
}
// Return best reading or null
if (bestAccuracy > minAccuracy
|| (System.currentTimeMillis() - bestAge) > maxAge) {
return null;
} else {
return bestResult;
}
}
#SuppressWarnings("deprecation")
private void updateDisplay(Location location) {
StringBuilder sb=new StringBuilder();
sb.append("Accuracy:" + location.getAccuracy());
//mAccuracyView.setText("Accuracy:" + location.getAccuracy());
sb.append("Time:"+ new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
//mTimeView.setText("Time:"+ new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
sb.append("Longitude:" + location.getLongitude());
//mLatView.setText("Longitude:" + location.getLongitude());
sb.append("Latitude:" + location.getLatitude());
//mLngView.setText("Latitude:" + location.getLatitude());
//db.insertCordsToDb(String.valueOf(location.getLongitude())+","+String.valueOf( location.getLatitude()),String.valueOf(new Date().getDate()) ,String.valueOf(location.getTime()));
db.insertCordsToDb(String.valueOf(location.getLongitude())+","+String.valueOf(lo cation.getLatitude()),new SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()).format(new Date(location.getTime())) ,new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(location.getTime())));
}
protected void onResume() {
// Determine whether initial reading is
// "good enough". If not, register for
// further location updates
if (null == mBestReading
|| mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
|| mBestReading.getTime() < System.currentTimeMillis()
- TWO_MIN) {
// Register for network location updates
if (null != mLocationManager
.getProvider(LocationManager.NETWORK_PROVIDER)) {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, POLLING_FREQ,
MIN_DISTANCE, mLocationListener);
}
// Register for GPS location updates
if (null != mLocationManager
.getProvider(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, POLLING_FREQ,
MIN_DISTANCE, mLocationListener);
}
// Schedule a runnable to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
#Override
public void run() {
Log.i(TAG, "location updates cancelled");
mLocationManager.removeUpdates(mLocationListener);
}
}, MEASURE_TIME, TimeUnit.MILLISECONDS);
}
}
// Unregister location listeners
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
please guide to finish this application
I am currently trying the LocationClient provided by Google Services. When I am next to a building I receive frequent location updates but in the middle of a road they are less frequent and less accurate. In the country side, no updates at all. I wondered if the Google Location Services uses the GPS so I disabled all location providers but the GPS in the phone's settings and I instantly stopped receiving any update. Obviously my LocationClient does not receive any update using GPS data.
Am I missing something? Is there anything I have to set for the LocationClient or do I have to use the standard LocationManager.GPS_PROVIDER?
I am trying to build an app for running and I need accurate location data. Any advice would be much appreciated ;-)!
Here is the implementation that I use:
public class CustomLocationProvider implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener, android.location.LocationListener {
private static final float DATA_UPDATE_DISTANCE = 100.0f;
private static final long ONE_MIN = 1000 * 60;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final int UPDATE_TIME = 5000;
private static final int FASTEST_INTERVAL = 16;
private static final int ACCURACY_THRESHOLD = 30;
private Context mContext;
private LocationClient mLocationClient;
private Location mPreviousLocation;
private float mTotalDistance;
private float mDistanceSinceLastUpdate = 0.0f;
private WeakReference<Activity> mDelegate;
public interface LocationProviderDelegate {
void locationUpdated(Location location);
}
// These settings are the same as the settings for the map. They will in fact give you updates
// at the maximal rates currently possible.
private static final LocationRequest REQUEST = LocationRequest.create()
.setInterval(UPDATE_TIME) // 5 seconds
.setFastestInterval(FASTEST_INTERVAL) // 16ms = 60fps
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
public CustomLocationProvider (Context context, Activity delegate) {
if(context != null) {
mContext = context;
mDelegate = new WeakReference<Activity>(delegate);
}
}
public void enableTracking(boolean enable) {
if(enable) {
setUpLocationClientIfNeeded();
mLocationClient.connect();
} else {
if(mLocationClient != null) {
mLocationClient.disconnect();
}
}
}
private void setUpLocationClientIfNeeded() {
if (mLocationClient == null) {
mLocationClient = new LocationClient(
mContext,
this, // ConnectionCallbacks
this); // OnConnectionFailedListener
}
}
#Override
public void onLocationChanged(Location location) {
if(mPreviousLocation != null
&& location.getTime() > mPreviousLocation.getTime()
&& location.getAccuracy() < ACCURACY_THRESHOLD)
{
float distanceIncrement = mPreviousLocation.distanceTo(location);
mDistanceSinceLastUpdate += distanceIncrement;
mTotalDistance += distanceIncrement;
if(mDistanceSinceLastUpdate >= DATA_UPDATE_DISTANCE)
{
mDistanceSinceLastUpdate = 0.0f;
requestDataUpdate(location);
}
updateLocation(location);
} else if( mPreviousLocation == null){
requestDataUpdate(location);
updateLocation(location);
}
}
private void updateLocation(Location location) {
try {
((LocationProviderDelegate) mDelegate.get()).locationUpdated(location);
} catch (Exception e) {
Logger.logError("Cannot cast as a LocationProviderDelegate");
}
mPreviousLocation = location;
}
/**
* Callback called when connected to GCore. Implementation of {#link ConnectionCallbacks}.
*/
#Override
public void onConnected(Bundle connectionHint) {
mLocationClient.requestLocationUpdates(
REQUEST,
this); // LocationListener
Location location = mLocationClient.getLastLocation();
if (location != null) {
if (age(location) < FIVE_MIN) {
mPreviousLocation = location;
requestDataUpdate(location);
}
}
}
/**
* Callback called when disconnected from GCore. Implementation of {#link ConnectionCallbacks}.
*/
#Override
public void onDisconnected() {
// Do nothing
}
/**
* Implementation of {#link OnConnectionFailedListener}.
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Logger.postMessageToTheUser("Connection failed", mDelegate.get());
}
public void Reset(){
mTotalDistance = 0;
}
public float TotalDistance() {
return mTotalDistance;
}
public void requestDataUpdate(Location location)
{
double latitude = location.getLatitude();
double longitude = location.getLongitude();
double offset = 0.002;
LatLngBounds bounds = LatLngBounds.builder()
.include(new LatLng(latitude - offset, longitude - offset))
.include(new LatLng(latitude + offset, longitude + offset))
.build();
updateData();
}
private long age(Location location) {
return System.currentTimeMillis() - location.getTime();
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
String newStatus = "";
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
newStatus = "OUT_OF_SERVICE";
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
newStatus = "TEMPORARILY_UNAVAILABLE";
break;
case LocationProvider.AVAILABLE:
newStatus = "AVAILABLE";
break;
}
String msg = provider + ": " + newStatus;
Logger.postMessageToTheUser(msg, mDelegate.get());
}
}
The LocationClient provided by Google Play Services, uses a fused location provider. This means that it will use the best provider available along with the phone's sensors to give you the most accurate location it can.
It seems from your code that you are disregarding updates if the location accuracy is less than 30m. Remember that even though GPS is the most accurate way to get a location you cannot control how accurate that location is.
Also, calling LocationRequest.create() will create the request with default parameters. I would think you want to call create() last (after setInterval(),etc ) instead of first.