| /* |
| * Copyright (C) 2016 Google Inc. |
| * |
| * 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 com.googlecode.android_scripting.facade; |
| |
| import android.app.Service; |
| import android.content.Context; |
| import android.location.Address; |
| import android.location.Geocoder; |
| import android.location.Location; |
| import android.location.LocationListener; |
| import android.location.LocationManager; |
| import android.os.Bundle; |
| |
| import com.google.common.collect.Maps; |
| import com.googlecode.android_scripting.jsonrpc.RpcReceiver; |
| import com.googlecode.android_scripting.rpc.Rpc; |
| import com.googlecode.android_scripting.rpc.RpcDefault; |
| import com.googlecode.android_scripting.rpc.RpcParameter; |
| import com.googlecode.android_scripting.rpc.RpcStartEvent; |
| import com.googlecode.android_scripting.rpc.RpcStopEvent; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| /** |
| * This facade exposes the LocationManager related functionality.<br> |
| * <br> |
| * <b>Overview</b><br> |
| * Once activated by 'startLocating' the LocationFacade attempts to return location data collected |
| * via GPS or the cell network. If neither are available the last known location may be retrieved. |
| * If both are available the format of the returned data is:<br> |
| * {u'network': {u'altitude': 0, u'provider': u'network', u'longitude': -0.38509020000000002, |
| * u'time': 1297079691231L, u'latitude': 52.410557300000001, u'speed': 0, u'accuracy': 75}, u'gps': |
| * {u'altitude': 51, u'provider': u'gps', u'longitude': -0.38537094593048096, u'time': |
| * 1297079709000L, u'latitude': 52.41076922416687, u'speed': 0, u'accuracy': 24}}<br> |
| * If neither are available {} is returned. <br> |
| * Example (python):<br> |
| * |
| * <pre> |
| * import android, time |
| * droid = android.Android() |
| * droid.startLocating() |
| * time.sleep(15) |
| * loc = droid.readLocation().result |
| * if loc = {}: |
| * loc = getLastKnownLocation().result |
| * if loc != {}: |
| * try: |
| * n = loc['gps'] |
| * except KeyError: |
| * n = loc['network'] |
| * la = n['latitude'] |
| * lo = n['longitude'] |
| * address = droid.geocode(la, lo).result |
| * droid.stopLocating() |
| * </pre> |
| * |
| * The address format is:<br> |
| * [{u'thoroughfare': u'Some Street', u'locality': u'Some Town', u'sub_admin_area': u'Some Borough', |
| * u'admin_area': u'Some City', u'feature_name': u'House Numbers', u'country_code': u'GB', |
| * u'country_name': u'United Kingdom', u'postal_code': u'ST1 1'}] |
| * |
| * @author Damon Kohler (damonkohler@gmail.com) |
| * @author Felix Arends (felix.arends@gmail.com) |
| */ |
| public class LocationFacade extends RpcReceiver { |
| private final EventFacade mEventFacade; |
| private final Service mService; |
| private final Map<String, Location> mLocationUpdates; |
| private final LocationManager mLocationManager; |
| private final Geocoder mGeocoder; |
| |
| private final LocationListener mLocationListener = new LocationListener() { |
| @Override |
| public synchronized void onLocationChanged(Location location) { |
| mLocationUpdates.put(location.getProvider(), location); |
| Map<String, Location> copy = Maps.newHashMap(); |
| for (Entry<String, Location> entry : mLocationUpdates.entrySet()) { |
| copy.put(entry.getKey(), entry.getValue()); |
| } |
| mEventFacade.postEvent("location", copy); |
| } |
| |
| @Override |
| public void onProviderDisabled(String provider) { |
| } |
| |
| @Override |
| public void onProviderEnabled(String provider) { |
| } |
| |
| @Override |
| public void onStatusChanged(String provider, int status, Bundle extras) { |
| } |
| }; |
| |
| public LocationFacade(FacadeManager manager) { |
| super(manager); |
| mService = manager.getService(); |
| mEventFacade = manager.getReceiver(EventFacade.class); |
| mGeocoder = new Geocoder(mService); |
| mLocationManager = (LocationManager) mService.getSystemService(Context.LOCATION_SERVICE); |
| mLocationUpdates = new HashMap<String, Location>(); |
| } |
| |
| @Override |
| public void shutdown() { |
| stopLocating(); |
| } |
| |
| @Rpc(description = "Returns availables providers on the phone") |
| public List<String> locationProviders() { |
| return mLocationManager.getAllProviders(); |
| } |
| |
| @Rpc(description = "Ask if provider is enabled") |
| public boolean locationProviderEnabled( |
| @RpcParameter(name = "provider", description = "Name of location provider") String provider) { |
| return mLocationManager.isProviderEnabled(provider); |
| } |
| |
| @Rpc(description = "Starts collecting location data.") |
| @RpcStartEvent("location") |
| public void startLocating( |
| @RpcParameter(name = "minDistance", description = "minimum time between updates in milliseconds") @RpcDefault("60000") Integer minUpdateTime, |
| @RpcParameter(name = "minUpdateDistance", description = "minimum distance between updates in meters") @RpcDefault("30") Integer minUpdateDistance) { |
| for (String provider : mLocationManager.getAllProviders()) { |
| mLocationManager.requestLocationUpdates(provider, minUpdateTime, minUpdateDistance, |
| mLocationListener, mService.getMainLooper()); |
| } |
| } |
| |
| @Rpc(description = "Returns the current location as indicated by all available providers.", returns = "A map of location information by provider.") |
| public Map<String, Location> readLocation() { |
| return mLocationUpdates; |
| } |
| |
| @Rpc(description = "Stops collecting location data.") |
| @RpcStopEvent("location") |
| public synchronized void stopLocating() { |
| mLocationManager.removeUpdates(mLocationListener); |
| mLocationUpdates.clear(); |
| } |
| |
| @Rpc(description = "Returns the last known location of the device.", returns = "A map of location information by provider.") |
| public Map<String, Location> getLastKnownLocation() { |
| Map<String, Location> location = new HashMap<String, Location>(); |
| for (String provider : mLocationManager.getAllProviders()) { |
| location.put(provider, mLocationManager.getLastKnownLocation(provider)); |
| } |
| return location; |
| } |
| |
| @Rpc(description = "Returns a list of addresses for the given latitude and longitude.", returns = "A list of addresses.") |
| public List<Address> geocode( |
| @RpcParameter(name = "latitude") Double latitude, |
| @RpcParameter(name = "longitude") Double longitude, |
| @RpcParameter(name = "maxResults", description = "maximum number of results") @RpcDefault("1") Integer maxResults) |
| throws IOException { |
| return mGeocoder.getFromLocation(latitude, longitude, maxResults); |
| } |
| } |