/* * This file is part of Find Your Friend. * * Find Your Friend is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Find Your Friend is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Find Your Friend. If not, see <http://www.gnu.org/licenses/>. */ package com.sgu.findyourfriend.utils; import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.content.SharedPreferences; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.maps.model.LatLng; import com.sgu.findyourfriend.mgr.MyLocationChangeListener; import com.sgu.findyourfriend.mgr.MyProfileManager; import com.sgu.findyourfriend.mgr.SettingManager; import com.sgu.findyourfriend.net.PostData; public class GpsPosition { public static final String TAG = "GPS POSITION"; private Context context; private Location lastLocation = null; private Timer gpsTimer = new Timer(); private long lastprovidertimestamp = 0; private LocationManager myLocationManager = null; private MyLocationChangeListener myLocationListener; private boolean isUploadMyPosition; private int checkInterval; private int minDistance; public GpsPosition(Context conext, MyLocationChangeListener myLocationListener) { this.context = conext; this.myLocationListener = myLocationListener; lastprovidertimestamp = 0; isUploadMyPosition = false; } public void startRecording() { gpsTimer.cancel(); gpsTimer = new Timer(); setCheckInterval(SettingManager.getInstance() .getIntervalUpdatePosition()); setMinDistance(SettingManager.getInstance().getAccuracyUpdatePosition()); // receive updates LocationManager locationManager = (LocationManager) context .getSystemService(Context.LOCATION_SERVICE); // get now Location mLocation = getBestLocation(); if (null != mLocation) { updateToServer(mLocation.getLatitude(), mLocation.getLongitude()); myLocationListener.onMyLocationChanged(mLocation); } for (String s : locationManager.getAllProviders()) { locationManager.requestLocationUpdates(s, getCheckInterval(), getMinDistance(), new LocationListener() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } @Override public void onLocationChanged(Location location) { // if this is a gps location, we can use it if (location.getProvider().equals( LocationManager.GPS_PROVIDER)) { Toast.makeText(context, "Updating location", Toast.LENGTH_SHORT).show(); doLocationUpdate(location, true); myLocationListener .onMyLocationChanged(location); } } }); } // start the gps receiver thread gpsTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { Log.i(TAG, "check!"); Location location = getBestLocation(); doLocationUpdate(location, false); } }, 0, getCheckInterval()); } public void setUploadMyPosition(boolean upload) { isUploadMyPosition = upload; } public void doLocationUpdate(Location l, boolean force) { // long minDistance = getMinDistanceFromPrefs(); // Log.d(TAG, "update received:" + l); if (l == null) { // Log.d(TAG, "Empty location"); if (force) Toast.makeText(context, "Current location not available", Toast.LENGTH_SHORT).show(); return; } if (getLastLocation() != null) { float distance = l.distanceTo(getLastLocation()); // Log.d(TAG, "Distance to last: " + distance); if (l.distanceTo(getLastLocation()) < getMinDistance() && !force) { // Log.d(TAG, "Position didn't change"); return; } if (l.getAccuracy() >= getLastLocation().getAccuracy() && l.distanceTo(getLastLocation()) < l.getAccuracy() && !force) { // Log.d(TAG, "Accuracy got worse and we are still " // + "within the accuracy range.. Not updating"); return; } if (l.getTime() <= lastprovidertimestamp && !force) { // Log.d(TAG, "Timestamp not never than last"); return; } } // upload/store your location here setLastLocation(l); Log.i(TAG, "update server here!"); if (isUploadMyPosition && getLastLocation() != null) { double lat = getLastLocation().getLatitude(); double lng = getLastLocation().getLongitude(); // ---------------- send to server ------------------ // updateToServer(lat, lng); // ------------------ end --------------------------- } } private void updateToServer(double lat, double lng) { Log.i("Gps", "call update to server"); if (null == MyProfileManager.getInstance().getMyPosition() || MyProfileManager.getInstance().getMyPosition().latitude != lat || MyProfileManager.getInstance().getMyPosition().latitude != lat) { Log.i("Gps", "call update to server ok"); PostData.historyCreate(context, MyProfileManager.getInstance() .getMyID(), new LatLng(lat, lng)); } } private Location getBestLocation() { Location gpslocation = getLocationByProvider(LocationManager.GPS_PROVIDER); Location networkLocation = getLocationByProvider(LocationManager.NETWORK_PROVIDER); // if we have only one location available, the choice is easy if (gpslocation == null) { // Log.d(TAG, "No GPS Location available."); return networkLocation; } if (networkLocation == null) { // Log.d(TAG, "No Network Location available"); return gpslocation; } // a location update is considered 'old' if its older than the // configured // update interval. this means, we didn't get a // update from this provider since the last check long old = System.currentTimeMillis() - getCheckInterval(); boolean gpsIsOld = (gpslocation.getTime() < old); boolean networkIsOld = (networkLocation.getTime() < old); // gps is current and available, gps is better than network if (!gpsIsOld) { // Log.d(TAG, "Returning current GPS Location"); return gpslocation; } // gps is old, we can't trust it. use network location if (!networkIsOld) { // Log.d(TAG, "GPS is old, Network is current, returning network"); return networkLocation; } // both are old return the newer of those two if (gpslocation.getTime() > networkLocation.getTime()) { // Log.d(TAG, "Both are old, returning gps(newer)"); return gpslocation; } else { // Log.d(TAG, "Both are old, returning network(newer)"); return networkLocation; } } private Location getLocationByProvider(String provider) { Location location = null; if (!isProviderSupported(provider)) { return null; } LocationManager locationManager = (LocationManager) context .getSystemService(Context.LOCATION_SERVICE); try { if (locationManager.isProviderEnabled(provider)) { location = locationManager.getLastKnownLocation(provider); } } catch (IllegalArgumentException e) { // Log.d(TAG, "Cannot acces Provider " + provider); } return location; } public boolean isProviderSupported(String in_Provider) { LocationManager locationManager = getLocationManager(); int lv_N; List<String> lv_List; try { lv_List = locationManager.getAllProviders(); } catch (Throwable e) { return false; } // scan the list for the specified provider for (lv_N = 0; lv_N < lv_List.size(); ++lv_N) if (in_Provider.equals((String) lv_List.get(lv_N))) return true; // not supported return false; } public LocationManager getLocationManager() { if (myLocationManager == null) { myLocationManager = (LocationManager) context .getSystemService(Context.LOCATION_SERVICE); } return myLocationManager; } public Location getLastLocation() { return lastLocation; } public void setLastLocation(Location lastLocation) { this.lastLocation = lastLocation; } public long getCheckInterval() { return checkInterval; } public void setCheckInterval(int checkInterval) { this.checkInterval = checkInterval; } public int getMinDistance() { return minDistance; } public void setMinDistance(int minDistance) { this.minDistance = minDistance; } }