Share the post "How To Get User’s Current Location In Android"
When I searched in Google on how to get the current location in Android, I came across the page in Android’s documentation about connecting to Google Play Services and initializing it.
I found out this was really not needed. If I could get the location without having to use this, all the better right?
User MrJre from the StackOverflow forum provided this very handy, useful, clean and non-Google Play Services type of code.
All you need are some broadcasters, receivers and listeners. This is how I did using some of his code. The code will try to get locations through GPS or WI-FI in case one or the other fails.
First off, place this code in a class.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
private Location currentBestLocation; private ServiceLocationListener gpsLocationListener; private ServiceLocationListener networkLocationListener; private ServiceLocationListener passiveLocationListener; private LocationManager locationManager; private Handler handler = new Handler(); public static Device getInstance() { if (device == null) device = new Device(); return device; } public Location fetchLocation(Context context) { locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); try { LocationProvider gpsProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER); LocationProvider networkProvider = locationManager.getProvider(LocationManager.NETWORK_PROVIDER); LocationProvider passiveProvider = locationManager.getProvider(LocationManager.PASSIVE_PROVIDER); if (gpsProvider != null ) { Location lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsProvider.getName()); if (isBetterLocation(lastKnownGPSLocation, currentBestLocation) ) currentBestLocation = lastKnownGPSLocation; } if (networkProvider != null ) { Location lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkProvider.getName()); if (isBetterLocation(lastKnownNetworkLocation, currentBestLocation) ) currentBestLocation = lastKnownNetworkLocation; } if (passiveProvider != null) { Location lastKnownPassiveLocation = locationManager.getLastKnownLocation(passiveProvider.getName()); if (isBetterLocation(lastKnownPassiveLocation, currentBestLocation)) { currentBestLocation = lastKnownPassiveLocation; } } timerRunnable = new TimerRunnable(context); gpsLocationListener = new ServiceLocationListener(); networkLocationListener = new ServiceLocationListener(); passiveLocationListener = new ServiceLocationListener(); if (gpsProvider != null) { locationManager.requestLocationUpdates(gpsProvider.getName(), 0l, 0.0f, gpsLocationListener); } if (networkProvider != null) { locationManager.requestLocationUpdates(networkProvider.getName(), 0l, 0.0f, networkLocationListener); } if (passiveProvider != null) { locationManager.requestLocationUpdates(passiveProvider.getName(), 0l, 0.0f, passiveLocationListener); } if (gpsProvider != null || networkProvider != null || passiveProvider != null) { handler.postDelayed(timerRunnable, 2 * 60 * 1000); } else { handler.post(timerRunnable); } } catch (SecurityException se) { finish(); Logger.getLogger(Web.class.getName()).log(Level.SEVERE, null, se); } return currentBestLocation; } private class ServiceLocationListener implements android.location.LocationListener { @Override public void onLocationChanged(Location newLocation) { synchronized (this) { if (isBetterLocation(newLocation, currentBestLocation)) { currentBestLocation = newLocation; LocationRetrieverBroadcaster.getInstance().fireGotLocation(currentBestLocation); if (currentBestLocation.hasAccuracy() && currentBestLocation.getAccuracy() <= 100) { finish(); } } } } @Override public void onStatusChanged(String s, int i, Bundle bundle) {} @Override public void onProviderEnabled(String s) {} @Override public void onProviderDisabled(String s) {} } private synchronized void finish() { handler.removeCallbacks(timerRunnable); handler.post(timerRunnable); } private static final int TWO_MINUTES = 1000 * 60 * 2; /** Determines whether one Location reading is better than the current Location fix * @param location The new Location that you want to evaluate * @param currentBestLocation The current Location fix, to which you want to compare the new one */ private boolean isBetterLocation(Location location, Location currentBestLocation) { if (currentBestLocation == null) { // A new location is always better than no location return true; } if (location == null) return true; // Check whether the new location fix is newer or older long timeDelta = location.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; boolean isNewer = timeDelta > 0; // If it's been more than two minutes since the current location, use the new location // because the user has likely moved if (isSignificantlyNewer) { return true; // If the new location is more than two minutes older, it must be worse } else if (isSignificantlyOlder) { return false; } // Check whether the new location fix is more or less accurate int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200; // Check if the old and new location are from the same provider boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider()); // Determine location quality using a combination of timeliness and accuracy if (isMoreAccurate) { return true; } else if (isNewer && !isLessAccurate) { return true; } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { return true; } return false; } /** Checks whether two providers are the same */ private boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); } private class TimerRunnable implements Runnable { Context context; TimerRunnable(Context context) { this.context = context; } @Override public void run() { Intent intent = new Intent(context.getPackageName() + ".action.LOCATION_FOUND"); if (currentBestLocation != null) { intent.putExtra(LocationManager.KEY_LOCATION_CHANGED, currentBestLocation); locationManager.removeUpdates(gpsLocationListener); locationManager.removeUpdates(networkLocationListener); locationManager.removeUpdates(passiveLocationListener); } } } private TimerRunnable timerRunnable; |
Then create a broadcast class that will fire events to all listeners when a location has been found.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class LocationRetrieverBroadcaster { private static LocationRetrieverBroadcaster lrb; private List _listeners = new ArrayList<>(); public static LocationRetrieverBroadcaster getInstance() { if (lrb == null) lrb = new LocationRetrieverBroadcaster(); return lrb; } public synchronized void addLocationRetrieverImpl(LocationRetrieverImpl lri) { if (!_listeners.contains(lri)) _listeners.add(lri); } public synchronized void fireGotLocation(Location location) { for (LocationRetrieverImpl _listener : _listeners) { (_listener).gotLocation(location); } } } |
Next, create a listener for use in any Activity that may use location tracking.
|
1 2 3 |
public interface LocationRetrieverImpl { void gotLocation(Location location); } |
All classes are now in place. The next thing to do is to implement the listener to your Activity.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class MyActivity extends Activity implements LocationRetrieverImpl { private Location myLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .... fetchLocation(this); } @Override public void gotLocation(Location location) { myLocation = location; } } |
In the onCreate() method, the fetchLocation() method is called and once a location is found, the broadcaster will fire the gotLocation() method to all listeners and return a Location object.
That’s it! And without having to use Google Play Services to get a location object.