| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.location; |
| |
| import android.app.PendingIntent; |
| import android.content.Intent; |
| import android.os.Bundle; |
| import android.os.Looper; |
| import android.os.RemoteException; |
| import android.os.Handler; |
| import android.os.Message; |
| import android.util.Log; |
| |
| import com.android.internal.location.DummyLocationProvider; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| |
| /** |
| * This class provides access to the system location services. These |
| * services allow applications to obtain periodic updates of the |
| * device's geographical location, or to fire an application-specified |
| * {@link Intent} when the device enters the proximity of a given |
| * geographical location. |
| * |
| * <p>You do not |
| * instantiate this class directly; instead, retrieve it through |
| * {@link android.content.Context#getSystemService |
| * Context.getSystemService(Context.LOCATION_SERVICE)}. |
| */ |
| public class LocationManager { |
| private static final String TAG = "LocationManager"; |
| private ILocationManager mService; |
| private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners = |
| new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>(); |
| private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners = |
| new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>(); |
| private final GpsStatus mGpsStatus = new GpsStatus(); |
| |
| /** |
| * Name of the network location provider. This provider determines location based on |
| * availability of cell tower and WiFi access points. Results are retrieved |
| * by means of a network lookup. |
| * |
| * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION |
| * or android.permission.ACCESS_FINE_LOCATION. |
| */ |
| public static final String NETWORK_PROVIDER = "network"; |
| |
| /** |
| * Name of the GPS location provider. This provider determines location using |
| * satellites. Depending on conditions, this provider may take a while to return |
| * a location fix. |
| * |
| * Requires the permission android.permission.ACCESS_FINE_LOCATION. |
| * |
| * <p> The extras Bundle for the GPS location provider can contain the |
| * following key/value pairs: |
| * |
| * <ul> |
| * <li> satellites - the number of satellites used to derive the fix |
| * </ul> |
| */ |
| public static final String GPS_PROVIDER = "gps"; |
| |
| /** |
| * A special location provider for receiving locations without actually initiating |
| * a location fix. This provider can be used to passively receive location updates |
| * when other applications or services request them without actually requesting |
| * the locations yourself. This provider will return locations generated by other |
| * providers. You can query the {@link Location#getProvider()} method to determine |
| * the origin of the location update. |
| * |
| * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS |
| * is not enabled this provider might only return coarse fixes. |
| */ |
| public static final String PASSIVE_PROVIDER = "passive"; |
| |
| /** |
| * Key used for the Bundle extra holding a boolean indicating whether |
| * a proximity alert is entering (true) or exiting (false).. |
| */ |
| public static final String KEY_PROXIMITY_ENTERING = "entering"; |
| |
| /** |
| * Key used for a Bundle extra holding an Integer status value |
| * when a status change is broadcast using a PendingIntent. |
| */ |
| public static final String KEY_STATUS_CHANGED = "status"; |
| |
| /** |
| * Key used for a Bundle extra holding an Boolean status value |
| * when a provider enabled/disabled event is broadcast using a PendingIntent. |
| */ |
| public static final String KEY_PROVIDER_ENABLED = "providerEnabled"; |
| |
| /** |
| * Key used for a Bundle extra holding a Location value |
| * when a location change is broadcast using a PendingIntent. |
| */ |
| public static final String KEY_LOCATION_CHANGED = "location"; |
| |
| /** |
| * Broadcast intent action indicating that the GPS has either been |
| * enabled or disabled. An intent extra provides this state as a boolean, |
| * where {@code true} means enabled. |
| * @see #EXTRA_GPS_ENABLED |
| * |
| * {@hide} |
| */ |
| public static final String GPS_ENABLED_CHANGE_ACTION = |
| "android.location.GPS_ENABLED_CHANGE"; |
| |
| /** |
| * Broadcast intent action when the configured location providers |
| * change. |
| */ |
| public static final String PROVIDERS_CHANGED_ACTION = |
| "android.location.PROVIDERS_CHANGED"; |
| |
| /** |
| * Broadcast intent action indicating that the GPS has either started or |
| * stopped receiving GPS fixes. An intent extra provides this state as a |
| * boolean, where {@code true} means that the GPS is actively receiving fixes. |
| * @see #EXTRA_GPS_ENABLED |
| * |
| * {@hide} |
| */ |
| public static final String GPS_FIX_CHANGE_ACTION = |
| "android.location.GPS_FIX_CHANGE"; |
| |
| /** |
| * The lookup key for a boolean that indicates whether GPS is enabled or |
| * disabled. {@code true} means GPS is enabled. Retrieve it with |
| * {@link android.content.Intent#getBooleanExtra(String,boolean)}. |
| * |
| * {@hide} |
| */ |
| public static final String EXTRA_GPS_ENABLED = "enabled"; |
| |
| // Map from LocationListeners to their associated ListenerTransport objects |
| private HashMap<LocationListener,ListenerTransport> mListeners = |
| new HashMap<LocationListener,ListenerTransport>(); |
| |
| private class ListenerTransport extends ILocationListener.Stub { |
| private static final int TYPE_LOCATION_CHANGED = 1; |
| private static final int TYPE_STATUS_CHANGED = 2; |
| private static final int TYPE_PROVIDER_ENABLED = 3; |
| private static final int TYPE_PROVIDER_DISABLED = 4; |
| |
| private LocationListener mListener; |
| private final Handler mListenerHandler; |
| |
| ListenerTransport(LocationListener listener, Looper looper) { |
| mListener = listener; |
| |
| if (looper == null) { |
| mListenerHandler = new Handler() { |
| @Override |
| public void handleMessage(Message msg) { |
| _handleMessage(msg); |
| } |
| }; |
| } else { |
| mListenerHandler = new Handler(looper) { |
| @Override |
| public void handleMessage(Message msg) { |
| _handleMessage(msg); |
| } |
| }; |
| } |
| } |
| |
| public void onLocationChanged(Location location) { |
| Message msg = Message.obtain(); |
| msg.what = TYPE_LOCATION_CHANGED; |
| msg.obj = location; |
| mListenerHandler.sendMessage(msg); |
| } |
| |
| public void onStatusChanged(String provider, int status, Bundle extras) { |
| Message msg = Message.obtain(); |
| msg.what = TYPE_STATUS_CHANGED; |
| Bundle b = new Bundle(); |
| b.putString("provider", provider); |
| b.putInt("status", status); |
| if (extras != null) { |
| b.putBundle("extras", extras); |
| } |
| msg.obj = b; |
| mListenerHandler.sendMessage(msg); |
| } |
| |
| public void onProviderEnabled(String provider) { |
| Message msg = Message.obtain(); |
| msg.what = TYPE_PROVIDER_ENABLED; |
| msg.obj = provider; |
| mListenerHandler.sendMessage(msg); |
| } |
| |
| public void onProviderDisabled(String provider) { |
| Message msg = Message.obtain(); |
| msg.what = TYPE_PROVIDER_DISABLED; |
| msg.obj = provider; |
| mListenerHandler.sendMessage(msg); |
| } |
| |
| private void _handleMessage(Message msg) { |
| switch (msg.what) { |
| case TYPE_LOCATION_CHANGED: |
| Location location = new Location((Location) msg.obj); |
| mListener.onLocationChanged(location); |
| break; |
| case TYPE_STATUS_CHANGED: |
| Bundle b = (Bundle) msg.obj; |
| String provider = b.getString("provider"); |
| int status = b.getInt("status"); |
| Bundle extras = b.getBundle("extras"); |
| mListener.onStatusChanged(provider, status, extras); |
| break; |
| case TYPE_PROVIDER_ENABLED: |
| mListener.onProviderEnabled((String) msg.obj); |
| break; |
| case TYPE_PROVIDER_DISABLED: |
| mListener.onProviderDisabled((String) msg.obj); |
| break; |
| } |
| try { |
| mService.locationCallbackFinished(this); |
| } catch (RemoteException e) { |
| Log.e(TAG, "locationCallbackFinished: RemoteException", e); |
| } |
| } |
| } |
| /** |
| * @hide - hide this constructor because it has a parameter |
| * of type ILocationManager, which is a system private class. The |
| * right way to create an instance of this class is using the |
| * factory Context.getSystemService. |
| */ |
| public LocationManager(ILocationManager service) { |
| mService = service; |
| } |
| |
| private LocationProvider createProvider(String name, Bundle info) { |
| DummyLocationProvider provider = |
| new DummyLocationProvider(name, mService); |
| provider.setRequiresNetwork(info.getBoolean("network")); |
| provider.setRequiresSatellite(info.getBoolean("satellite")); |
| provider.setRequiresCell(info.getBoolean("cell")); |
| provider.setHasMonetaryCost(info.getBoolean("cost")); |
| provider.setSupportsAltitude(info.getBoolean("altitude")); |
| provider.setSupportsSpeed(info.getBoolean("speed")); |
| provider.setSupportsBearing(info.getBoolean("bearing")); |
| provider.setPowerRequirement(info.getInt("power")); |
| provider.setAccuracy(info.getInt("accuracy")); |
| return provider; |
| } |
| |
| /** |
| * Returns a list of the names of all known location providers. All |
| * providers are returned, including ones that are not permitted to be |
| * accessed by the calling activity or are currently disabled. |
| * |
| * @return list of Strings containing names of the providers |
| */ |
| public List<String> getAllProviders() { |
| if (false) { |
| Log.d(TAG, "getAllProviders"); |
| } |
| try { |
| return mService.getAllProviders(); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getAllProviders: RemoteException", ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns a list of the names of location providers. Only providers that |
| * are permitted to be accessed by the calling activity will be returned. |
| * |
| * @param enabledOnly if true then only the providers which are currently |
| * enabled are returned. |
| * @return list of Strings containing names of the providers |
| */ |
| public List<String> getProviders(boolean enabledOnly) { |
| try { |
| return mService.getProviders(null, enabledOnly); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getProviders: RemoteException", ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the information associated with the location provider of the |
| * given name, or null if no provider exists by that name. |
| * |
| * @param name the provider name |
| * @return a LocationProvider, or null |
| * |
| * @throws IllegalArgumentException if name is null |
| * @throws SecurityException if the caller is not permitted to access the |
| * given provider. |
| */ |
| public LocationProvider getProvider(String name) { |
| if (name == null) { |
| throw new IllegalArgumentException("name==null"); |
| } |
| try { |
| Bundle info = mService.getProviderInfo(name); |
| if (info == null) { |
| return null; |
| } |
| return createProvider(name, info); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getProvider: RemoteException", ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns a list of the names of LocationProviders that satisfy the given |
| * criteria, or null if none do. Only providers that are permitted to be |
| * accessed by the calling activity will be returned. |
| * |
| * @param criteria the criteria that the returned providers must match |
| * @param enabledOnly if true then only the providers which are currently |
| * enabled are returned. |
| * @return list of Strings containing names of the providers |
| */ |
| public List<String> getProviders(Criteria criteria, boolean enabledOnly) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| try { |
| return mService.getProviders(criteria, enabledOnly); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getProviders: RemoteException", ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the name of the provider that best meets the given criteria. Only providers |
| * that are permitted to be accessed by the calling activity will be |
| * returned. If several providers meet the criteria, the one with the best |
| * accuracy is returned. If no provider meets the criteria, |
| * the criteria are loosened in the following sequence: |
| * |
| * <ul> |
| * <li> power requirement |
| * <li> accuracy |
| * <li> bearing |
| * <li> speed |
| * <li> altitude |
| * </ul> |
| * |
| * <p> Note that the requirement on monetary cost is not removed |
| * in this process. |
| * |
| * @param criteria the criteria that need to be matched |
| * @param enabledOnly if true then only a provider that is currently enabled is returned |
| * @return name of the provider that best matches the requirements |
| */ |
| public String getBestProvider(Criteria criteria, boolean enabledOnly) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| try { |
| return mService.getBestProvider(criteria, enabledOnly); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getBestProvider: RemoteException", ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Registers the current activity to be notified periodically by |
| * the named provider. Periodically, the supplied LocationListener will |
| * be called with the current Location or with status updates. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> In case the provider is disabled by the user, updates will stop, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * <p> The frequency of notification may be controlled using the |
| * minTime and minDistance parameters. If minTime is greater than 0, |
| * the LocationManager could potentially rest for minTime milliseconds |
| * between location updates to conserve power. If minDistance is greater than 0, |
| * a location will only be broadcasted if the device moves by minDistance meters. |
| * To obtain notifications as frequently as possible, set both parameters to 0. |
| * |
| * <p> Background services should be careful about setting a sufficiently high |
| * minTime so that the device doesn't consume too much power by keeping the |
| * GPS or wireless radios on all the time. In particular, values under 60000ms |
| * are not recommended. |
| * |
| * <p> The calling thread must be a {@link android.os.Looper} thread such as |
| * the main thread of the calling Activity. |
| * |
| * @param provider the name of the provider with which to register |
| * @param minTime the minimum time interval for notifications, in |
| * milliseconds. This field is only used as a hint to conserve power, and actual |
| * time between location updates may be greater or lesser than this value. |
| * @param minDistance the minimum distance interval for notifications, |
| * in meters |
| * @param listener a {#link LocationListener} whose |
| * {@link LocationListener#onLocationChanged} method will be called for |
| * each location update |
| * |
| * @throws IllegalArgumentException if provider or listener is null |
| * @throws RuntimeException if the calling thread has no Looper |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestLocationUpdates(String provider, |
| long minTime, float minDistance, LocationListener listener) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null); |
| } |
| |
| /** |
| * Registers the current activity to be notified periodically by |
| * the named provider. Periodically, the supplied LocationListener will |
| * be called with the current Location or with status updates. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> In case the provider is disabled by the user, updates will stop, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * <p> The frequency of notification may be controlled using the |
| * minTime and minDistance parameters. If minTime is greater than 0, |
| * the LocationManager could potentially rest for minTime milliseconds |
| * between location updates to conserve power. If minDistance is greater than 0, |
| * a location will only be broadcasted if the device moves by minDistance meters. |
| * To obtain notifications as frequently as possible, set both parameters to 0. |
| * |
| * <p> Background services should be careful about setting a sufficiently high |
| * minTime so that the device doesn't consume too much power by keeping the |
| * GPS or wireless radios on all the time. In particular, values under 60000ms |
| * are not recommended. |
| * |
| * <p> The supplied Looper is used to implement the callback mechanism. |
| * |
| * @param provider the name of the provider with which to register |
| * @param minTime the minimum time interval for notifications, in |
| * milliseconds. This field is only used as a hint to conserve power, and actual |
| * time between location updates may be greater or lesser than this value. |
| * @param minDistance the minimum distance interval for notifications, |
| * in meters |
| * @param listener a {#link LocationListener} whose |
| * {@link LocationListener#onLocationChanged} method will be called for |
| * each location update |
| * @param looper a Looper object whose message queue will be used to |
| * implement the callback mechanism. |
| * If looper is null then the callbacks will be called on the main thread. |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if listener is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestLocationUpdates(String provider, |
| long minTime, float minDistance, LocationListener listener, |
| Looper looper) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper); |
| } |
| |
| /** |
| * Registers the current activity to be notified periodically based on |
| * the specified criteria. Periodically, the supplied LocationListener will |
| * be called with the current Location or with status updates. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> In case the provider is disabled by the user, updates will stop, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * <p> The frequency of notification may be controlled using the |
| * minTime and minDistance parameters. If minTime is greater than 0, |
| * the LocationManager could potentially rest for minTime milliseconds |
| * between location updates to conserve power. If minDistance is greater than 0, |
| * a location will only be broadcasted if the device moves by minDistance meters. |
| * To obtain notifications as frequently as possible, set both parameters to 0. |
| * |
| * <p> Background services should be careful about setting a sufficiently high |
| * minTime so that the device doesn't consume too much power by keeping the |
| * GPS or wireless radios on all the time. In particular, values under 60000ms |
| * are not recommended. |
| * |
| * <p> The supplied Looper is used to implement the callback mechanism. |
| * |
| * @param minTime the minimum time interval for notifications, in |
| * milliseconds. This field is only used as a hint to conserve power, and actual |
| * time between location updates may be greater or lesser than this value. |
| * @param minDistance the minimum distance interval for notifications, |
| * in meters |
| * @param criteria contains parameters for the location manager to choose the |
| * appropriate provider and parameters to compute the location |
| * @param listener a {#link LocationListener} whose |
| * {@link LocationListener#onLocationChanged} method will be called for |
| * each location update |
| * @param looper a Looper object whose message queue will be used to |
| * implement the callback mechanism. |
| * If looper is null then the callbacks will be called on the main thread. |
| * |
| * @throws IllegalArgumentException if criteria is null |
| * @throws IllegalArgumentException if listener is null |
| * @throws SecurityException if no suitable permission is present to access |
| * the location services. |
| */ |
| public void requestLocationUpdates(long minTime, float minDistance, |
| Criteria criteria, LocationListener listener, Looper looper) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper); |
| } |
| |
| private void _requestLocationUpdates(String provider, Criteria criteria, long minTime, |
| float minDistance, boolean singleShot, LocationListener listener, Looper looper) { |
| if (minTime < 0L) { |
| minTime = 0L; |
| } |
| if (minDistance < 0.0f) { |
| minDistance = 0.0f; |
| } |
| |
| try { |
| synchronized (mListeners) { |
| ListenerTransport transport = mListeners.get(listener); |
| if (transport == null) { |
| transport = new ListenerTransport(listener, looper); |
| } |
| mListeners.put(listener, transport); |
| mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); |
| } |
| } catch (RemoteException ex) { |
| Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex); |
| } |
| } |
| |
| /** |
| * Registers the current activity to be notified periodically by |
| * the named provider. Periodically, the supplied PendingIntent will |
| * be broadcast with the current Location or with status updates. |
| * |
| * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> The frequency of notification or new locations may be controlled using the |
| * minTime and minDistance parameters. If minTime is greater than 0, |
| * the LocationManager could potentially rest for minTime milliseconds |
| * between location updates to conserve power. If minDistance is greater than 0, |
| * a location will only be broadcast if the device moves by minDistance meters. |
| * To obtain notifications as frequently as possible, set both parameters to 0. |
| * |
| * <p> Background services should be careful about setting a sufficiently high |
| * minTime so that the device doesn't consume too much power by keeping the |
| * GPS or wireless radios on all the time. In particular, values under 60000ms |
| * are not recommended. |
| * |
| * <p> In case the provider is disabled by the user, updates will stop, |
| * and an intent will be sent with an extra with key KEY_PROVIDER_ENABLED and a boolean value |
| * of false. If the provider is re-enabled, an intent will be sent with an |
| * extra with key KEY_PROVIDER_ENABLED and a boolean value of true and location updates will |
| * start again. |
| * |
| * <p> If the provider's status changes, an intent will be sent with an extra with key |
| * KEY_STATUS_CHANGED and an integer value indicating the new status. Any extras associated |
| * with the status update will be sent as well. |
| * |
| * @param provider the name of the provider with which to register |
| * @param minTime the minimum time interval for notifications, in |
| * milliseconds. This field is only used as a hint to conserve power, and actual |
| * time between location updates may be greater or lesser than this value. |
| * @param minDistance the minimum distance interval for notifications, |
| * in meters |
| * @param intent a {#link PendingIntent} to be sent for each location update |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if intent is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestLocationUpdates(String provider, |
| long minTime, float minDistance, PendingIntent intent) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| if (intent == null) { |
| throw new IllegalArgumentException("intent==null"); |
| } |
| _requestLocationUpdates(provider, null, minTime, minDistance, false, intent); |
| } |
| |
| /** |
| * Registers the current activity to be notified periodically based on |
| * the specified criteria. Periodically, the supplied PendingIntent will |
| * be broadcast with the current Location or with status updates. |
| * |
| * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> The frequency of notification or new locations may be controlled using the |
| * minTime and minDistance parameters. If minTime is greater than 0, |
| * the LocationManager could potentially rest for minTime milliseconds |
| * between location updates to conserve power. If minDistance is greater than 0, |
| * a location will only be broadcast if the device moves by minDistance meters. |
| * To obtain notifications as frequently as possible, set both parameters to 0. |
| * |
| * <p> Background services should be careful about setting a sufficiently high |
| * minTime so that the device doesn't consume too much power by keeping the |
| * GPS or wireless radios on all the time. In particular, values under 60000ms |
| * are not recommended. |
| * |
| * <p> In case the provider is disabled by the user, updates will stop, |
| * and an intent will be sent with an extra with key KEY_PROVIDER_ENABLED and a boolean value |
| * of false. If the provider is re-enabled, an intent will be sent with an |
| * extra with key KEY_PROVIDER_ENABLED and a boolean value of true and location updates will |
| * start again. |
| * |
| * <p> If the provider's status changes, an intent will be sent with an extra with key |
| * KEY_STATUS_CHANGED and an integer value indicating the new status. Any extras associated |
| * with the status update will be sent as well. |
| * |
| * @param minTime the minimum time interval for notifications, in |
| * milliseconds. This field is only used as a hint to conserve power, and actual |
| * time between location updates may be greater or lesser than this value. |
| * @param minDistance the minimum distance interval for notifications, |
| * in meters |
| * @param criteria contains parameters for the location manager to choose the |
| * appropriate provider and parameters to compute the location |
| * @param intent a {#link PendingIntent} to be sent for each location update |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if intent is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| if (intent == null) { |
| throw new IllegalArgumentException("intent==null"); |
| } |
| _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent); |
| } |
| |
| private void _requestLocationUpdates(String provider, Criteria criteria, |
| long minTime, float minDistance, boolean singleShot, PendingIntent intent) { |
| if (minTime < 0L) { |
| minTime = 0L; |
| } |
| if (minDistance < 0.0f) { |
| minDistance = 0.0f; |
| } |
| |
| try { |
| mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "requestLocationUpdates: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Requests a single location update from the named provider. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> In case the provider is disabled by the user, the update will not be received, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * <p> The supplied Looper is used to implement the callback mechanism. |
| * |
| * @param provider the name of the provider with which to register |
| * @param listener a {#link LocationListener} whose |
| * {@link LocationListener#onLocationChanged} method will be called when |
| * the location update is available |
| * @param looper a Looper object whose message queue will be used to |
| * implement the callback mechanism. |
| * If looper is null then the callbacks will be called on the main thread. |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if listener is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper); |
| } |
| |
| /** |
| * Requests a single location update based on the specified criteria. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> In case the provider is disabled by the user, the update will not be received, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * <p> The supplied Looper is used to implement the callback mechanism. |
| * |
| * @param criteria contains parameters for the location manager to choose the |
| * appropriate provider and parameters to compute the location |
| * @param listener a {#link LocationListener} whose |
| * {@link LocationListener#onLocationChanged} method will be called when |
| * the location update is available |
| * @param looper a Looper object whose message queue will be used to |
| * implement the callback mechanism. |
| * If looper is null then the callbacks will be called on the current thread. |
| * |
| * @throws IllegalArgumentException if criteria is null |
| * @throws IllegalArgumentException if listener is null |
| * @throws SecurityException if no suitable permission is present to access |
| * the location services. |
| */ |
| public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper); |
| } |
| |
| /** |
| * Requests a single location update from the named provider. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. |
| * |
| * <p> In case the provider is disabled by the user, the update will not be received, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * @param provider the name of the provider with which to register |
| * @param intent a {#link PendingIntent} to be sent for the location update |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if intent is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestSingleUpdate(String provider, PendingIntent intent) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| if (intent == null) { |
| throw new IllegalArgumentException("intent==null"); |
| } |
| _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent); |
| } |
| |
| /** |
| * Requests a single location update based on the specified criteria. |
| * |
| * <p> It may take a while to receive the most recent location. If |
| * an immediate location is required, applications may use the |
| * {@link #getLastKnownLocation(String)} method. |
| * |
| * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. |
| * |
| * <p> In case the provider is disabled by the user, the update will not be received, |
| * and the {@link LocationListener#onProviderDisabled(String)} |
| * method will be called. As soon as the provider is enabled again, |
| * the {@link LocationListener#onProviderEnabled(String)} method will |
| * be called and location updates will start again. |
| * |
| * @param criteria contains parameters for the location manager to choose the |
| * appropriate provider and parameters to compute the location |
| * @param intent a {#link PendingIntent} to be sent for the location update |
| * |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| * @throws IllegalArgumentException if intent is null |
| * @throws SecurityException if no suitable permission is present for the provider. |
| */ |
| public void requestSingleUpdate(Criteria criteria, PendingIntent intent) { |
| if (criteria == null) { |
| throw new IllegalArgumentException("criteria==null"); |
| } |
| if (intent == null) { |
| throw new IllegalArgumentException("intent==null"); |
| } |
| _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent); |
| } |
| |
| /** |
| * Removes any current registration for location updates of the current activity |
| * with the given LocationListener. Following this call, updates will no longer |
| * occur for this listener. |
| * |
| * @param listener {#link LocationListener} object that no longer needs location updates |
| * @throws IllegalArgumentException if listener is null |
| */ |
| public void removeUpdates(LocationListener listener) { |
| if (listener == null) { |
| throw new IllegalArgumentException("listener==null"); |
| } |
| if (false) { |
| Log.d(TAG, "removeUpdates: listener = " + listener); |
| } |
| try { |
| ListenerTransport transport = mListeners.remove(listener); |
| if (transport != null) { |
| mService.removeUpdates(transport); |
| } |
| } catch (RemoteException ex) { |
| Log.e(TAG, "removeUpdates: DeadObjectException", ex); |
| } |
| } |
| |
| /** |
| * Removes any current registration for location updates of the current activity |
| * with the given PendingIntent. Following this call, updates will no longer |
| * occur for this intent. |
| * |
| * @param intent {#link PendingIntent} object that no longer needs location updates |
| * @throws IllegalArgumentException if intent is null |
| */ |
| public void removeUpdates(PendingIntent intent) { |
| if (intent == null) { |
| throw new IllegalArgumentException("intent==null"); |
| } |
| if (false) { |
| Log.d(TAG, "removeUpdates: intent = " + intent); |
| } |
| try { |
| mService.removeUpdatesPI(intent); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "removeUpdates: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Sets a proximity alert for the location given by the position |
| * (latitude, longitude) and the given radius. When the device |
| * detects that it has entered or exited the area surrounding the |
| * location, the given PendingIntent will be used to create an Intent |
| * to be fired. |
| * |
| * <p> The fired Intent will have a boolean extra added with key |
| * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is |
| * entering the proximity region; if false, it is exiting. |
| * |
| * <p> Due to the approximate nature of position estimation, if the |
| * device passes through the given area briefly, it is possible |
| * that no Intent will be fired. Similarly, an Intent could be |
| * fired if the device passes very close to the given area but |
| * does not actually enter it. |
| * |
| * <p> After the number of milliseconds given by the expiration |
| * parameter, the location manager will delete this proximity |
| * alert and no longer monitor it. A value of -1 indicates that |
| * there should be no expiration time. |
| * |
| * <p> In case the screen goes to sleep, checks for proximity alerts |
| * happen only once every 4 minutes. This conserves battery life by |
| * ensuring that the device isn't perpetually awake. |
| * |
| * <p> Internally, this method uses both {@link #NETWORK_PROVIDER} |
| * and {@link #GPS_PROVIDER}. |
| * |
| * @param latitude the latitude of the central point of the |
| * alert region |
| * @param longitude the longitude of the central point of the |
| * alert region |
| * @param radius the radius of the central point of the |
| * alert region, in meters |
| * @param expiration time for this proximity alert, in milliseconds, |
| * or -1 to indicate no expiration |
| * @param intent a PendingIntent that will be used to generate an Intent to |
| * fire when entry to or exit from the alert region is detected |
| * |
| * @throws SecurityException if no permission exists for the required |
| * providers. |
| */ |
| public void addProximityAlert(double latitude, double longitude, |
| float radius, long expiration, PendingIntent intent) { |
| if (false) { |
| Log.d(TAG, "addProximityAlert: latitude = " + latitude + |
| ", longitude = " + longitude + ", radius = " + radius + |
| ", expiration = " + expiration + |
| ", intent = " + intent); |
| } |
| try { |
| mService.addProximityAlert(latitude, longitude, radius, |
| expiration, intent); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "addProximityAlert: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Removes the proximity alert with the given PendingIntent. |
| * |
| * @param intent the PendingIntent that no longer needs to be notified of |
| * proximity alerts |
| */ |
| public void removeProximityAlert(PendingIntent intent) { |
| if (false) { |
| Log.d(TAG, "removeProximityAlert: intent = " + intent); |
| } |
| try { |
| mService.removeProximityAlert(intent); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "removeProximityAlert: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Returns the current enabled/disabled status of the given provider. If the |
| * user has enabled this provider in the Settings menu, true is returned |
| * otherwise false is returned |
| * |
| * @param provider the name of the provider |
| * @return true if the provider is enabled |
| * |
| * @throws SecurityException if no suitable permission is present for the provider. |
| * @throws IllegalArgumentException if provider is null |
| */ |
| public boolean isProviderEnabled(String provider) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| try { |
| return mService.isProviderEnabled(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "isProviderEnabled: RemoteException", ex); |
| return false; |
| } |
| } |
| |
| /** |
| * Returns a Location indicating the data from the last known |
| * location fix obtained from the given provider. This can be done |
| * without starting the provider. Note that this location could |
| * be out-of-date, for example if the device was turned off and |
| * moved to another location. |
| * |
| * <p> If the provider is currently disabled, null is returned. |
| * |
| * @param provider the name of the provider |
| * @return the last known location for the provider, or null |
| * |
| * @throws SecurityException if no suitable permission is present for the provider. |
| * @throws IllegalArgumentException if provider is null or doesn't exist |
| */ |
| public Location getLastKnownLocation(String provider) { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider==null"); |
| } |
| try { |
| return mService.getLastKnownLocation(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "getLastKnowLocation: RemoteException", ex); |
| return null; |
| } |
| } |
| |
| // Mock provider support |
| |
| /** |
| * Creates a mock location provider and adds it to the set of active providers. |
| * |
| * @param name the provider name |
| * @param requiresNetwork |
| * @param requiresSatellite |
| * @param requiresCell |
| * @param hasMonetaryCost |
| * @param supportsAltitude |
| * @param supportsSpeed |
| * @param supportsBearing |
| * @param powerRequirement |
| * @param accuracy |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled |
| * @throws IllegalArgumentException if a provider with the given name already exists |
| */ |
| public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, |
| boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, |
| boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { |
| try { |
| mService.addTestProvider(name, requiresNetwork, requiresSatellite, requiresCell, |
| hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, powerRequirement, |
| accuracy); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "addTestProvider: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Removes the mock location provider with the given name. |
| * |
| * @param provider the provider name |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void removeTestProvider(String provider) { |
| try { |
| mService.removeTestProvider(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "removeTestProvider: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Sets a mock location for the given provider. This location will be used in place |
| * of any actual location from the provider. |
| * |
| * @param provider the provider name |
| * @param loc the mock location |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void setTestProviderLocation(String provider, Location loc) { |
| try { |
| mService.setTestProviderLocation(provider, loc); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "setTestProviderLocation: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Removes any mock location associated with the given provider. |
| * |
| * @param provider the provider name |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void clearTestProviderLocation(String provider) { |
| try { |
| mService.clearTestProviderLocation(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "clearTestProviderLocation: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Sets a mock enabled value for the given provider. This value will be used in place |
| * of any actual value from the provider. |
| * |
| * @param provider the provider name |
| * @param enabled the mock enabled value |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void setTestProviderEnabled(String provider, boolean enabled) { |
| try { |
| mService.setTestProviderEnabled(provider, enabled); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "setTestProviderEnabled: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Removes any mock enabled value associated with the given provider. |
| * |
| * @param provider the provider name |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void clearTestProviderEnabled(String provider) { |
| try { |
| mService.clearTestProviderEnabled(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "clearTestProviderEnabled: RemoteException", ex); |
| } |
| |
| } |
| |
| /** |
| * Sets mock status values for the given provider. These values will be used in place |
| * of any actual values from the provider. |
| * |
| * @param provider the provider name |
| * @param status the mock status |
| * @param extras a Bundle containing mock extras |
| * @param updateTime the mock update time |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { |
| try { |
| mService.setTestProviderStatus(provider, status, extras, updateTime); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "setTestProviderStatus: RemoteException", ex); |
| } |
| } |
| |
| /** |
| * Removes any mock status values associated with the given provider. |
| * |
| * @param provider the provider name |
| * |
| * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present |
| * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION |
| * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled |
| * @throws IllegalArgumentException if no provider with the given name exists |
| */ |
| public void clearTestProviderStatus(String provider) { |
| try { |
| mService.clearTestProviderStatus(provider); |
| } catch (RemoteException ex) { |
| Log.e(TAG, "clearTestProviderStatus: RemoteException", ex); |
| } |
| } |
| |
| // GPS-specific support |
| |
| // This class is used to send GPS status events to the client's main thread. |
| private class GpsStatusListenerTransport extends IGpsStatusListener.Stub { |
| |
| private final GpsStatus.Listener mListener; |
| private final GpsStatus.NmeaListener mNmeaListener; |
| |
| // This must not equal any of the GpsStatus event IDs |
| private static final int NMEA_RECEIVED = 1000; |
| |
| private class Nmea { |
| long mTimestamp; |
| String mNmea; |
| |
| Nmea(long timestamp, String nmea) { |
| mTimestamp = timestamp; |
| mNmea = nmea; |
| } |
| } |
| private ArrayList<Nmea> mNmeaBuffer; |
| |
| GpsStatusListenerTransport(GpsStatus.Listener listener) { |
| mListener = listener; |
| mNmeaListener = null; |
| } |
| |
| GpsStatusListenerTransport(GpsStatus.NmeaListener listener) { |
| mNmeaListener = listener; |
| mListener = null; |
| mNmeaBuffer = new ArrayList<Nmea>(); |
| } |
| |
| public void onGpsStarted() { |
| if (mListener != null) { |
| Message msg = Message.obtain(); |
| msg.what = GpsStatus.GPS_EVENT_STARTED; |
| mGpsHandler.sendMessage(msg); |
| } |
| } |
| |
| public void onGpsStopped() { |
| if (mListener != null) { |
| Message msg = Message.obtain(); |
| msg.what = GpsStatus.GPS_EVENT_STOPPED; |
| mGpsHandler.sendMessage(msg); |
| } |
| } |
| |
| public void onFirstFix(int ttff) { |
| if (mListener != null) { |
| mGpsStatus.setTimeToFirstFix(ttff); |
| Message msg = Message.obtain(); |
| msg.what = GpsStatus.GPS_EVENT_FIRST_FIX; |
| mGpsHandler.sendMessage(msg); |
| } |
| } |
| |
| public void onSvStatusChanged(int svCount, int[] prns, float[] snrs, |
| float[] elevations, float[] azimuths, int ephemerisMask, |
| int almanacMask, int usedInFixMask) { |
| if (mListener != null) { |
| mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths, |
| ephemerisMask, almanacMask, usedInFixMask); |
| |
| Message msg = Message.obtain(); |
| msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS; |
| // remove any SV status messages already in the queue |
| mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS); |
| mGpsHandler.sendMessage(msg); |
| } |
| } |
| |
| public void onNmeaReceived(long timestamp, String nmea) { |
| if (mNmeaListener != null) { |
| synchronized (mNmeaBuffer) { |
| mNmeaBuffer.add(new Nmea(timestamp, nmea)); |
| } |
| Message msg = Message.obtain(); |
| msg.what = NMEA_RECEIVED; |
| // remove any NMEA_RECEIVED messages already in the queue |
| mGpsHandler.removeMessages(NMEA_RECEIVED); |
| mGpsHandler.sendMessage(msg); |
| } |
| } |
| |
| private final Handler mGpsHandler = new Handler() { |
| @Override |
| public void handleMessage(Message msg) { |
| if (msg.what == NMEA_RECEIVED) { |
| synchronized (mNmeaBuffer) { |
| int length = mNmeaBuffer.size(); |
| for (int i = 0; i < length; i++) { |
| Nmea nmea = mNmeaBuffer.get(i); |
| mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea); |
| } |
| mNmeaBuffer.clear(); |
| } |
| } else { |
| // synchronize on mGpsStatus to ensure the data is copied atomically. |
| synchronized(mGpsStatus) { |
| mListener.onGpsStatusChanged(msg.what); |
| } |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Adds a GPS status listener. |
| * |
| * @param listener GPS status listener object to register |
| * |
| * @return true if the listener was successfully added |
| * |
| * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present |
| */ |
| public boolean addGpsStatusListener(GpsStatus.Listener listener) { |
| boolean result; |
| |
| if (mGpsStatusListeners.get(listener) != null) { |
| // listener is already registered |
| return true; |
| } |
| try { |
| GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); |
| result = mService.addGpsStatusListener(transport); |
| if (result) { |
| mGpsStatusListeners.put(listener, transport); |
| } |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e); |
| result = false; |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Removes a GPS status listener. |
| * |
| * @param listener GPS status listener object to remove |
| */ |
| public void removeGpsStatusListener(GpsStatus.Listener listener) { |
| try { |
| GpsStatusListenerTransport transport = mGpsStatusListeners.remove(listener); |
| if (transport != null) { |
| mService.removeGpsStatusListener(transport); |
| } |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); |
| } |
| } |
| |
| /** |
| * Adds an NMEA listener. |
| * |
| * @param listener a {#link GpsStatus.NmeaListener} object to register |
| * |
| * @return true if the listener was successfully added |
| * |
| * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present |
| */ |
| public boolean addNmeaListener(GpsStatus.NmeaListener listener) { |
| boolean result; |
| |
| if (mNmeaListeners.get(listener) != null) { |
| // listener is already registered |
| return true; |
| } |
| try { |
| GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); |
| result = mService.addGpsStatusListener(transport); |
| if (result) { |
| mNmeaListeners.put(listener, transport); |
| } |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e); |
| result = false; |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Removes an NMEA listener. |
| * |
| * @param listener a {#link GpsStatus.NmeaListener} object to remove |
| */ |
| public void removeNmeaListener(GpsStatus.NmeaListener listener) { |
| try { |
| GpsStatusListenerTransport transport = mNmeaListeners.remove(listener); |
| if (transport != null) { |
| mService.removeGpsStatusListener(transport); |
| } |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); |
| } |
| } |
| |
| /** |
| * Retrieves information about the current status of the GPS engine. |
| * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} |
| * callback to ensure that the data is copied atomically. |
| * |
| * The caller may either pass in a {@link GpsStatus} object to set with the latest |
| * status information, or pass null to create a new {@link GpsStatus} object. |
| * |
| * @param status object containing GPS status details, or null. |
| * @return status object containing updated GPS status. |
| */ |
| public GpsStatus getGpsStatus(GpsStatus status) { |
| if (status == null) { |
| status = new GpsStatus(); |
| } |
| status.setStatus(mGpsStatus); |
| return status; |
| } |
| |
| /** |
| * Sends additional commands to a location provider. |
| * Can be used to support provider specific extensions to the Location Manager API |
| * |
| * @param provider name of the location provider. |
| * @param command name of the command to send to the provider. |
| * @param extras optional arguments for the command (or null). |
| * The provider may optionally fill the extras Bundle with results from the command. |
| * |
| * @return true if the command succeeds. |
| */ |
| public boolean sendExtraCommand(String provider, String command, Bundle extras) { |
| try { |
| return mService.sendExtraCommand(provider, command, extras); |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in sendExtraCommand: ", e); |
| return false; |
| } |
| } |
| |
| /** |
| * Used by NetInitiatedActivity to report user response |
| * for network initiated GPS fix requests. |
| * |
| * {@hide} |
| */ |
| public boolean sendNiResponse(int notifId, int userResponse) { |
| try { |
| return mService.sendNiResponse(notifId, userResponse); |
| } catch (RemoteException e) { |
| Log.e(TAG, "RemoteException in sendNiResponse: ", e); |
| return false; |
| } |
| } |
| |
| } |