mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-03 18:03:06 +02:00
Clean up DataSource, DataSourceManager, and DataSourceListener.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2011 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.google.android.apps.mytracks.content;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Data source on the phone.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class DataSource {
|
||||
|
||||
private static final int NETWORK_PROVIDER_MIN_TIME = 5 * 60 * 1000; // 5 minutes
|
||||
private static final String TAG = DataSource.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
private final ContentResolver contentResolver;
|
||||
private final LocationManager locationManager;
|
||||
private final SensorManager sensorManager;
|
||||
private final SharedPreferences sharedPreferences;
|
||||
|
||||
public DataSource(Context context) {
|
||||
this.context = context;
|
||||
contentResolver = context.getContentResolver();
|
||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a content observer.
|
||||
*
|
||||
* @param uri the uri
|
||||
* @param observer the observer
|
||||
*/
|
||||
public void registerContentObserver(Uri uri, ContentObserver observer) {
|
||||
contentResolver.registerContentObserver(uri, false, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a content observer.
|
||||
*
|
||||
* @param observer the observer
|
||||
*/
|
||||
public void unregisterContentObserver(ContentObserver observer) {
|
||||
contentResolver.unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a location listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void registerLocationListener(LocationListener listener) {
|
||||
// Check if the GPS provider exists
|
||||
if (locationManager.getProvider(LocationManager.GPS_PROVIDER) == null) {
|
||||
listener.onProviderDisabled(LocationManager.GPS_PROVIDER);
|
||||
unregisterLocationListener(listener);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen for GPS location
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
|
||||
|
||||
// Update the listener with the current provider state
|
||||
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
||||
listener.onProviderEnabled(LocationManager.GPS_PROVIDER);
|
||||
} else {
|
||||
listener.onProviderDisabled(LocationManager.GPS_PROVIDER);
|
||||
}
|
||||
|
||||
// Listen for network location
|
||||
try {
|
||||
locationManager.requestLocationUpdates(
|
||||
LocationManager.NETWORK_PROVIDER, NETWORK_PROVIDER_MIN_TIME, 0, listener);
|
||||
} catch (RuntimeException e) {
|
||||
// Network location is optional, so just log the exception
|
||||
Log.w(TAG, "Could not register for network location.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a location listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void unregisterLocationListener(LocationListener listener) {
|
||||
locationManager.removeUpdates(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last known location.
|
||||
*/
|
||||
public Location getLastKnownLocation() {
|
||||
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||
if (!isLocationRecent(location)) {
|
||||
// Try network location
|
||||
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
|
||||
int id = isLocationRecent(location)
|
||||
? R.string.my_location_approximate_location : R.string.my_location_no_location;
|
||||
Toast.makeText(context, id, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the location is recent.
|
||||
*
|
||||
* @param location the location
|
||||
*/
|
||||
private boolean isLocationRecent(Location location) {
|
||||
if (location == null) {
|
||||
return false;
|
||||
}
|
||||
return location.getTime() > System.currentTimeMillis() - MAX_LOCATION_AGE_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a compass listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void registerCompassListener(SensorEventListener listener) {
|
||||
Sensor compass = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
|
||||
if (compass == null) {
|
||||
Log.d(TAG, "No compass sensor.");
|
||||
return;
|
||||
}
|
||||
sensorManager.registerListener(listener, compass, SensorManager.SENSOR_DELAY_UI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a compass listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void unregisterCompassListener(SensorEventListener listener) {
|
||||
sensorManager.unregisterListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a shared preference change listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a shared preference change listener.
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2011 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.google.android.apps.mytracks.content;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
* Listener to be invoked when {@link DataSource} changes.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public interface DataSourceListener {
|
||||
|
||||
/**
|
||||
* Notifies when the tracks table is updated.
|
||||
*/
|
||||
public void notifyTracksTableUpdated();
|
||||
|
||||
/**
|
||||
* Notifies when the waypoints table is updated.
|
||||
*/
|
||||
public void notifyWaypointsTableUpdated();
|
||||
|
||||
/**
|
||||
* Notifies when the track points table is updated.
|
||||
*/
|
||||
public void notifyTrackPointsTableUpdated();
|
||||
|
||||
/**
|
||||
* Notifies when the current location changes.
|
||||
*
|
||||
* @param location the location
|
||||
*/
|
||||
public void notifyLocationChanged(Location location);
|
||||
|
||||
|
||||
/**
|
||||
* Notifies when the location provider enabled status changes.
|
||||
*
|
||||
* @param enabled true if enabled, false if not
|
||||
*/
|
||||
public void notifyLocationProviderEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Notifies when the location provider availability status changes.
|
||||
*
|
||||
* @param available true if available, false if not
|
||||
*/
|
||||
public void notifyLocationProviderAvailable(boolean available);
|
||||
|
||||
/**
|
||||
* Notifies when the compass heading changes.
|
||||
*
|
||||
* @param heading the new heading
|
||||
*/
|
||||
public void notifyHeadingChanged(float heading);
|
||||
|
||||
/**
|
||||
* Notifies when a preference changes.
|
||||
*
|
||||
* @param key the preference key
|
||||
*/
|
||||
public void notifyPreferenceChanged(String key);
|
||||
}
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2011 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.google.android.apps.mytracks.content;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
@@ -10,7 +26,6 @@ import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
@@ -23,154 +38,178 @@ import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* External data source manager, which converts system-level events into My Tracks data events.
|
||||
*
|
||||
* Data source manager. Creates observers/listeners and manages their
|
||||
* registration with {@link DataSource}. The observers/listeners calls
|
||||
* {@link DataSourceListener} when data changes.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
class DataSourceManager {
|
||||
public class DataSourceManager {
|
||||
|
||||
/** Single interface for receiving system events that were registered for. */
|
||||
interface DataSourceListener {
|
||||
void notifyTrackUpdated();
|
||||
void notifyWaypointUpdated();
|
||||
void notifyPointsUpdated();
|
||||
void notifyPreferenceChanged(String key);
|
||||
void notifyLocationProviderEnabled(boolean enabled);
|
||||
void notifyLocationProviderAvailable(boolean available);
|
||||
void notifyLocationChanged(Location loc);
|
||||
void notifyHeadingChanged(float heading);
|
||||
}
|
||||
/**
|
||||
* Observer when the tracks table is updated.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class TracksTableObserver extends ContentObserver {
|
||||
|
||||
private final DataSourceListener listener;
|
||||
|
||||
/** Observer for when the tracks table is updated. */
|
||||
private class TrackObserver extends ContentObserver {
|
||||
public TrackObserver() {
|
||||
super(contentHandler);
|
||||
public TracksTableObserver() {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
listener.notifyTrackUpdated();
|
||||
dataSourceListener.notifyTracksTableUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
/** Observer for when the waypoints table is updated. */
|
||||
private class WaypointObserver extends ContentObserver {
|
||||
public WaypointObserver() {
|
||||
super(contentHandler);
|
||||
/**
|
||||
* Observer when the waypoints table is updated.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class WaypointsTableObserver extends ContentObserver {
|
||||
|
||||
public WaypointsTableObserver() {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
listener.notifyWaypointUpdated();
|
||||
dataSourceListener.notifyWaypointsTableUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
/** Observer for when the points table is updated. */
|
||||
private class PointObserver extends ContentObserver {
|
||||
public PointObserver() {
|
||||
super(contentHandler);
|
||||
/**
|
||||
* Observer when the track points table is updated.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class TrackPointsTableObserver extends ContentObserver {
|
||||
|
||||
public TrackPointsTableObserver() {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
listener.notifyPointsUpdated();
|
||||
dataSourceListener.notifyTrackPointsTableUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
/** Listener for when preferences change. */
|
||||
private class HubSharedPreferenceListener implements OnSharedPreferenceChangeListener {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
listener.notifyPreferenceChanged(key);
|
||||
}
|
||||
}
|
||||
|
||||
/** Listener for the current location (independent from track data). */
|
||||
private class CurrentLocationListener implements
|
||||
LocationListener {
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||
|
||||
listener.notifyLocationProviderAvailable(status == LocationProvider.AVAILABLE);
|
||||
}
|
||||
/**
|
||||
* Listener for location changes.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class CurrentLocationListener implements LocationListener {
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||
|
||||
listener.notifyLocationProviderEnabled(true);
|
||||
public void onLocationChanged(Location location) {
|
||||
dataSourceListener.notifyLocationChanged(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||
|
||||
listener.notifyLocationProviderEnabled(false);
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) {
|
||||
return;
|
||||
}
|
||||
dataSourceListener.notifyLocationProviderEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
listener.notifyLocationChanged(location);
|
||||
public void onProviderEnabled(String provider) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) {
|
||||
return;
|
||||
}
|
||||
dataSourceListener.notifyLocationProviderEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) {
|
||||
return;
|
||||
}
|
||||
dataSourceListener.notifyLocationProviderAvailable(status == LocationProvider.AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Listener for compass readings. */
|
||||
private class CompassListener implements
|
||||
SensorEventListener {
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
listener.notifyHeadingChanged(event.values[0]);
|
||||
}
|
||||
/**
|
||||
* Listener for compass changes.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class CompassListener implements SensorEventListener {
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
dataSourceListener.notifyHeadingChanged(event.values[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrapper for registering internal listeners. */
|
||||
private final DataSourcesWrapper dataSources;
|
||||
/**
|
||||
* Listener for preference changes.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class PreferenceListener implements OnSharedPreferenceChangeListener {
|
||||
|
||||
// Internal listeners (to receive data from the system)
|
||||
private final Set<ListenerDataType> registeredListeners =
|
||||
EnumSet.noneOf(ListenerDataType.class);
|
||||
private final Handler contentHandler;
|
||||
private final ContentObserver pointObserver;
|
||||
private final ContentObserver waypointObserver;
|
||||
private final ContentObserver trackObserver;
|
||||
private final LocationListener locationListener;
|
||||
private final OnSharedPreferenceChangeListener preferenceListener;
|
||||
private final SensorEventListener compassListener;
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
dataSourceListener.notifyPreferenceChanged(key);
|
||||
}
|
||||
}
|
||||
|
||||
DataSourceManager(DataSourceListener listener, DataSourcesWrapper dataSources) {
|
||||
this.listener = listener;
|
||||
this.dataSources = dataSources;
|
||||
private final DataSource dataSource;
|
||||
private final DataSourceListener dataSourceListener;
|
||||
|
||||
contentHandler = new Handler();
|
||||
pointObserver = new PointObserver();
|
||||
waypointObserver = new WaypointObserver();
|
||||
trackObserver = new TrackObserver();
|
||||
// Registered listeners
|
||||
private final Set<ListenerDataType> registeredListeners = EnumSet.noneOf(ListenerDataType.class);
|
||||
|
||||
private final Handler handler;
|
||||
private final TracksTableObserver tracksTableObserver;
|
||||
private final WaypointsTableObserver waypointsTableObserver;
|
||||
private final TrackPointsTableObserver trackPointsTableObserver;
|
||||
private final CurrentLocationListener currentLocationListener;
|
||||
private final CompassListener compassListener;
|
||||
private final PreferenceListener preferenceListener;
|
||||
|
||||
public DataSourceManager(DataSource dataSource, DataSourceListener dataSourceListener) {
|
||||
this.dataSource = dataSource;
|
||||
this.dataSourceListener = dataSourceListener;
|
||||
|
||||
handler = new Handler();
|
||||
tracksTableObserver = new TracksTableObserver();
|
||||
waypointsTableObserver = new WaypointsTableObserver();
|
||||
trackPointsTableObserver = new TrackPointsTableObserver();
|
||||
currentLocationListener = new CurrentLocationListener();
|
||||
compassListener = new CompassListener();
|
||||
locationListener = new CurrentLocationListener();
|
||||
preferenceListener = new HubSharedPreferenceListener();
|
||||
preferenceListener = new PreferenceListener();
|
||||
}
|
||||
|
||||
/** Updates the internal (sensor, position, etc) listeners. */
|
||||
void updateAllListeners(EnumSet<ListenerDataType> externallyNeededListeners) {
|
||||
EnumSet<ListenerDataType> neededListeners = EnumSet.copyOf(externallyNeededListeners);
|
||||
/**
|
||||
* Updates listeners with data source.
|
||||
*
|
||||
* @param listeners the listeners
|
||||
*/
|
||||
public void updateListeners(EnumSet<ListenerDataType> listeners) {
|
||||
EnumSet<ListenerDataType> neededListeners = EnumSet.copyOf(listeners);
|
||||
|
||||
// Special case - map sampled-out points type to points type since they
|
||||
// correspond to the same internal listener.
|
||||
/*
|
||||
* Map SAMPLED_OUT_POINT_UPDATES to POINT_UPDATES since they correspond to
|
||||
* the same internal listener
|
||||
*/
|
||||
if (neededListeners.contains(ListenerDataType.SAMPLED_OUT_POINT_UPDATES)) {
|
||||
neededListeners.remove(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
||||
neededListeners.add(ListenerDataType.POINT_UPDATES);
|
||||
}
|
||||
|
||||
Log.d(TAG, "Updating internal listeners to types " + neededListeners);
|
||||
Log.d(TAG, "Updating listeners " + neededListeners);
|
||||
|
||||
// Unnecessary = registered - needed
|
||||
Set<ListenerDataType> unnecessaryListeners = EnumSet.copyOf(registeredListeners);
|
||||
@@ -180,86 +219,100 @@ class DataSourceManager {
|
||||
Set<ListenerDataType> missingListeners = EnumSet.copyOf(neededListeners);
|
||||
missingListeners.removeAll(registeredListeners);
|
||||
|
||||
// Remove all unnecessary listeners.
|
||||
// Remove unnecessary listeners
|
||||
for (ListenerDataType type : unnecessaryListeners) {
|
||||
unregisterListener(type);
|
||||
}
|
||||
|
||||
// Add all missing listeners.
|
||||
// Add missing listeners
|
||||
for (ListenerDataType type : missingListeners) {
|
||||
registerListener(type);
|
||||
}
|
||||
|
||||
// Now all needed types are registered.
|
||||
// Update registered listeners
|
||||
registeredListeners.clear();
|
||||
registeredListeners.addAll(neededListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener with data source.
|
||||
*
|
||||
* @param type the listener data type
|
||||
*/
|
||||
private void registerListener(ListenerDataType type) {
|
||||
switch (type) {
|
||||
case COMPASS_UPDATES: {
|
||||
// Listen to compass
|
||||
Sensor compass = dataSources.getSensor(Sensor.TYPE_ORIENTATION);
|
||||
if (compass != null) {
|
||||
Log.d(TAG, "TrackDataHub: Now registering sensor listener.");
|
||||
dataSources.registerSensorListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LOCATION_UPDATES:
|
||||
dataSources.requestLocationUpdates(locationListener);
|
||||
break;
|
||||
case POINT_UPDATES:
|
||||
dataSources.registerContentObserver(
|
||||
TrackPointsColumns.CONTENT_URI, false, pointObserver);
|
||||
case SELECTED_TRACK_CHANGED:
|
||||
// Do nothing
|
||||
break;
|
||||
case TRACK_UPDATES:
|
||||
dataSources.registerContentObserver(TracksColumns.CONTENT_URI, false, trackObserver);
|
||||
dataSource.registerContentObserver(TracksColumns.CONTENT_URI, tracksTableObserver);
|
||||
break;
|
||||
case WAYPOINT_UPDATES:
|
||||
dataSources.registerContentObserver(
|
||||
WaypointsColumns.CONTENT_URI, false, waypointObserver);
|
||||
dataSource.registerContentObserver(WaypointsColumns.CONTENT_URI, waypointsTableObserver);
|
||||
break;
|
||||
case DISPLAY_PREFERENCES:
|
||||
dataSources.registerOnSharedPreferenceChangeListener(preferenceListener);
|
||||
case POINT_UPDATES:
|
||||
dataSource.registerContentObserver(
|
||||
TrackPointsColumns.CONTENT_URI, trackPointsTableObserver);
|
||||
break;
|
||||
case SAMPLED_OUT_POINT_UPDATES:
|
||||
throw new IllegalArgumentException("Should have been mapped to point updates");
|
||||
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
|
||||
break;
|
||||
case LOCATION_UPDATES:
|
||||
dataSource.registerLocationListener(currentLocationListener);
|
||||
break;
|
||||
case COMPASS_UPDATES:
|
||||
dataSource.registerCompassListener(compassListener);
|
||||
break;
|
||||
case DISPLAY_PREFERENCES:
|
||||
dataSource.registerOnSharedPreferenceChangeListener(preferenceListener);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a listener with data source.
|
||||
*
|
||||
* @param type listener data type
|
||||
*/
|
||||
private void unregisterListener(ListenerDataType type) {
|
||||
switch (type) {
|
||||
case COMPASS_UPDATES:
|
||||
dataSources.unregisterSensorListener(compassListener);
|
||||
break;
|
||||
case LOCATION_UPDATES:
|
||||
dataSources.removeLocationUpdates(locationListener);
|
||||
break;
|
||||
case POINT_UPDATES:
|
||||
dataSources.unregisterContentObserver(pointObserver);
|
||||
case SELECTED_TRACK_CHANGED:
|
||||
// Do nothing
|
||||
break;
|
||||
case TRACK_UPDATES:
|
||||
dataSources.unregisterContentObserver(trackObserver);
|
||||
dataSource.unregisterContentObserver(tracksTableObserver);
|
||||
break;
|
||||
case WAYPOINT_UPDATES:
|
||||
dataSources.unregisterContentObserver(waypointObserver);
|
||||
dataSource.unregisterContentObserver(waypointsTableObserver);
|
||||
break;
|
||||
case DISPLAY_PREFERENCES:
|
||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||
case POINT_UPDATES:
|
||||
dataSource.unregisterContentObserver(trackPointsTableObserver);
|
||||
break;
|
||||
case SAMPLED_OUT_POINT_UPDATES:
|
||||
throw new IllegalArgumentException("Should have been mapped to point updates");
|
||||
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
|
||||
break;
|
||||
case LOCATION_UPDATES:
|
||||
dataSource.unregisterLocationListener(currentLocationListener);
|
||||
break;
|
||||
case COMPASS_UPDATES:
|
||||
dataSource.unregisterCompassListener(compassListener);
|
||||
break;
|
||||
case DISPLAY_PREFERENCES:
|
||||
dataSource.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Unregisters all internal (sensor, position, etc.) listeners. */
|
||||
void unregisterAllListeners() {
|
||||
dataSources.removeLocationUpdates(locationListener);
|
||||
dataSources.unregisterSensorListener(compassListener);
|
||||
dataSources.unregisterContentObserver(trackObserver);
|
||||
dataSources.unregisterContentObserver(waypointObserver);
|
||||
dataSources.unregisterContentObserver(pointObserver);
|
||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||
/**
|
||||
* Unregisters all listeners with data source.
|
||||
*/
|
||||
public void unregisterAllListeners() {
|
||||
for (ListenerDataType type : ListenerDataType.values()) {
|
||||
unregisterListener(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.google.android.apps.mytracks.content;
|
||||
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* Interface for abstracting registration of external data source listeners.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
interface DataSourcesWrapper {
|
||||
// Preferences
|
||||
void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener);
|
||||
void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener);
|
||||
|
||||
// Content provider
|
||||
void registerContentObserver(Uri contentUri, boolean descendents,
|
||||
ContentObserver observer);
|
||||
void unregisterContentObserver(ContentObserver observer);
|
||||
|
||||
// Sensors
|
||||
Sensor getSensor(int type);
|
||||
void registerSensorListener(SensorEventListener listener,
|
||||
Sensor sensor, int sensorDelay);
|
||||
void unregisterSensorListener(SensorEventListener listener);
|
||||
|
||||
// Location
|
||||
boolean isLocationProviderEnabled(String provider);
|
||||
void requestLocationUpdates(LocationListener listener);
|
||||
void removeLocationUpdates(LocationListener listener);
|
||||
Location getLastKnownLocation();
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.google.android.apps.mytracks.content;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS;
|
||||
import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.location.LocationProvider;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Real implementation of the data sources, which talks to system services.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
class DataSourcesWrapperImpl implements DataSourcesWrapper {
|
||||
// System services
|
||||
private final SensorManager sensorManager;
|
||||
private final LocationManager locationManager;
|
||||
private final ContentResolver contentResolver;
|
||||
private final SharedPreferences sharedPreferences;
|
||||
private final Context context;
|
||||
|
||||
DataSourcesWrapperImpl(Context context, SharedPreferences sharedPreferences) {
|
||||
this.context = context;
|
||||
this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
this.contentResolver = context.getContentResolver();
|
||||
this.sharedPreferences = sharedPreferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerContentObserver(Uri contentUri, boolean descendents,
|
||||
ContentObserver observer) {
|
||||
contentResolver.registerContentObserver(contentUri, descendents, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterContentObserver(ContentObserver observer) {
|
||||
contentResolver.unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sensor getSensor(int type) {
|
||||
return sensorManager.getDefaultSensor(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSensorListener(SensorEventListener listener,
|
||||
Sensor sensor, int sensorDelay) {
|
||||
sensorManager.registerListener(listener, sensor, sensorDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterSensorListener(SensorEventListener listener) {
|
||||
sensorManager.unregisterListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocationProviderEnabled(String provider) {
|
||||
return locationManager.isProviderEnabled(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestLocationUpdates(LocationListener listener) {
|
||||
// Check if the provider exists.
|
||||
LocationProvider gpsProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
|
||||
if (gpsProvider == null) {
|
||||
listener.onProviderDisabled(LocationManager.GPS_PROVIDER);
|
||||
locationManager.removeUpdates(listener);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen to GPS location.
|
||||
String providerName = gpsProvider.getName();
|
||||
Log.d(Constants.TAG, "TrackDataHub: Using location provider " + providerName);
|
||||
locationManager.requestLocationUpdates(providerName,
|
||||
0 /*minTime*/, 0 /*minDist*/, listener);
|
||||
|
||||
// Give an initial update on provider state.
|
||||
if (locationManager.isProviderEnabled(providerName)) {
|
||||
listener.onProviderEnabled(providerName);
|
||||
} else {
|
||||
listener.onProviderDisabled(providerName);
|
||||
}
|
||||
|
||||
// Listen to network location
|
||||
try {
|
||||
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
|
||||
1000 * 60 * 5 /*minTime*/, 0 /*minDist*/, listener);
|
||||
} catch (RuntimeException e) {
|
||||
// If anything at all goes wrong with getting a cell location do not
|
||||
// abort. Cell location is not essential to this app.
|
||||
Log.w(Constants.TAG, "Could not register network location listener.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLastKnownLocation() {
|
||||
// TODO: Let's look at more advanced algorithms to determine the best
|
||||
// current location.
|
||||
|
||||
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||
final long now = System.currentTimeMillis();
|
||||
if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) {
|
||||
// We don't have a recent GPS fix, just use cell towers if available
|
||||
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
|
||||
|
||||
int toastResId = R.string.my_location_approximate_location;
|
||||
if (loc == null || loc.getTime() < now - MAX_NETWORK_AGE_MS) {
|
||||
// We don't have a recent cell tower location, let the user know:
|
||||
toastResId = R.string.my_location_no_location;
|
||||
}
|
||||
|
||||
// Let the user know we have only an approximate location:
|
||||
Toast.makeText(context, toastResId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLocationUpdates(LocationListener listener) {
|
||||
locationManager.removeUpdates(listener);
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS;
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.DataSourceManager.DataSourceListener;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.DoubleBufferedLocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
|
||||
@@ -32,7 +30,6 @@ import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.hardware.GeomagneticField;
|
||||
import android.location.Location;
|
||||
@@ -94,17 +91,17 @@ public class TrackDataHub {
|
||||
/** Listener which receives events from the system. */
|
||||
private class HubDataSourceListener implements DataSourceListener {
|
||||
@Override
|
||||
public void notifyTrackUpdated() {
|
||||
public void notifyTracksTableUpdated() {
|
||||
TrackDataHub.this.notifyTrackUpdated(getListenersFor(ListenerDataType.TRACK_UPDATES));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyWaypointUpdated() {
|
||||
public void notifyWaypointsTableUpdated() {
|
||||
TrackDataHub.this.notifyWaypointUpdated(getListenersFor(ListenerDataType.WAYPOINT_UPDATES));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPointsUpdated() {
|
||||
public void notifyTrackPointsTableUpdated() {
|
||||
TrackDataHub.this.notifyPointsUpdated(true, 0, 0,
|
||||
getListenersFor(ListenerDataType.POINT_UPDATES),
|
||||
getListenersFor(ListenerDataType.SAMPLED_OUT_POINT_UPDATES));
|
||||
@@ -144,7 +141,6 @@ public class TrackDataHub {
|
||||
// Application services
|
||||
private final Context context;
|
||||
private final MyTracksProviderUtils providerUtils;
|
||||
private final SharedPreferences preferences;
|
||||
|
||||
// Get content notifications on the main thread, send listener callbacks in another.
|
||||
// This ensures listener calls are serialized.
|
||||
@@ -154,8 +150,7 @@ public class TrackDataHub {
|
||||
/** Manager for external listeners (those from activities). */
|
||||
private final TrackDataListeners dataListeners;
|
||||
|
||||
/** Wrapper for interacting with system data managers. */
|
||||
private DataSourcesWrapper dataSources;
|
||||
private DataSource dataSource;
|
||||
|
||||
/** Manager for system data listener registrations. */
|
||||
private DataSourceManager dataSourceManager;
|
||||
@@ -193,24 +188,19 @@ public class TrackDataHub {
|
||||
* Builds a new {@link TrackDataHub} instance.
|
||||
*/
|
||||
public synchronized static TrackDataHub newInstance(Context context) {
|
||||
SharedPreferences preferences = context.getSharedPreferences(
|
||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
return new TrackDataHub(context,
|
||||
new TrackDataListeners(),
|
||||
preferences, providerUtils,
|
||||
TARGET_DISPLAYED_TRACK_POINTS);
|
||||
return new TrackDataHub(
|
||||
context, new TrackDataListeners(), providerUtils, TARGET_DISPLAYED_TRACK_POINTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection constructor.
|
||||
*/
|
||||
// @VisibleForTesting
|
||||
TrackDataHub(Context ctx, TrackDataListeners listeners, SharedPreferences preferences,
|
||||
MyTracksProviderUtils providerUtils, int targetNumPoints) {
|
||||
TrackDataHub(Context ctx, TrackDataListeners listeners, MyTracksProviderUtils providerUtils,
|
||||
int targetNumPoints) {
|
||||
this.context = ctx;
|
||||
this.dataListeners = listeners;
|
||||
this.preferences = preferences;
|
||||
this.providerUtils = providerUtils;
|
||||
this.targetNumPoints = targetNumPoints;
|
||||
this.locationFactory = new DoubleBufferedLocationFactory();
|
||||
@@ -233,12 +223,12 @@ public class TrackDataHub {
|
||||
listenerHandlerThread = new HandlerThread("trackDataContentThread");
|
||||
listenerHandlerThread.start();
|
||||
listenerHandler = new Handler(listenerHandlerThread.getLooper());
|
||||
dataSources = newDataSources();
|
||||
dataSourceManager = new DataSourceManager(dataSourceListener, dataSources);
|
||||
dataSource = newDataSource();
|
||||
dataSourceManager = new DataSourceManager(dataSource, dataSourceListener);
|
||||
|
||||
// This may or may not register internal listeners, depending on whether
|
||||
// we already had external listeners.
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||
loadSharedPreferences();
|
||||
|
||||
// If there were listeners already registered, make sure they become up-to-date.
|
||||
@@ -246,8 +236,8 @@ public class TrackDataHub {
|
||||
}
|
||||
|
||||
// @VisibleForTesting
|
||||
protected DataSourcesWrapper newDataSources() {
|
||||
return new DataSourcesWrapperImpl(context, preferences);
|
||||
protected DataSource newDataSource() {
|
||||
return new DataSource(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,7 +257,7 @@ public class TrackDataHub {
|
||||
|
||||
started = false;
|
||||
|
||||
dataSources = null;
|
||||
dataSource = null;
|
||||
dataSourceManager = null;
|
||||
listenerHandlerThread = null;
|
||||
listenerHandler = null;
|
||||
@@ -343,7 +333,7 @@ public class TrackDataHub {
|
||||
}
|
||||
Log.i(TAG, "Forcing location update");
|
||||
|
||||
Location loc = dataSources.getLastKnownLocation();
|
||||
Location loc = dataSource.getLastKnownLocation();
|
||||
if (loc != null) {
|
||||
notifyLocationChanged(loc, getListenersFor(ListenerDataType.LOCATION_UPDATES));
|
||||
}
|
||||
@@ -426,7 +416,7 @@ public class TrackDataHub {
|
||||
|
||||
loadNewDataForListener(registration);
|
||||
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +428,7 @@ public class TrackDataHub {
|
||||
// called. When it is called, we'll do both things.
|
||||
if (!isStarted()) return;
|
||||
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.anyInt;
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
import static com.google.android.testing.mocking.AndroidMock.isA;
|
||||
import static com.google.android.testing.mocking.AndroidMock.leq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.same;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||
@@ -32,6 +30,7 @@ import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockC
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
@@ -70,7 +69,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private TrackDataHub hub;
|
||||
private TrackDataListeners listeners;
|
||||
private DataSourcesWrapper dataSources;
|
||||
private DataSource dataSource;
|
||||
private SharedPreferences sharedPreferences;
|
||||
private TrackDataListener listener1;
|
||||
private TrackDataListener listener2;
|
||||
@@ -79,6 +78,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
private MockContext context;
|
||||
private float declination;
|
||||
|
||||
@UsesMocks({MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class})
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -90,13 +90,13 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
|
||||
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
providerUtils = AndroidMock.createMock("providerUtils", MyTracksProviderUtils.class);
|
||||
dataSources = AndroidMock.createNiceMock("dataSources", DataSourcesWrapper.class);
|
||||
dataSource = AndroidMock.createMock("dataSource", DataSource.class, context);
|
||||
|
||||
listeners = new TrackDataListeners();
|
||||
hub = new TrackDataHub(context, listeners, sharedPreferences, providerUtils, TARGET_POINTS) {
|
||||
hub = new TrackDataHub(context, listeners, providerUtils, TARGET_POINTS) {
|
||||
@Override
|
||||
protected DataSourcesWrapper newDataSources() {
|
||||
return dataSources;
|
||||
protected DataSource newDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,18 +119,18 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
AndroidMock.reset(dataSources);
|
||||
AndroidMock.reset(dataSource);
|
||||
|
||||
// Expect everything to be unregistered.
|
||||
if (preferenceListenerCapture.hasCaptured()) {
|
||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListenerCapture.getValue());
|
||||
dataSource.unregisterOnSharedPreferenceChangeListener(preferenceListenerCapture.getValue());
|
||||
}
|
||||
dataSources.removeLocationUpdates(isA(LocationListener.class));
|
||||
dataSources.unregisterSensorListener(isA(SensorEventListener.class));
|
||||
dataSources.unregisterContentObserver(isA(ContentObserver.class));
|
||||
dataSource.unregisterLocationListener(isA(LocationListener.class));
|
||||
dataSource.unregisterCompassListener(isA(SensorEventListener.class));
|
||||
dataSource.unregisterContentObserver(isA(ContentObserver.class));
|
||||
AndroidMock.expectLastCall().times(3);
|
||||
|
||||
AndroidMock.replay(dataSources);
|
||||
AndroidMock.replay(dataSource);
|
||||
|
||||
hub.stop();
|
||||
hub = null;
|
||||
@@ -143,8 +143,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Track track = new Track();
|
||||
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TracksColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
// Expect the initial loading.
|
||||
// Both listeners (registered before and after start) should get the same data.
|
||||
@@ -185,7 +184,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the other, expect internal unregistration
|
||||
dataSources.unregisterContentObserver(observer);
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
|
||||
replay();
|
||||
|
||||
@@ -321,8 +320,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
.andReturn(wpt2);
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(WaypointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
// Expect the initial loading.
|
||||
// Both listeners (registered before and after start) should get the same data.
|
||||
@@ -398,7 +396,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the other, expect internal unregistration
|
||||
dataSources.unregisterContentObserver(observer);
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
|
||||
replay();
|
||||
|
||||
@@ -412,8 +410,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -497,8 +495,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -519,7 +517,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
|
||||
// Unregister
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
dataSources.unregisterContentObserver(observer);
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
|
||||
replay();
|
||||
|
||||
@@ -528,8 +526,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
verifyAndReset();
|
||||
|
||||
// Register again, except only points since unregistered.
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -552,8 +550,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -574,7 +572,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
|
||||
// Unregister
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
dataSources.unregisterContentObserver(observer);
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
|
||||
replay();
|
||||
|
||||
@@ -583,8 +581,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
verifyAndReset();
|
||||
|
||||
// Register again after track changed, expect all points.
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -608,8 +606,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 200, 4, 25, 71, 120);
|
||||
expect(providerUtils.getLocationIterator(
|
||||
@@ -639,8 +637,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
|
||||
expectStart();
|
||||
dataSources.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
// Deliver 30 points (no sampling happens)
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
|
||||
@@ -702,16 +700,14 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
public void testCompassListen() throws Exception {
|
||||
AndroidMock.resetToDefault(listener1);
|
||||
|
||||
Sensor compass = newSensor();
|
||||
expect(dataSources.getSensor(Sensor.TYPE_ORIENTATION)).andReturn(compass);
|
||||
expectStart();
|
||||
Capture<SensorEventListener> listenerCapture = new Capture<SensorEventListener>();
|
||||
dataSources.registerSensorListener(capture(listenerCapture), same(compass), anyInt());
|
||||
dataSource.registerCompassListener(capture(listenerCapture));
|
||||
|
||||
Capture<LocationListener> locationListenerCapture = new Capture<LocationListener>();
|
||||
dataSources.requestLocationUpdates(capture(locationListenerCapture));
|
||||
dataSource.registerLocationListener(capture(locationListenerCapture));
|
||||
|
||||
SensorEvent event = newSensorEvent();
|
||||
event.sensor = compass;
|
||||
|
||||
// First, get a dummy heading update.
|
||||
listener1.onCurrentHeadingChanged(0.0);
|
||||
@@ -786,9 +782,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
|
||||
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
|
||||
|
||||
Capture<OnSharedPreferenceChangeListener> listenerCapture =
|
||||
new Capture<OnSharedPreferenceChangeListener>();
|
||||
dataSources.registerOnSharedPreferenceChangeListener(capture(listenerCapture));
|
||||
expectStart();
|
||||
|
||||
expect(listener1.onUnitsChanged(true)).andReturn(false);
|
||||
expect(listener2.onUnitsChanged(true)).andReturn(false);
|
||||
@@ -809,12 +803,12 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
replay();
|
||||
|
||||
PreferencesUtils.setBoolean(context, R.string.report_speed_key, false);
|
||||
OnSharedPreferenceChangeListener listener = listenerCapture.getValue();
|
||||
OnSharedPreferenceChangeListener listener = preferenceListenerCapture.getValue();
|
||||
listener.onSharedPreferenceChanged(
|
||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.report_speed_key));
|
||||
|
||||
AndroidMock.verify(dataSources, providerUtils, listener1, listener2);
|
||||
AndroidMock.reset(dataSources, providerUtils, listener1, listener2);
|
||||
AndroidMock.verify(dataSource, providerUtils, listener1, listener2);
|
||||
AndroidMock.reset(dataSource, providerUtils, listener1, listener2);
|
||||
|
||||
expect(listener1.onUnitsChanged(false)).andReturn(false);
|
||||
expect(listener2.onUnitsChanged(false)).andReturn(false);
|
||||
@@ -829,15 +823,15 @@ public class TrackDataHubTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
private void expectStart() {
|
||||
dataSources.registerOnSharedPreferenceChangeListener(capture(preferenceListenerCapture));
|
||||
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceListenerCapture));
|
||||
}
|
||||
|
||||
private void replay() {
|
||||
AndroidMock.replay(dataSources, providerUtils, listener1, listener2);
|
||||
AndroidMock.replay(dataSource, providerUtils, listener1, listener2);
|
||||
}
|
||||
|
||||
private void verifyAndReset() {
|
||||
AndroidMock.verify(listener1, listener2, dataSources, providerUtils);
|
||||
AndroidMock.reset(listener1, listener2, dataSources, providerUtils);
|
||||
AndroidMock.verify(listener1, listener2, dataSource, providerUtils);
|
||||
AndroidMock.reset(listener1, listener2, dataSource, providerUtils);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user