167e1eb686439afba13be3d6e02786ebb07b359daSteve Block/* 267e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Copyright (C) 2009 The Android Open Source Project 367e1eb686439afba13be3d6e02786ebb07b359daSteve Block * 467e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Licensed under the Apache License, Version 2.0 (the "License"); 567e1eb686439afba13be3d6e02786ebb07b359daSteve Block * you may not use this file except in compliance with the License. 667e1eb686439afba13be3d6e02786ebb07b359daSteve Block * You may obtain a copy of the License at 767e1eb686439afba13be3d6e02786ebb07b359daSteve Block * 867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * http://www.apache.org/licenses/LICENSE-2.0 967e1eb686439afba13be3d6e02786ebb07b359daSteve Block * 1067e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Unless required by applicable law or agreed to in writing, software 1167e1eb686439afba13be3d6e02786ebb07b359daSteve Block * distributed under the License is distributed on an "AS IS" BASIS, 1267e1eb686439afba13be3d6e02786ebb07b359daSteve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367e1eb686439afba13be3d6e02786ebb07b359daSteve Block * See the License for the specific language governing permissions and 1467e1eb686439afba13be3d6e02786ebb07b359daSteve Block * limitations under the License. 1567e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 1667e1eb686439afba13be3d6e02786ebb07b359daSteve Block 1767e1eb686439afba13be3d6e02786ebb07b359daSteve Blockpackage android.webkit; 1867e1eb686439afba13be3d6e02786ebb07b359daSteve Block 1967e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.app.ActivityThread; 2067e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.content.Context; 2167e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.location.Location; 2267e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.location.LocationListener; 2367e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.location.LocationManager; 2467e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.location.LocationProvider; 2567e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.os.Bundle; 2667e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.util.Log; 2767e1eb686439afba13be3d6e02786ebb07b359daSteve Blockimport android.webkit.WebViewCore; 2867e1eb686439afba13be3d6e02786ebb07b359daSteve Block 2967e1eb686439afba13be3d6e02786ebb07b359daSteve Block 3067e1eb686439afba13be3d6e02786ebb07b359daSteve Block/** 3167e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Implements the Java side of GeolocationServiceAndroid. 3267e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 330691ad50ca6b7a2968a0b95e1e9bb7228dd47d65Grace Klobafinal class GeolocationService implements LocationListener { 3467e1eb686439afba13be3d6e02786ebb07b359daSteve Block 3567e1eb686439afba13be3d6e02786ebb07b359daSteve Block // Log tag 3667e1eb686439afba13be3d6e02786ebb07b359daSteve Block private static final String TAG = "geolocationService"; 3767e1eb686439afba13be3d6e02786ebb07b359daSteve Block 3867e1eb686439afba13be3d6e02786ebb07b359daSteve Block private long mNativeObject; 3967e1eb686439afba13be3d6e02786ebb07b359daSteve Block private LocationManager mLocationManager; 4067e1eb686439afba13be3d6e02786ebb07b359daSteve Block private boolean mIsGpsEnabled; 4167e1eb686439afba13be3d6e02786ebb07b359daSteve Block private boolean mIsRunning; 4267e1eb686439afba13be3d6e02786ebb07b359daSteve Block private boolean mIsNetworkProviderAvailable; 4367e1eb686439afba13be3d6e02786ebb07b359daSteve Block private boolean mIsGpsProviderAvailable; 4467e1eb686439afba13be3d6e02786ebb07b359daSteve Block 4567e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 4667e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Constructor 47074c08c4ebbba0875549496829ee7872dd153ee8Steve Block * @param context The context from which we obtain the system service. 4867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param nativeObject The native object to which this object will report position updates and 4967e1eb686439afba13be3d6e02786ebb07b359daSteve Block * errors. 5067e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 51074c08c4ebbba0875549496829ee7872dd153ee8Steve Block public GeolocationService(Context context, long nativeObject) { 5267e1eb686439afba13be3d6e02786ebb07b359daSteve Block mNativeObject = nativeObject; 5367e1eb686439afba13be3d6e02786ebb07b359daSteve Block // Register newLocationAvailable with platform service. 5467e1eb686439afba13be3d6e02786ebb07b359daSteve Block mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 5567e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (mLocationManager == null) { 5667e1eb686439afba13be3d6e02786ebb07b359daSteve Block Log.e(TAG, "Could not get location manager."); 5767e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 5867e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 5967e1eb686439afba13be3d6e02786ebb07b359daSteve Block 6067e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 6167e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Start listening for location updates. 6267e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 633d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block public boolean start() { 6467e1eb686439afba13be3d6e02786ebb07b359daSteve Block registerForLocationUpdates(); 6567e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsRunning = true; 663d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block return mIsNetworkProviderAvailable || mIsGpsProviderAvailable; 6767e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 6867e1eb686439afba13be3d6e02786ebb07b359daSteve Block 6967e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 7067e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Stop listening for location updates. 7167e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 7267e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void stop() { 7367e1eb686439afba13be3d6e02786ebb07b359daSteve Block unregisterFromLocationUpdates(); 7467e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsRunning = false; 7567e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 7667e1eb686439afba13be3d6e02786ebb07b359daSteve Block 7767e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 7867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Sets whether to use the GPS. 7967e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param enable Whether to use the GPS. 8067e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 8167e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void setEnableGps(boolean enable) { 8267e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (mIsGpsEnabled != enable) { 8367e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsGpsEnabled = enable; 8467e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (mIsRunning) { 8567e1eb686439afba13be3d6e02786ebb07b359daSteve Block // There's no way to unregister from a single provider, so we can 8667e1eb686439afba13be3d6e02786ebb07b359daSteve Block // only unregister from all, then reregister with all but the GPS. 8767e1eb686439afba13be3d6e02786ebb07b359daSteve Block unregisterFromLocationUpdates(); 8867e1eb686439afba13be3d6e02786ebb07b359daSteve Block registerForLocationUpdates(); 893d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block // Check that the providers are still available after we re-register. 903d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block maybeReportError("The last location provider is no longer available"); 9167e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 9267e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 9367e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 9467e1eb686439afba13be3d6e02786ebb07b359daSteve Block 9567e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 9667e1eb686439afba13be3d6e02786ebb07b359daSteve Block * LocationListener implementation. 9767e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Called when the location has changed. 9867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param location The new location, as a Location object. 9967e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 10067e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void onLocationChanged(Location location) { 10167e1eb686439afba13be3d6e02786ebb07b359daSteve Block // Callbacks from the system location sevice are queued to this thread, so it's possible 10267e1eb686439afba13be3d6e02786ebb07b359daSteve Block // that we receive callbacks after unregistering. At this point, the native object will no 10367e1eb686439afba13be3d6e02786ebb07b359daSteve Block // longer exist. 10467e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (mIsRunning) { 10567e1eb686439afba13be3d6e02786ebb07b359daSteve Block nativeNewLocationAvailable(mNativeObject, location); 10667e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 10767e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 10867e1eb686439afba13be3d6e02786ebb07b359daSteve Block 10967e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 11067e1eb686439afba13be3d6e02786ebb07b359daSteve Block * LocationListener implementation. 11167e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Called when the provider status changes. 11267e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param provider The name of the provider. 11367e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param status The new status of the provider. 11467e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param extras an optional Bundle with provider specific data. 11567e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 11667e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void onStatusChanged(String providerName, int status, Bundle extras) { 11767e1eb686439afba13be3d6e02786ebb07b359daSteve Block boolean isAvailable = (status == LocationProvider.AVAILABLE); 11867e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 11967e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsNetworkProviderAvailable = isAvailable; 12067e1eb686439afba13be3d6e02786ebb07b359daSteve Block } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 12167e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsGpsProviderAvailable = isAvailable; 12267e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 12367e1eb686439afba13be3d6e02786ebb07b359daSteve Block maybeReportError("The last location provider is no longer available"); 12467e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 12567e1eb686439afba13be3d6e02786ebb07b359daSteve Block 12667e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 12767e1eb686439afba13be3d6e02786ebb07b359daSteve Block * LocationListener implementation. 12867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Called when the provider is enabled. 12967e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param provider The name of the location provider that is now enabled. 13067e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 13167e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void onProviderEnabled(String providerName) { 13267e1eb686439afba13be3d6e02786ebb07b359daSteve Block // No need to notify the native side. It's enough to start sending 13367e1eb686439afba13be3d6e02786ebb07b359daSteve Block // valid position fixes again. 13467e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 13567e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsNetworkProviderAvailable = true; 13667e1eb686439afba13be3d6e02786ebb07b359daSteve Block } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 13767e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsGpsProviderAvailable = true; 13867e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 13967e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 14067e1eb686439afba13be3d6e02786ebb07b359daSteve Block 14167e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 14267e1eb686439afba13be3d6e02786ebb07b359daSteve Block * LocationListener implementation. 14367e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Called when the provider is disabled. 14467e1eb686439afba13be3d6e02786ebb07b359daSteve Block * @param provider The name of the location provider that is now disabled. 14567e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 14667e1eb686439afba13be3d6e02786ebb07b359daSteve Block public void onProviderDisabled(String providerName) { 14767e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 14867e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsNetworkProviderAvailable = false; 14967e1eb686439afba13be3d6e02786ebb07b359daSteve Block } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 15067e1eb686439afba13be3d6e02786ebb07b359daSteve Block mIsGpsProviderAvailable = false; 15167e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 15267e1eb686439afba13be3d6e02786ebb07b359daSteve Block maybeReportError("The last location provider was disabled"); 15367e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 15467e1eb686439afba13be3d6e02786ebb07b359daSteve Block 15567e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 15667e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Registers this object with the location service. 15767e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 15867e1eb686439afba13be3d6e02786ebb07b359daSteve Block private void registerForLocationUpdates() { 1594afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block try { 1603d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block // Registration may fail if providers are not present on the device. 1613d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block try { 1623d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); 1633d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mIsNetworkProviderAvailable = true; 1643d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block } catch(IllegalArgumentException e) { } 1654afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block if (mIsGpsEnabled) { 1663d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block try { 1673d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); 1683d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mIsGpsProviderAvailable = true; 1693d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block } catch(IllegalArgumentException e) { } 1704afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block } 1714afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block } catch(SecurityException e) { 1724afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block Log.e(TAG, "Caught security exception registering for location updates from system. " + 1734afcd2e9d65f67a06e5afb4140b909885ebe2e1cSteve Block "This should only happen in DumpRenderTree."); 17467e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 17567e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 17667e1eb686439afba13be3d6e02786ebb07b359daSteve Block 17767e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 17867e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Unregisters this object from the location service. 17967e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 18067e1eb686439afba13be3d6e02786ebb07b359daSteve Block private void unregisterFromLocationUpdates() { 18167e1eb686439afba13be3d6e02786ebb07b359daSteve Block mLocationManager.removeUpdates(this); 1823d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mIsNetworkProviderAvailable = false; 1833d9e066ab3bbb184a9651d47ace5fe4c1626287fSteve Block mIsGpsProviderAvailable = false; 18467e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 18567e1eb686439afba13be3d6e02786ebb07b359daSteve Block 18667e1eb686439afba13be3d6e02786ebb07b359daSteve Block /** 18767e1eb686439afba13be3d6e02786ebb07b359daSteve Block * Reports an error if neither the network nor the GPS provider is available. 18867e1eb686439afba13be3d6e02786ebb07b359daSteve Block */ 18967e1eb686439afba13be3d6e02786ebb07b359daSteve Block private void maybeReportError(String message) { 19067e1eb686439afba13be3d6e02786ebb07b359daSteve Block // Callbacks from the system location sevice are queued to this thread, so it's possible 19167e1eb686439afba13be3d6e02786ebb07b359daSteve Block // that we receive callbacks after unregistering. At this point, the native object will no 19267e1eb686439afba13be3d6e02786ebb07b359daSteve Block // longer exist. 19367e1eb686439afba13be3d6e02786ebb07b359daSteve Block if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) { 19467e1eb686439afba13be3d6e02786ebb07b359daSteve Block nativeNewErrorAvailable(mNativeObject, message); 19567e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 19667e1eb686439afba13be3d6e02786ebb07b359daSteve Block } 19767e1eb686439afba13be3d6e02786ebb07b359daSteve Block 19867e1eb686439afba13be3d6e02786ebb07b359daSteve Block // Native functions 19967e1eb686439afba13be3d6e02786ebb07b359daSteve Block private static native void nativeNewLocationAvailable(long nativeObject, Location location); 20067e1eb686439afba13be3d6e02786ebb07b359daSteve Block private static native void nativeNewErrorAvailable(long nativeObject, String message); 20167e1eb686439afba13be3d6e02786ebb07b359daSteve Block} 202