1package com.xtremelabs.robolectric.shadows; 2 3import android.app.PendingIntent; 4import android.content.Context; 5import android.content.Intent; 6import android.location.Criteria; 7import android.location.GpsStatus.Listener; 8import android.location.Location; 9import android.location.LocationListener; 10import android.location.LocationManager; 11import android.os.Bundle; 12import com.xtremelabs.robolectric.Robolectric; 13import com.xtremelabs.robolectric.WithTestDefaultsRunner; 14import junit.framework.Assert; 15import org.junit.Before; 16import org.junit.Test; 17import org.junit.runner.RunWith; 18 19import java.util.*; 20 21import static android.location.LocationManager.GPS_PROVIDER; 22import static android.location.LocationManager.NETWORK_PROVIDER; 23import static com.xtremelabs.robolectric.Robolectric.shadowOf; 24import static junit.framework.Assert.*; 25import static org.hamcrest.core.IsEqual.equalTo; 26import static org.junit.Assert.assertSame; 27import static org.junit.Assert.assertThat; 28 29@RunWith(WithTestDefaultsRunner.class) 30public class LocationManagerTest { 31 private LocationManager locationManager; 32 private ShadowLocationManager shadowLocationManager; 33 34 @Before 35 public void setUp() { 36 locationManager = (LocationManager) Robolectric.application.getSystemService(Context.LOCATION_SERVICE); 37 shadowLocationManager = shadowOf(locationManager); 38 } 39 40 @Test 41 public void shouldReturnNoProviderEnabledByDefault() { 42 Boolean enabled = locationManager.isProviderEnabled(GPS_PROVIDER); 43 assertFalse(enabled); 44 enabled = locationManager.isProviderEnabled(NETWORK_PROVIDER); 45 assertFalse(enabled); 46 enabled = locationManager.isProviderEnabled("RANDOM_PROVIDER"); 47 assertFalse(enabled); 48 } 49 50 @Test 51 public void shouldDisableProvider() { 52 // No provider is enabled by default, so it must be manually enabled 53 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 54 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, false); 55 assertFalse(locationManager.isProviderEnabled(GPS_PROVIDER)); 56 } 57 58 @Test 59 public void shouldHaveListenerOnceAdded() { 60 Listener listener = addGpsListenerToLocationManager(); 61 assertTrue(shadowLocationManager.hasGpsStatusListener(listener)); 62 } 63 64 @Test 65 public void shouldNotHaveListenerOnceRemoved() { 66 Listener listener = addGpsListenerToLocationManager(); 67 68 locationManager.removeGpsStatusListener(listener); 69 70 assertFalse(shadowLocationManager.hasGpsStatusListener(listener)); 71 } 72 73 @Test 74 public void shouldReturnEnabledProviders() throws Exception { 75 shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, false); 76 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, false); 77 shadowLocationManager.setProviderEnabled(LocationManager.PASSIVE_PROVIDER, false); 78 79 assertTrue(locationManager.getProviders(true).isEmpty()); 80 assertThat(locationManager.getProviders(false).size(), equalTo(3)); 81 82 shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, true); 83 84 List<String> providers = locationManager.getProviders(true); 85 assertTrue(providers.contains(NETWORK_PROVIDER)); 86 assertThat(providers.size(), equalTo(1)); 87 88 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 89 providers = locationManager.getProviders(true); 90 assertTrue(providers.contains(NETWORK_PROVIDER)); 91 assertTrue(providers.contains(GPS_PROVIDER)); 92 assertThat(providers.size(), equalTo(2)); 93 94 shadowLocationManager.setProviderEnabled(LocationManager.PASSIVE_PROVIDER, true); 95 providers = locationManager.getProviders(true); 96 assertTrue(providers.contains(NETWORK_PROVIDER)); 97 assertTrue(providers.contains(GPS_PROVIDER)); 98 assertTrue(providers.contains(LocationManager.PASSIVE_PROVIDER)); 99 assertThat(providers.size(), equalTo(3)); 100 } 101 102 @Test 103 public void shouldReturnAllProviders() throws Exception { 104 assertThat(locationManager.getAllProviders().size(), equalTo(3)); 105 106 shadowLocationManager.setProviderEnabled("MY_PROVIDER", false); 107 assertThat(locationManager.getAllProviders().size(), equalTo(4)); 108 } 109 110 @Test 111 public void shouldReturnLastKnownLocationForAProvider() throws Exception { 112 assertNull(locationManager.getLastKnownLocation(NETWORK_PROVIDER)); 113 114 Location networkLocation = new Location(NETWORK_PROVIDER); 115 Location gpsLocation = new Location(GPS_PROVIDER); 116 117 shadowLocationManager.setLastKnownLocation(NETWORK_PROVIDER, networkLocation); 118 shadowLocationManager.setLastKnownLocation(GPS_PROVIDER, gpsLocation); 119 120 assertSame(locationManager.getLastKnownLocation(NETWORK_PROVIDER), networkLocation); 121 assertSame(locationManager.getLastKnownLocation(GPS_PROVIDER), gpsLocation); 122 } 123 124 @Test 125 public void shouldStoreRequestLocationUpdateListeners() throws Exception { 126 TestLocationListener listener = new TestLocationListener(); 127 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 2.0f, listener); 128 assertSame(shadowLocationManager.getRequestLocationUpdateListeners().get(0), listener); 129 } 130 131 @Test 132 public void shouldKeepTrackOfWhichProvidersAListenerIsBoundTo_withoutDuplicates_inAnyOrder() throws Exception { 133 TestLocationListener listener1 = new TestLocationListener(); 134 TestLocationListener listener2 = new TestLocationListener(); 135 136 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, listener1); 137 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 1, listener1); 138 139 Set<String> listOfExpectedProvidersForListener1 = new HashSet<String>(); 140 listOfExpectedProvidersForListener1.add(LocationManager.NETWORK_PROVIDER); 141 listOfExpectedProvidersForListener1.add(LocationManager.GPS_PROVIDER); 142 143 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, listener2); 144 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, listener2); 145 146 Set<String> listOfExpectedProvidersForListener2 = new HashSet<String>(); 147 listOfExpectedProvidersForListener2.add(LocationManager.NETWORK_PROVIDER); 148 149 assertEquals(listOfExpectedProvidersForListener1, new HashSet<String>(shadowLocationManager.getProvidersForListener(listener1))); 150 assertEquals(listOfExpectedProvidersForListener2, new HashSet<String>(shadowLocationManager.getProvidersForListener(listener2))); 151 152 locationManager.removeUpdates(listener1); 153 assertEquals(0, shadowLocationManager.getProvidersForListener(listener1).size()); 154 } 155 156 @Test 157 public void shouldRemoveLocationListeners() throws Exception { 158 TestLocationListener listener = new TestLocationListener(); 159 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 2.0f, listener); 160 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 2.0f, listener); 161 162 TestLocationListener otherListener = new TestLocationListener(); 163 locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 2.0f, otherListener); 164 165 locationManager.removeUpdates(listener); 166 167 List<LocationListener> expected = new ArrayList<LocationListener>(); 168 expected.add(otherListener); 169 assertThat(shadowLocationManager.getRequestLocationUpdateListeners(), equalTo(expected)); 170 } 171 172 @Test 173 public void shouldRemovePendingIntentsWhenRequestingLocationUpdatesUsingCriteria() throws Exception { 174 Intent someIntent = new Intent("some_action"); 175 PendingIntent someLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric 176 .getShadowApplication().getApplicationContext(), 0, someIntent, 177 PendingIntent.FLAG_UPDATE_CURRENT); 178 Intent someOtherIntent = new Intent("some_other_action"); 179 PendingIntent someOtherLocationListenerPendingIntent = PendingIntent.getBroadcast( 180 Robolectric.getShadowApplication().getApplicationContext(), 0, someOtherIntent, 181 PendingIntent.FLAG_UPDATE_CURRENT); 182 183 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 184 shadowLocationManager.setBestProvider(LocationManager.GPS_PROVIDER, true); 185 Criteria criteria = new Criteria(); 186 criteria.setAccuracy(Criteria.ACCURACY_FINE); 187 188 locationManager.requestLocationUpdates(0, 0, criteria, someLocationListenerPendingIntent); 189 locationManager.requestLocationUpdates(0, 0, criteria, someOtherLocationListenerPendingIntent); 190 191 locationManager.removeUpdates(someLocationListenerPendingIntent); 192 193 Map<PendingIntent, Criteria> expectedCriteria = new HashMap<PendingIntent, Criteria>(); 194 expectedCriteria.put(someOtherLocationListenerPendingIntent, criteria); 195 assertThat(shadowLocationManager.getRequestLocationUdpateCriteriaPendingIntents(), equalTo(expectedCriteria)); 196 } 197 198 @Test 199 public void shouldNotSetBestEnabledProviderIfProviderIsDisabled() throws Exception { 200 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 201 assertTrue(shadowLocationManager.setBestProvider(LocationManager.GPS_PROVIDER, true)); 202 } 203 204 @Test 205 public void shouldNotSetBestDisabledProviderIfProviderIsEnabled() throws Exception { 206 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 207 assertFalse(shadowLocationManager.setBestProvider(LocationManager.GPS_PROVIDER, false)); 208 } 209 210 @Test 211 public void shouldRemovePendingIntentsWhenRequestingLocationUpdatesUsingLocationListeners() throws Exception { 212 Intent someIntent = new Intent("some_action"); 213 PendingIntent someLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric.getShadowApplication().getApplicationContext(), 0, 214 someIntent, PendingIntent.FLAG_UPDATE_CURRENT); 215 Intent someOtherIntent = new Intent("some_other_action"); 216 PendingIntent someOtherLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric.getShadowApplication().getApplicationContext(), 217 0, someOtherIntent, PendingIntent.FLAG_UPDATE_CURRENT); 218 219 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 220 shadowLocationManager.setBestProvider(LocationManager.GPS_PROVIDER, true); 221 shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, true); 222 223 locationManager.requestLocationUpdates(GPS_PROVIDER, 0, 0, someLocationListenerPendingIntent); 224 locationManager.requestLocationUpdates(NETWORK_PROVIDER, 0, 0, someOtherLocationListenerPendingIntent); 225 226 locationManager.removeUpdates(someLocationListenerPendingIntent); 227 228 Map<PendingIntent, String> expectedProviders = new HashMap<PendingIntent, String>(); 229 expectedProviders.put(someOtherLocationListenerPendingIntent, NETWORK_PROVIDER); 230 assertThat(shadowLocationManager.getRequestLocationUdpateProviderPendingIntents(), 231 equalTo(expectedProviders)); 232 } 233 234 @Test 235 public void shouldStoreBestProviderCriteriaAndEnabledOnlyFlag() throws Exception { 236 Criteria criteria = new Criteria(); 237 assertNull(locationManager.getBestProvider(criteria, true)); 238 assertSame(criteria, shadowLocationManager.getLastBestProviderCriteria()); 239 assertTrue(shadowLocationManager.getLastBestProviderEnabledOnly()); 240 } 241 242 @Test 243 public void shouldReturnNullIfBestProviderNotExplicitlySet() throws Exception { 244 Criteria criteria = new Criteria(); 245 assertNull(locationManager.getBestProvider(null, false)); 246 assertNull(locationManager.getBestProvider(null, true)); 247 assertNull(locationManager.getBestProvider(criteria, false)); 248 assertNull(locationManager.getBestProvider(criteria, true)); 249 } 250 251 @Test 252 public void shouldThrowExceptionWhenRequestingLocationUpdatesWithANullIntent() throws Exception { 253 try { 254 shadowLocationManager.requestLocationUpdates(0, 0, new Criteria(), null); 255 Assert.fail("When requesting location updates the intent must not be null!"); 256 } catch (Exception e) { 257 // No worries, everything is fine... 258 } 259 } 260 261 @Test 262 public void shouldThrowExceptionWhenRequestingLocationUpdatesAndNoProviderIsFound() throws Exception { 263 Intent someIntent = new Intent("some_action"); 264 PendingIntent someLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric.getShadowApplication().getApplicationContext(), 0, 265 someIntent, PendingIntent.FLAG_UPDATE_CURRENT); 266 Criteria criteria = new Criteria(); 267 criteria.setAccuracy(Criteria.ACCURACY_FINE); 268 try { 269 shadowLocationManager.requestLocationUpdates(0, 0, criteria, someLocationListenerPendingIntent); 270 Assert.fail("When requesting location updates the intent must not be null!"); 271 } catch (Exception e) { 272 // No worries, everything is fine... 273 } 274 } 275 276 @Test 277 public void shouldThrowExceptionIfTheBestProviderIsUnknown() throws Exception { 278 Criteria criteria = new Criteria(); 279 criteria.setAccuracy(Criteria.ACCURACY_FINE); 280 try { 281 shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER", true); 282 Assert.fail("The best provider is unknown!"); 283 } catch (Exception e) { 284 // No worries, everything is fine... 285 } 286 } 287 288 @Test 289 public void shouldReturnBestCustomProviderUsingCriteria() throws Exception { 290 Criteria criteria = new Criteria(); 291 Criteria customProviderCriteria = new Criteria(); 292 293 // Manually set best provider should be returned 294 ArrayList<Criteria> criteriaList = new ArrayList<Criteria>(); 295 customProviderCriteria.setAccuracy(Criteria.ACCURACY_COARSE); 296 criteriaList.add(customProviderCriteria); 297 shadowLocationManager.setProviderEnabled("BEST_ENABLED_PROVIDER_WITH_CRITERIA", true, criteriaList); 298 assertTrue(shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER_WITH_CRITERIA", true)); 299 criteria.setAccuracy(Criteria.ACCURACY_COARSE); 300 criteria.setPowerRequirement(Criteria.NO_REQUIREMENT); 301 assertThat("BEST_ENABLED_PROVIDER_WITH_CRITERIA", equalTo(locationManager.getBestProvider(criteria, true))); 302 assertTrue(shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER_WITH_CRITERIA", true)); 303 assertThat("BEST_ENABLED_PROVIDER_WITH_CRITERIA", equalTo(locationManager.getBestProvider(criteria, false))); 304 assertThat("BEST_ENABLED_PROVIDER_WITH_CRITERIA", equalTo(locationManager.getBestProvider(criteria, true))); 305 } 306 307 @Test 308 public void shouldReturnBestProviderUsingCriteria() { 309 Criteria criteria = new Criteria(); 310 311 shadowLocationManager.setProviderEnabled(LocationManager.GPS_PROVIDER, false); 312 criteria.setAccuracy(Criteria.ACCURACY_FINE); 313 assertThat(LocationManager.GPS_PROVIDER, equalTo(locationManager.getBestProvider(criteria, false))); 314 315 shadowLocationManager.setProviderEnabled(LocationManager.NETWORK_PROVIDER, false); 316 criteria.setAccuracy(Criteria.ACCURACY_COARSE); 317 assertThat(LocationManager.NETWORK_PROVIDER, equalTo(locationManager.getBestProvider(criteria, false))); 318 319 criteria.setPowerRequirement(Criteria.POWER_LOW); 320 criteria.setAccuracy(Criteria.ACCURACY_FINE); 321 assertThat(LocationManager.NETWORK_PROVIDER, equalTo(locationManager.getBestProvider(criteria, false))); 322 } 323 324 @Test 325 public void shouldReturnBestDisabledProvider() throws Exception { 326 shadowLocationManager.setProviderEnabled("BEST_DISABLED_PROVIDER", false); 327 shadowLocationManager.setBestProvider("BEST_DISABLED_PROVIDER", false); 328 shadowLocationManager.setProviderEnabled("BEST_ENABLED_PROVIDER", true); 329 shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER", true); 330 331 assertTrue(shadowLocationManager.setBestProvider("BEST_DISABLED_PROVIDER", false)); 332 assertThat("BEST_DISABLED_PROVIDER", equalTo(locationManager.getBestProvider(null, false))); 333 assertThat("BEST_ENABLED_PROVIDER", equalTo(locationManager.getBestProvider(null, true))); 334 } 335 336 @Test 337 public void shouldReturnBestEnabledProvider() throws Exception { 338 shadowLocationManager.setProviderEnabled("BEST_ENABLED_PROVIDER", true); 339 340 assertTrue(shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER", true)); 341 assertFalse(shadowLocationManager.setBestProvider("BEST_ENABLED_PROVIDER", false)); 342 assertThat("BEST_ENABLED_PROVIDER", equalTo(locationManager.getBestProvider(null, true))); 343 assertNull(locationManager.getBestProvider(null, false)); 344 } 345 346 @Test 347 public void shouldNotifyAllListenersIfProviderStateChanges() { 348 TestLocationListener listener = new TestLocationListener(); 349 locationManager.requestLocationUpdates("TEST_PROVIDER", 0, 0, listener); 350 shadowLocationManager.setProviderEnabled("TEST_PROVIDER", true); 351 assertTrue(listener.providerEnabled); 352 shadowLocationManager.setProviderEnabled("TEST_PROVIDER", false); 353 assertFalse(listener.providerEnabled); 354 } 355 356 @Test 357 public void shouldRegisterLocationUpdatesWhenProviderGiven() throws Exception { 358 shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); 359 shadowLocationManager.setBestProvider(LocationManager.GPS_PROVIDER, true); 360 361 Intent someIntent = new Intent("some_action"); 362 PendingIntent someLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric.getShadowApplication().getApplicationContext(), 0, 363 someIntent, PendingIntent.FLAG_UPDATE_CURRENT); 364 locationManager.requestLocationUpdates(GPS_PROVIDER, 0, 0, someLocationListenerPendingIntent); 365 366 assertThat(shadowLocationManager.getRequestLocationUdpateProviderPendingIntents().get(someLocationListenerPendingIntent), 367 equalTo(GPS_PROVIDER)); 368 } 369 370 @Test 371 public void shouldRegisterLocationUpdatesWhenCriteriaGiven() throws Exception { 372 shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, true); 373 shadowLocationManager.setBestProvider(LocationManager.NETWORK_PROVIDER, true); 374 Criteria criteria = new Criteria(); 375 criteria.setAccuracy(Criteria.ACCURACY_COARSE); 376 377 Intent someIntent = new Intent("some_action"); 378 PendingIntent someLocationListenerPendingIntent = PendingIntent.getBroadcast(Robolectric.getShadowApplication().getApplicationContext(), 0, 379 someIntent, PendingIntent.FLAG_UPDATE_CURRENT); 380 Criteria someCriteria = new Criteria(); 381 someCriteria.setAccuracy(Criteria.ACCURACY_COARSE); 382 locationManager.requestLocationUpdates(0, 0, someCriteria, someLocationListenerPendingIntent); 383 384 assertThat(shadowLocationManager.getRequestLocationUdpateCriteriaPendingIntents().get(someLocationListenerPendingIntent), 385 equalTo(someCriteria)); 386 } 387 388 private Listener addGpsListenerToLocationManager() { 389 Listener listener = new TestGpsListener(); 390 locationManager.addGpsStatusListener(listener); 391 return listener; 392 } 393 394 private static class TestLocationListener implements LocationListener { 395 public boolean providerEnabled; 396 397 @Override 398 public void onLocationChanged(Location location) { 399 } 400 401 @Override 402 public void onStatusChanged(String s, int i, Bundle bundle) { 403 } 404 405 @Override 406 public void onProviderEnabled(String s) { 407 providerEnabled = true; 408 } 409 410 @Override 411 public void onProviderDisabled(String s) { 412 providerEnabled = false; 413 } 414 } 415 416 private class TestGpsListener implements Listener { 417 418 @Override 419 public void onGpsStatusChanged(int event) { 420 421 } 422 } 423} 424