blob: 91de1d8f92e6496bc4ea3d468a3f20670089f083 [file] [log] [blame]
Steve Block67e1eb62009-07-31 09:06:59 +01001/*
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
17package android.webkit;
18
19import android.app.ActivityThread;
20import android.content.Context;
21import android.location.Location;
22import android.location.LocationListener;
23import android.location.LocationManager;
24import android.location.LocationProvider;
25import android.os.Bundle;
26import android.util.Log;
27import android.webkit.WebView;
28import android.webkit.WebViewCore;
29
30
31/**
32 * Implements the Java side of GeolocationServiceAndroid.
Steve Block67e1eb62009-07-31 09:06:59 +010033 */
Grace Kloba0691ad52009-10-22 12:17:20 -070034final class GeolocationService implements LocationListener {
Steve Block67e1eb62009-07-31 09:06:59 +010035
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
Steve Block074c08c2010-06-28 10:26:39 +010048 * @param context The context from which we obtain the system service.
Steve Block67e1eb62009-07-31 09:06:59 +010049 * @param nativeObject The native object to which this object will report position updates and
50 * errors.
51 */
Steve Block074c08c2010-06-28 10:26:39 +010052 public GeolocationService(Context context, long nativeObject) {
Steve Block67e1eb62009-07-31 09:06:59 +010053 mNativeObject = nativeObject;
54 // Register newLocationAvailable with platform service.
Steve Block67e1eb62009-07-31 09:06:59 +010055 mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
56 if (mLocationManager == null) {
57 Log.e(TAG, "Could not get location manager.");
58 }
59 }
60
61 /**
62 * Start listening for location updates.
63 */
Steve Block3d9e0662010-05-18 15:16:55 +010064 public boolean start() {
Steve Block67e1eb62009-07-31 09:06:59 +010065 registerForLocationUpdates();
66 mIsRunning = true;
Steve Block3d9e0662010-05-18 15:16:55 +010067 return mIsNetworkProviderAvailable || mIsGpsProviderAvailable;
Steve Block67e1eb62009-07-31 09:06:59 +010068 }
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();
Steve Block3d9e0662010-05-18 15:16:55 +010090 // Check that the providers are still available after we re-register.
91 maybeReportError("The last location provider is no longer available");
Steve Block67e1eb62009-07-31 09:06:59 +010092 }
93 }
94 }
95
96 /**
97 * LocationListener implementation.
98 * Called when the location has changed.
99 * @param location The new location, as a Location object.
100 */
101 public void onLocationChanged(Location location) {
102 // Callbacks from the system location sevice are queued to this thread, so it's possible
103 // that we receive callbacks after unregistering. At this point, the native object will no
104 // longer exist.
105 if (mIsRunning) {
106 nativeNewLocationAvailable(mNativeObject, location);
107 }
108 }
109
110 /**
111 * LocationListener implementation.
112 * Called when the provider status changes.
113 * @param provider The name of the provider.
114 * @param status The new status of the provider.
115 * @param extras an optional Bundle with provider specific data.
116 */
117 public void onStatusChanged(String providerName, int status, Bundle extras) {
118 boolean isAvailable = (status == LocationProvider.AVAILABLE);
119 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
120 mIsNetworkProviderAvailable = isAvailable;
121 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
122 mIsGpsProviderAvailable = isAvailable;
123 }
124 maybeReportError("The last location provider is no longer available");
125 }
126
127 /**
128 * LocationListener implementation.
129 * Called when the provider is enabled.
130 * @param provider The name of the location provider that is now enabled.
131 */
132 public void onProviderEnabled(String providerName) {
133 // No need to notify the native side. It's enough to start sending
134 // valid position fixes again.
135 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
136 mIsNetworkProviderAvailable = true;
137 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
138 mIsGpsProviderAvailable = true;
139 }
140 }
141
142 /**
143 * LocationListener implementation.
144 * Called when the provider is disabled.
145 * @param provider The name of the location provider that is now disabled.
146 */
147 public void onProviderDisabled(String providerName) {
148 if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
149 mIsNetworkProviderAvailable = false;
150 } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
151 mIsGpsProviderAvailable = false;
152 }
153 maybeReportError("The last location provider was disabled");
154 }
155
156 /**
157 * Registers this object with the location service.
158 */
159 private void registerForLocationUpdates() {
Steve Block4afcd2e2009-09-03 11:41:29 +0100160 try {
Steve Block3d9e0662010-05-18 15:16:55 +0100161 // Registration may fail if providers are not present on the device.
162 try {
163 mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
164 mIsNetworkProviderAvailable = true;
165 } catch(IllegalArgumentException e) { }
Steve Block4afcd2e2009-09-03 11:41:29 +0100166 if (mIsGpsEnabled) {
Steve Block3d9e0662010-05-18 15:16:55 +0100167 try {
168 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
169 mIsGpsProviderAvailable = true;
170 } catch(IllegalArgumentException e) { }
Steve Block4afcd2e2009-09-03 11:41:29 +0100171 }
172 } catch(SecurityException e) {
173 Log.e(TAG, "Caught security exception registering for location updates from system. " +
174 "This should only happen in DumpRenderTree.");
Steve Block67e1eb62009-07-31 09:06:59 +0100175 }
176 }
177
178 /**
179 * Unregisters this object from the location service.
180 */
181 private void unregisterFromLocationUpdates() {
182 mLocationManager.removeUpdates(this);
Steve Block3d9e0662010-05-18 15:16:55 +0100183 mIsNetworkProviderAvailable = false;
184 mIsGpsProviderAvailable = false;
Steve Block67e1eb62009-07-31 09:06:59 +0100185 }
186
187 /**
188 * Reports an error if neither the network nor the GPS provider is available.
189 */
190 private void maybeReportError(String message) {
191 // Callbacks from the system location sevice are queued to this thread, so it's possible
192 // that we receive callbacks after unregistering. At this point, the native object will no
193 // longer exist.
194 if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) {
195 nativeNewErrorAvailable(mNativeObject, message);
196 }
197 }
198
199 // Native functions
200 private static native void nativeNewLocationAvailable(long nativeObject, Location location);
201 private static native void nativeNewErrorAvailable(long nativeObject, String message);
202}