AI2 Component  (Version nb184)
LocationSensor.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2009-2011 Google, All Rights reserved
3 // Copyright 2011-2018 MIT, All rights reserved
4 // Released under the Apache License, Version 2.0
5 // http://www.apache.org/licenses/LICENSE-2.0
6 
7 package com.google.appinventor.components.runtime;
8 
21 
22 import android.content.Context;
23 import android.location.Address;
24 import android.location.Criteria;
25 import android.location.Geocoder;
26 import android.location.Location;
27 import android.location.LocationListener;
28 import android.location.LocationManager;
29 import android.location.LocationProvider;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.util.Log;
33 import android.Manifest;
34 
35 import java.io.IOException;
36 import java.util.ArrayList;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Set;
40 
58 @DesignerComponent(version = YaVersion.LOCATIONSENSOR_COMPONENT_VERSION,
59  description = "Non-visible component providing location information, " +
60  "including longitude, latitude, altitude (if supported by the device), " +
61  "speed (if supported by the device), " +
62  "and address. This can also perform \"geocoding\", converting a given " +
63  "address (not necessarily the current one) to a latitude (with the " +
64  "<code>LatitudeFromAddress</code> method) and a longitude (with the " +
65  "<code>LongitudeFromAddress</code> method).</p>\n" +
66  "<p>In order to function, the component must have its " +
67  "<code>Enabled</code> property set to True, and the device must have " +
68  "location sensing enabled through wireless networks or GPS " +
69  "satellites (if outdoors).</p>\n" +
70  "Location information might not be immediately available when an app starts. You'll have to wait a short time for " +
71  "a location provider to be found and used, or wait for the LocationChanged event",
72  category = ComponentCategory.SENSORS,
73  nonVisible = true,
74  iconName = "images/locationSensor.png")
75 @SimpleObject
76 @UsesPermissions(permissionNames =
77  "android.permission.ACCESS_FINE_LOCATION," +
78  "android.permission.ACCESS_COARSE_LOCATION," +
79  "android.permission.ACCESS_MOCK_LOCATION," +
80  "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS")
83 
84  public interface LocationSensorListener extends LocationListener {
85  void onTimeIntervalChanged(int time);
86  void onDistanceIntervalChanged(int distance);
87  void setSource(LocationSensor provider);
88  }
89 
95  private class MyLocationListener implements LocationListener {
96  @Override
97  // This sets fields longitude, latitude, altitude, hasLocationData, and
98  // hasAltitude, then calls LocationSensor.LocationChanged(), all in the
99  // enclosing class LocationSensor.
100  public void onLocationChanged(final Location location) {
101  lastLocation = location;
102  longitude = location.getLongitude();
103  latitude = location.getLatitude();
104  speed = location.getSpeed();
105  // If the current location doesn't have altitude information, the prior
106  // altitude reading is retained.
107  if (location.hasAltitude()) {
108  hasAltitude = true;
109  altitude = location.getAltitude();
110  }
111 
112  // By default Location.latitude == Location.longitude == 0.
113  // So we want to ignore that case rather than generating a changed event.
114  if (longitude != UNKNOWN_VALUE || latitude != UNKNOWN_VALUE) {
115  hasLocationData = true;
116  final double argLatitude = latitude;
117  final double argLongitude = longitude;
118  final double argAltitude = altitude;
119  final float argSpeed = speed;
120  androidUIHandler.post(new Runnable() {
121  @Override
122  public void run() {
123  LocationChanged(argLatitude, argLongitude, argAltitude, argSpeed);
124  for (LocationSensorListener listener : listeners) {
125  listener.onLocationChanged(location);
126  }
127  }
128  });
129  }
130  }
131 
132  @Override
133  public void onProviderDisabled(String provider) {
134  StatusChanged(provider, "Disabled");
135  stopListening();
136  if (enabled) {
137  RefreshProvider("onProviderDisabled");
138  }
139  }
140 
141  @Override
142  public void onProviderEnabled(String provider) {
143  StatusChanged(provider, "Enabled");
144  RefreshProvider("onProviderEnabled");
145  }
146 
147  @Override
148  public void onStatusChanged(String provider, int status, Bundle extras) {
149  switch (status) {
150  // Ignore TEMPORARILY_UNAVAILABLE, because service usually returns quickly.
151  case LocationProvider.TEMPORARILY_UNAVAILABLE:
152  StatusChanged(provider, "TEMPORARILY_UNAVAILABLE");
153  break;
154  case LocationProvider.OUT_OF_SERVICE:
155  // If the provider we were listening to is no longer available,
156  // find another.
157  StatusChanged(provider, "OUT_OF_SERVICE");
158 
159  if (provider.equals(providerName)) {
160  stopListening();
161  RefreshProvider("onStatusChanged");
162  }
163  break;
164  case LocationProvider.AVAILABLE:
165  // If another provider becomes available and is one we hadn't known
166  // about see if it is better than the one we're currently using.
167  StatusChanged(provider, "AVAILABLE");
168  if (!provider.equals(providerName) &&
169  !allProviders.contains(provider)) {
170  RefreshProvider("onStatusChanged");
171  }
172  break;
173  }
174  }
175  }
176 
183  public static final int UNKNOWN_VALUE = 0;
184 
185  // These variables contain information related to the LocationProvider.
186  private final Criteria locationCriteria;
187  private final Handler handler;
188  private final LocationManager locationManager;
189 
190  private final Set<LocationSensorListener> listeners = new HashSet<LocationSensorListener>();
191 
192  private boolean providerLocked = false; // if true we can't change providerName
193  private String providerName;
194  // Invariant: providerLocked => providerName is non-empty
195 
196  private boolean initialized = false;
197 
198  private int timeInterval;
199  private int distanceInterval;
200 
201  private MyLocationListener myLocationListener;
202 
203  private LocationProvider locationProvider;
204  private boolean listening = false;
205  // Invariant: listening <=> a myLocationListener is registered with locationManager
206  // Invariant: !listening <=> locationProvider == null
207 
208  //This holds all the providers available when we last chose providerName.
209  //The reported best provider is first, possibly duplicated.
210  private List<String> allProviders;
211 
212  // These location-related values are set in MyLocationListener.onLocationChanged().
213  private Location lastLocation;
214  private double longitude = UNKNOWN_VALUE;
215  private double latitude = UNKNOWN_VALUE;
216  private double altitude = UNKNOWN_VALUE;
217  private float speed = UNKNOWN_VALUE;
218  private boolean hasLocationData = false;
219  private boolean hasAltitude = false;
220 
221  // For posting events on the UI thread
222  private final Handler androidUIHandler = new Handler();
223 
224  // This is used in reverse geocoding.
225  private Geocoder geocoder;
226 
227  // User-settable properties
228  private boolean enabled = true; // the default value is true
229 
230  private boolean havePermission = false; // Do we have the necessary permission
231  private static final String LOG_TAG = LocationSensor.class.getSimpleName();
232 
238  public LocationSensor(ComponentContainer container) {
239  this(container, true);
240  }
241 
248  public LocationSensor(ComponentContainer container, boolean enabled) {
249  super(container.$form());
250  this.enabled = enabled;
251  handler = new Handler();
252  // Set up listener
253  form.registerForOnResume(this);
254  form.registerForOnStop(this);
255 
256  // Initialize sensor properties (60 seconds; 5 meters)
257  timeInterval = 60000;
258  distanceInterval = 5;
259 
260  // Initialize location-related fields
261  Context context = container.$context();
262  geocoder = new Geocoder(context);
263  locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
264  locationCriteria = new Criteria();
265  myLocationListener = new MyLocationListener();
266  allProviders = new ArrayList<String>();
267  // Do some initialization depending on the initial enabled state
268  Enabled(enabled);
269  }
270 
271  @SuppressWarnings({"unused"}) // Called from Scheme
272  public void Initialize() {
273  initialized = true;
274  Enabled(enabled);
275  }
276 
277  // Events
278 
283  @SimpleEvent(description = "Indicates that a new location has been detected.")
284  public void LocationChanged(double latitude, double longitude, double altitude, float speed) {
285  EventDispatcher.dispatchEvent(this, "LocationChanged", latitude, longitude, altitude, speed);
286  }
287 
292  @SimpleEvent
293  public void StatusChanged(String provider, String status) {
294  if (enabled) {
295  EventDispatcher.dispatchEvent(this, "StatusChanged", provider, status);
296  }
297  }
298 
299  // Properties
300 
306  public String ProviderName() {
307  if (providerName == null) {
308  return "NO PROVIDER";
309  } else {
310  return providerName;
311  }
312  }
313 
324  public void ProviderName(String providerName) {
325  this.providerName = providerName;
326  if (!empty(providerName) && startProvider(providerName)) {
327  return;
328  } else {
329  RefreshProvider("ProviderName");
330  }
331  }
332 
334  public boolean ProviderLocked() {
335  return providerLocked;
336  }
337 
352  public void ProviderLocked(boolean lock) {
353  providerLocked = lock;
354  }
355 
357  defaultValue = "60000")
359  public void TimeInterval(int interval) {
360 
361  // make sure that the provided value is a valid one.
362  // choose 1000000 miliseconds to be the upper limit
363  if (interval < 0 || interval > 1000000)
364  return;
365 
366  timeInterval = interval;
367 
368  // restart listening for location updates, using the new time interval
369  if (enabled) {
370  RefreshProvider("TimeInterval");
371  }
372 
373  for (LocationSensorListener listener : listeners) {
374  listener.onTimeIntervalChanged(timeInterval);
375  }
376  }
377 
389  description = "Determines the minimum time interval, in milliseconds, that the sensor will try " +
390  "to use for sending out location updates. However, location updates will only be received " +
391  "when the location of the phone actually changes, and use of the specified time interval " +
392  "is not guaranteed. For example, if 1000 is used as the time interval, location updates will " +
393  "never be fired sooner than 1000ms, but they may be fired anytime after.",
394  category = PropertyCategory.BEHAVIOR)
395  public int TimeInterval() {
396  return timeInterval;
397  }
398 
400  defaultValue = "5")
402  public void DistanceInterval(int interval) {
403 
404  // make sure that the provided value is a valid one.
405  // choose 1000 meters to be the upper limit
406  if (interval < 0 || interval > 1000)
407  return;
408 
409  distanceInterval = interval;
410 
411  // restart listening for location updates, using the new distance interval
412  if (enabled) {
413  RefreshProvider("DistanceInterval");
414  }
415 
416  for (LocationSensorListener listener : listeners) {
417  listener.onDistanceIntervalChanged(distanceInterval);
418  }
419  }
420 
432  description = "Determines the minimum distance interval, in meters, that the sensor will try " +
433  "to use for sending out location updates. For example, if this is set to 5, then the sensor will " +
434  "fire a LocationChanged event only after 5 meters have been traversed. However, the sensor does " +
435  "not guarantee that an update will be received at exactly the distance interval. It may take more " +
436  "than 5 meters to fire an event, for instance.",
437  category = PropertyCategory.BEHAVIOR)
438  public int DistanceInterval() {
439  return distanceInterval;
440  }
441 
447  public boolean HasLongitudeLatitude() {
448  return hasLocationData && enabled;
449  }
450 
455  public boolean HasAltitude() {
456  return hasAltitude && enabled;
457  }
458 
463  public boolean HasAccuracy() {
464  return Accuracy() != UNKNOWN_VALUE && enabled;
465  }
466 
473  public double Longitude() {
474  return longitude;
475  }
476 
483  public double Latitude() {
484  return latitude;
485  }
486 
498  description = "The most recently available altitude value, in meters. If no value is "
499  + "available, 0 will be returned.")
500  public double Altitude() {
501  return altitude;
502  }
503 
515  description = "The most recent measure of accuracy, in meters. If no value is available, "
516  + "0 will be returned.")
517  public double Accuracy() {
518  if (lastLocation != null && lastLocation.hasAccuracy()) {
519  return lastLocation.getAccuracy();
520  } else if (locationProvider != null) {
521  return locationProvider.getAccuracy();
522  } else {
523  return UNKNOWN_VALUE;
524  }
525  }
526 
532  public boolean Enabled() {
533  return enabled;
534  }
535 
543  defaultValue = "True")
545  public void Enabled(boolean enabled) {
546  this.enabled = enabled;
547  if (!initialized) {
548  return;
549  }
550  if (!enabled) {
551  stopListening();
552  } else {
553  RefreshProvider("Enabled");
554  }
555  }
556 
567  description = "Provides a textual representation of the current address or \"No address "
568  + "available\".")
569  public String CurrentAddress() {
570  if (hasLocationData &&
571  latitude <= 90 && latitude >= -90 &&
572  longitude <= 180 || longitude >= -180) {
573  try {
574  List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
575  if (addresses != null && addresses.size() == 1) {
576  Address address = addresses.get(0);
577  if (address != null) {
578  StringBuilder sb = new StringBuilder();
579  for (int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
580  sb.append(address.getAddressLine(i));
581  sb.append("\n");
582  }
583  return sb.toString();
584  }
585  }
586 
587  } catch (Exception e) {
588  // getFromLocation can throw an IOException or an IllegalArgumentException
589  // a bad result can give an indexOutOfBoundsException
590  // are there others?
591  if (e instanceof IllegalArgumentException
592  || e instanceof IOException
593  || e instanceof IndexOutOfBoundsException ) {
594  Log.e(LOG_TAG, "Exception thrown by getting current address " + e.getMessage());
595  } else {
596  // what other exceptions can happen here?
597  Log.e(LOG_TAG,
598  "Unexpected exception thrown by getting current address " + e.getMessage());
599  }
600  }
601  }
602  return "No address available";
603  }
604 
612  @SimpleFunction(description = "Derives latitude of given address")
613  public double LatitudeFromAddress(String locationName) {
614  try {
615  List<Address> addressObjs = geocoder.getFromLocationName(locationName, 1);
616  Log.i(LOG_TAG, "latitude addressObjs size is " + addressObjs.size() + " for " + locationName);
617  if ( (addressObjs == null) || (addressObjs.size() == 0) ){
618  throw new IOException("");
619  }
620  return addressObjs.get(0).getLatitude();
621  } catch (IOException e) {
622  form.dispatchErrorOccurredEvent(this, "LatitudeFromAddress",
624  return 0;
625  }
626  }
627 
635  @SimpleFunction(description = "Derives longitude of given address")
636  public double LongitudeFromAddress(String locationName) {
637  try {
638  List<Address> addressObjs = geocoder.getFromLocationName(locationName, 1);
639  Log.i(LOG_TAG, "longitude addressObjs size is " + addressObjs.size() + " for " + locationName);
640  if ( (addressObjs == null) || (addressObjs.size() == 0) ){
641  throw new IOException("");
642  }
643  return addressObjs.get(0).getLongitude();
644  } catch (IOException e) {
645  form.dispatchErrorOccurredEvent(this, "LongitudeFromAddress",
647  return 0;
648  }
649  }
650 
656  public List<String> AvailableProviders () {
657  return allProviders;
658  }
659 
660  // Methods to stop and start listening to LocationProviders
661 
669  // @SimpleFunction(description = "Find and start listening to a location provider.")
670  public void RefreshProvider(final String caller) {
671  if (!initialized) return; // Not yet ready to start...
672  stopListening(); // In case another provider is active.
673  final LocationSensor me = this;
674  if (!havePermission) {
675  // Make sure we do this on the UI thread
676  androidUIHandler.post(new Runnable() {
677  @Override
678  public void run() {
679  me.form.askPermission(Manifest.permission.ACCESS_FINE_LOCATION,
681  @Override
682  public void HandlePermissionResponse(String permission, boolean granted) {
683  if (granted) {
684  me.havePermission = true;
685  me.RefreshProvider(caller);
686  Log.d(LOG_TAG, "Permission Granted");
687  } else {
688  me.havePermission = false;
689  me.enabled = false;
690  me.form.dispatchPermissionDeniedEvent(me, caller, Manifest.permission.ACCESS_FINE_LOCATION);
691  }
692  }
693  });
694  }
695  });
696  }
697  if (providerLocked && !empty(providerName)) {
698  listening = startProvider(providerName);
699  return;
700  }
701  allProviders = locationManager.getProviders(true); // Typically it's ("network" "gps")
702  String bProviderName = locationManager.getBestProvider(locationCriteria, true);
703  if (bProviderName != null && !bProviderName.equals(allProviders.get(0))) {
704  allProviders.add(0, bProviderName);
705  }
706  // We'll now try the best first and stop as soon as one successfully starts.
707  for (String providerN : allProviders) {
708  listening = startProvider(providerN);
709  if (listening) {
710  if (!providerLocked) {
711  providerName = providerN;
712  }
713  return;
714  }
715  }
716  }
717 
718  /* Start listening to ProviderName.
719  * Return true iff successful.
720  */
721  private boolean startProvider(final String providerName) {
722  this.providerName = providerName;
723  LocationProvider tLocationProvider = locationManager.getProvider(providerName);
724  if (tLocationProvider == null) {
725  Log.d(LOG_TAG, "getProvider(" + providerName + ") returned null");
726  return false;
727  }
728  stopListening();
729  locationProvider = tLocationProvider;
730  locationManager.requestLocationUpdates(providerName, timeInterval,
731  distanceInterval, myLocationListener);
732  listening = true;
733  return true;
734  }
735 
743  private void stopListening() {
744  if (listening) {
745  locationManager.removeUpdates(myLocationListener);
746  locationProvider = null;
747  listening = false;
748  }
749  }
750 
751 
752  // OnResumeListener implementation
753 
754  @Override
755  public void onResume() {
756  if (enabled) {
757  RefreshProvider("onResume");
758  }
759  }
760 
761  // OnStopListener implementation
762 
763  @Override
764  public void onStop() {
765  stopListening();
766  }
767 
768  // Deleteable implementation
769 
770  @Override
771  public void onDelete() {
772  stopListening();
773  }
774 
775  public void addListener(LocationSensorListener listener) {
776  listener.setSource(this);
777  listeners.add(listener);
778  }
779 
780  public void removeListener(LocationSensorListener listener) {
781  listeners.remove(listener);
782  listener.setSource(null);
783  }
784 
785  private boolean empty(String s) {
786  return s == null || s.length() == 0;
787  }
788 }
com.google.appinventor.components.runtime.EventDispatcher
Definition: EventDispatcher.java:22
com.google.appinventor.components.runtime.LocationSensor.LocationSensor
LocationSensor(ComponentContainer container, boolean enabled)
Definition: LocationSensor.java:248
com.google.appinventor.components.runtime.Form.askPermission
void askPermission(final String permission, final PermissionResultHandler responseRequestor)
Definition: Form.java:2633
com.google.appinventor.components.annotations.SimpleFunction
Definition: SimpleFunction.java:23
com.google.appinventor.components.runtime.LocationSensor.DistanceInterval
void DistanceInterval(int interval)
Definition: LocationSensor.java:402
com.google.appinventor.components.runtime.util.ErrorMessages
Definition: ErrorMessages.java:17
com.google.appinventor.components.runtime.LocationSensor.onDelete
void onDelete()
Definition: LocationSensor.java:771
com.google.appinventor.components.runtime.util
-*- mode: java; c-basic-offset: 2; -*-
Definition: AccountChooser.java:7
com.google.appinventor.components.common.YaVersion
Definition: YaVersion.java:14
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_SENSOR_DIST_INTERVAL
static final String PROPERTY_TYPE_SENSOR_DIST_INTERVAL
Definition: PropertyTypeConstants.java:224
com.google.appinventor.components.annotations.DesignerProperty
Definition: DesignerProperty.java:25
com.google.appinventor.components
com.google.appinventor.components.runtime.LocationSensor.Enabled
void Enabled(boolean enabled)
Definition: LocationSensor.java:545
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN
static final String PROPERTY_TYPE_BOOLEAN
Definition: PropertyTypeConstants.java:35
com.google.appinventor.components.runtime.LocationSensor.ProviderLocked
void ProviderLocked(boolean lock)
Definition: LocationSensor.java:352
com.google.appinventor.components.runtime.LocationSensor.addListener
void addListener(LocationSensorListener listener)
Definition: LocationSensor.java:775
com.google.appinventor.components.annotations.DesignerComponent
Definition: DesignerComponent.java:22
com.google.appinventor.components.annotations.SimpleEvent
Definition: SimpleEvent.java:20
com.google.appinventor.components.annotations.PropertyCategory.BEHAVIOR
BEHAVIOR
Definition: PropertyCategory.java:15
com.google.appinventor.components.runtime.LocationSensor.LocationSensorListener.onDistanceIntervalChanged
void onDistanceIntervalChanged(int distance)
com.google.appinventor.components.runtime.LocationSensor.removeListener
void removeListener(LocationSensorListener listener)
Definition: LocationSensor.java:780
com.google.appinventor.components.runtime.LocationSensor.ProviderName
void ProviderName(String providerName)
Definition: LocationSensor.java:324
com.google.appinventor.components.runtime.Form.dispatchPermissionDeniedEvent
void dispatchPermissionDeniedEvent(final Component component, final String functionName, final PermissionException exception)
Definition: Form.java:987
com.google.appinventor.components.annotations.UsesPermissions
Definition: UsesPermissions.java:21
com.google.appinventor.components.runtime.OnResumeListener
Definition: OnResumeListener.java:14
com.google.appinventor.components.runtime.util.ErrorMessages.ERROR_LOCATION_SENSOR_LATITUDE_NOT_FOUND
static final int ERROR_LOCATION_SENSOR_LATITUDE_NOT_FOUND
Definition: ErrorMessages.java:26
com.google.appinventor.components.runtime.PermissionResultHandler
Definition: PermissionResultHandler.java:15
com.google.appinventor.components.runtime.EventDispatcher.dispatchEvent
static boolean dispatchEvent(Component component, String eventName, Object...args)
Definition: EventDispatcher.java:188
com.google.appinventor.components.runtime.AndroidNonvisibleComponent
Definition: AndroidNonvisibleComponent.java:17
com.google.appinventor.components.runtime.LocationSensor.StatusChanged
void StatusChanged(String provider, String status)
Definition: LocationSensor.java:293
com.google.appinventor.components.runtime.LocationSensor.onStop
void onStop()
Definition: LocationSensor.java:764
com.google.appinventor.components.annotations.SimpleProperty
Definition: SimpleProperty.java:23
com.google.appinventor.components.runtime.LocationSensor.LocationSensorListener.setSource
void setSource(LocationSensor provider)
com.google.appinventor.components.annotations.PropertyCategory
Definition: PropertyCategory.java:13
com.google.appinventor.components.runtime.ComponentContainer
Definition: ComponentContainer.java:16
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_SENSOR_TIME_INTERVAL
static final String PROPERTY_TYPE_SENSOR_TIME_INTERVAL
Definition: PropertyTypeConstants.java:230
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google.appinventor.components.runtime.Component
Definition: Component.java:17
com.google.appinventor.components.runtime.Deleteable
Definition: Deleteable.java:15
com.google.appinventor.components.runtime.LocationSensor
Definition: LocationSensor.java:81
com.google.appinventor.components.common
Definition: ComponentCategory.java:7
com.google.appinventor.components.common.ComponentCategory
Definition: ComponentCategory.java:48
com.google.appinventor.components.runtime.OnStopListener
Definition: OnStopListener.java:15
com.google.appinventor.components.runtime.LocationSensor.LocationSensorListener
Definition: LocationSensor.java:84
com.google.appinventor.components.annotations.SimpleObject
Definition: SimpleObject.java:23
com.google
com
com.google.appinventor.components.runtime.LocationSensor.TimeInterval
void TimeInterval(int interval)
Definition: LocationSensor.java:359
com.google.appinventor.components.runtime.LocationSensor.LocationSensor
LocationSensor(ComponentContainer container)
Definition: LocationSensor.java:238
com.google.appinventor.components.runtime.ComponentContainer.$form
Form $form()
com.google.appinventor.components.runtime.ComponentContainer.$context
Activity $context()
com.google.appinventor.components.runtime.LocationSensor.onResume
void onResume()
Definition: LocationSensor.java:755
com.google.appinventor.components.runtime.util.ErrorMessages.ERROR_LOCATION_SENSOR_LONGITUDE_NOT_FOUND
static final int ERROR_LOCATION_SENSOR_LONGITUDE_NOT_FOUND
Definition: ErrorMessages.java:27
com.google.appinventor.components.runtime.AndroidNonvisibleComponent.form
final Form form
Definition: AndroidNonvisibleComponent.java:19
com.google.appinventor.components.runtime.LocationSensor.Initialize
void Initialize()
Definition: LocationSensor.java:272
com.google.appinventor.components.common.PropertyTypeConstants
Definition: PropertyTypeConstants.java:14
com.google.appinventor.components.annotations
com.google.appinventor
com.google.appinventor.components.runtime.LocationSensor.RefreshProvider
void RefreshProvider(final String caller)
Definition: LocationSensor.java:670
com.google.appinventor.components.runtime.LocationSensor.LocationSensorListener.onTimeIntervalChanged
void onTimeIntervalChanged(int time)