1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.webkit; 18 19 import android.app.ActivityThread; 20 import android.content.Context; 21 import android.location.Location; 22 import android.location.LocationListener; 23 import android.location.LocationManager; 24 import android.location.LocationProvider; 25 import android.os.Bundle; 26 import android.util.Log; 27 import android.webkit.WebView; 28 import android.webkit.WebViewCore; 29 30 31 /** 32 * Implements the Java side of GeolocationServiceAndroid. 33 */ 34 final class GeolocationService implements LocationListener { 35 36 // Log tag 37 private static final String TAG = "geolocationService"; 38 39 private long mNativeObject; 40 private LocationManager mLocationManager; 41 private boolean mIsGpsEnabled; 42 private boolean mIsRunning; 43 private boolean mIsNetworkProviderAvailable; 44 private boolean mIsGpsProviderAvailable; 45 46 /** 47 * Constructor 48 * @param nativeObject The native object to which this object will report position updates and 49 * errors. 50 */ 51 public GeolocationService(long nativeObject) { 52 mNativeObject = nativeObject; 53 // Register newLocationAvailable with platform service. 54 ActivityThread thread = ActivityThread.systemMain(); 55 Context context = thread.getApplication(); 56 mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 57 if (mLocationManager == null) { 58 Log.e(TAG, "Could not get location manager."); 59 } 60 } 61 62 /** 63 * Start listening for location updates. 64 */ 65 public void start() { 66 registerForLocationUpdates(); 67 mIsRunning = true; 68 } 69 70 /** 71 * Stop listening for location updates. 72 */ 73 public void stop() { 74 unregisterFromLocationUpdates(); 75 mIsRunning = false; 76 } 77 78 /** 79 * Sets whether to use the GPS. 80 * @param enable Whether to use the GPS. 81 */ 82 public void setEnableGps(boolean enable) { 83 if (mIsGpsEnabled != enable) { 84 mIsGpsEnabled = enable; 85 if (mIsRunning) { 86 // There's no way to unregister from a single provider, so we can 87 // only unregister from all, then reregister with all but the GPS. 88 unregisterFromLocationUpdates(); 89 registerForLocationUpdates(); 90 } 91 } 92 } 93 94 /** 95 * LocationListener implementation. 96 * Called when the location has changed. 97 * @param location The new location, as a Location object. 98 */ 99 public void onLocationChanged(Location location) { 100 // Callbacks from the system location sevice are queued to this thread, so it's possible 101 // that we receive callbacks after unregistering. At this point, the native object will no 102 // longer exist. 103 if (mIsRunning) { 104 nativeNewLocationAvailable(mNativeObject, location); 105 } 106 } 107 108 /** 109 * LocationListener implementation. 110 * Called when the provider status changes. 111 * @param provider The name of the provider. 112 * @param status The new status of the provider. 113 * @param extras an optional Bundle with provider specific data. 114 */ 115 public void onStatusChanged(String providerName, int status, Bundle extras) { 116 boolean isAvailable = (status == LocationProvider.AVAILABLE); 117 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 118 mIsNetworkProviderAvailable = isAvailable; 119 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 120 mIsGpsProviderAvailable = isAvailable; 121 } 122 maybeReportError("The last location provider is no longer available"); 123 } 124 125 /** 126 * LocationListener implementation. 127 * Called when the provider is enabled. 128 * @param provider The name of the location provider that is now enabled. 129 */ 130 public void onProviderEnabled(String providerName) { 131 // No need to notify the native side. It's enough to start sending 132 // valid position fixes again. 133 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 134 mIsNetworkProviderAvailable = true; 135 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 136 mIsGpsProviderAvailable = true; 137 } 138 } 139 140 /** 141 * LocationListener implementation. 142 * Called when the provider is disabled. 143 * @param provider The name of the location provider that is now disabled. 144 */ 145 public void onProviderDisabled(String providerName) { 146 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) { 147 mIsNetworkProviderAvailable = false; 148 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) { 149 mIsGpsProviderAvailable = false; 150 } 151 maybeReportError("The last location provider was disabled"); 152 } 153 154 /** 155 * Registers this object with the location service. 156 */ 157 private void registerForLocationUpdates() { 158 try { 159 mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); 160 mIsNetworkProviderAvailable = true; 161 if (mIsGpsEnabled) { 162 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); 163 mIsGpsProviderAvailable = true; 164 } 165 } catch(SecurityException e) { 166 Log.e(TAG, "Caught security exception registering for location updates from system. " + 167 "This should only happen in DumpRenderTree."); 168 } 169 } 170 171 /** 172 * Unregisters this object from the location service. 173 */ 174 private void unregisterFromLocationUpdates() { 175 mLocationManager.removeUpdates(this); 176 } 177 178 /** 179 * Reports an error if neither the network nor the GPS provider is available. 180 */ 181 private void maybeReportError(String message) { 182 // Callbacks from the system location sevice are queued to this thread, so it's possible 183 // that we receive callbacks after unregistering. At this point, the native object will no 184 // longer exist. 185 if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) { 186 nativeNewErrorAvailable(mNativeObject, message); 187 } 188 } 189 190 // Native functions 191 private static native void nativeNewLocationAvailable(long nativeObject, Location location); 192 private static native void nativeNewErrorAvailable(long nativeObject, String message); 193 } 194