forked from upstream-mirrors/OpenTracks
merge heads
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,16 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
package com.google.android.apps.mytracks.content;
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorEvent;
|
import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
import android.hardware.SensorManager;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
@@ -23,243 +36,281 @@ import java.util.EnumSet;
|
|||||||
import java.util.Set;
|
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
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
class DataSourceManager {
|
public class DataSourceManager {
|
||||||
|
|
||||||
/** Single interface for receiving system events that were registered for. */
|
/**
|
||||||
interface DataSourceListener {
|
* Observer when the tracks table is updated.
|
||||||
void notifyTrackUpdated();
|
*
|
||||||
void notifyWaypointUpdated();
|
* @author Jimmy Shih
|
||||||
void notifyPointsUpdated();
|
*/
|
||||||
void notifyPreferenceChanged(String key);
|
private class TracksTableObserver extends ContentObserver {
|
||||||
void notifyLocationProviderEnabled(boolean enabled);
|
|
||||||
void notifyLocationProviderAvailable(boolean available);
|
|
||||||
void notifyLocationChanged(Location loc);
|
|
||||||
void notifyHeadingChanged(float heading);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final DataSourceListener listener;
|
public TracksTableObserver() {
|
||||||
|
super(handler);
|
||||||
/** Observer for when the tracks table is updated. */
|
|
||||||
private class TrackObserver extends ContentObserver {
|
|
||||||
public TrackObserver() {
|
|
||||||
super(contentHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
listener.notifyTrackUpdated();
|
dataSourceListener.notifyTracksTableUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Observer for when the waypoints table is updated. */
|
/**
|
||||||
private class WaypointObserver extends ContentObserver {
|
* Observer when the waypoints table is updated.
|
||||||
public WaypointObserver() {
|
*
|
||||||
super(contentHandler);
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
private class WaypointsTableObserver extends ContentObserver {
|
||||||
|
|
||||||
|
public WaypointsTableObserver() {
|
||||||
|
super(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
listener.notifyWaypointUpdated();
|
dataSourceListener.notifyWaypointsTableUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Observer for when the points table is updated. */
|
/**
|
||||||
private class PointObserver extends ContentObserver {
|
* Observer when the track points table is updated.
|
||||||
public PointObserver() {
|
*
|
||||||
super(contentHandler);
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
private class TrackPointsTableObserver extends ContentObserver {
|
||||||
|
|
||||||
|
public TrackPointsTableObserver() {
|
||||||
|
super(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
listener.notifyPointsUpdated();
|
dataSourceListener.notifyTrackPointsTableUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Listener for when preferences change. */
|
/**
|
||||||
private class HubSharedPreferenceListener implements OnSharedPreferenceChangeListener {
|
* Listener for location changes.
|
||||||
@Override
|
*
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
* @author Jimmy Shih
|
||||||
listener.notifyPreferenceChanged(key);
|
*/
|
||||||
}
|
private class CurrentLocationListener implements LocationListener {
|
||||||
}
|
|
||||||
|
|
||||||
/** 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProviderEnabled(String provider) {
|
public void onLocationChanged(Location location) {
|
||||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
dataSourceListener.notifyLocationChanged(location);
|
||||||
|
|
||||||
listener.notifyLocationProviderEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProviderDisabled(String provider) {
|
public void onProviderDisabled(String provider) {
|
||||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
if (!LocationManager.GPS_PROVIDER.equals(provider)) {
|
||||||
|
return;
|
||||||
listener.notifyLocationProviderEnabled(false);
|
}
|
||||||
|
dataSourceListener.notifyLocationProviderEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChanged(Location location) {
|
public void onProviderEnabled(String provider) {
|
||||||
listener.notifyLocationChanged(location);
|
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
|
* Listener for compass changes.
|
||||||
SensorEventListener {
|
*
|
||||||
@Override
|
* @author Jimmy Shih
|
||||||
public void onSensorChanged(SensorEvent event) {
|
*/
|
||||||
listener.notifyHeadingChanged(event.values[0]);
|
private class CompassListener implements SensorEventListener {
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||||
// Do nothing
|
// 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)
|
@Override
|
||||||
private final Set<ListenerDataType> registeredListeners =
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
EnumSet.noneOf(ListenerDataType.class);
|
dataSourceListener.notifyPreferenceChanged(key);
|
||||||
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;
|
|
||||||
|
|
||||||
DataSourceManager(DataSourceListener listener, DataSourcesWrapper dataSources) {
|
private final DataSource dataSource;
|
||||||
this.listener = listener;
|
private final DataSourceListener dataSourceListener;
|
||||||
this.dataSources = dataSources;
|
|
||||||
|
|
||||||
contentHandler = new Handler();
|
// Registered listeners
|
||||||
pointObserver = new PointObserver();
|
private final Set<TrackDataType> registeredListeners = EnumSet.noneOf(TrackDataType.class);
|
||||||
waypointObserver = new WaypointObserver();
|
|
||||||
trackObserver = new TrackObserver();
|
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();
|
compassListener = new CompassListener();
|
||||||
locationListener = new CurrentLocationListener();
|
preferenceListener = new PreferenceListener();
|
||||||
preferenceListener = new HubSharedPreferenceListener();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the internal (sensor, position, etc) listeners. */
|
/**
|
||||||
void updateAllListeners(EnumSet<ListenerDataType> externallyNeededListeners) {
|
* Updates listeners with data source.
|
||||||
EnumSet<ListenerDataType> neededListeners = EnumSet.copyOf(externallyNeededListeners);
|
*
|
||||||
|
* @param listeners the listeners
|
||||||
|
*/
|
||||||
|
public void updateListeners(EnumSet<TrackDataType> listeners) {
|
||||||
|
EnumSet<TrackDataType> 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
|
||||||
if (neededListeners.contains(ListenerDataType.SAMPLED_OUT_POINT_UPDATES)) {
|
* the same internal listener
|
||||||
neededListeners.remove(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
*/
|
||||||
neededListeners.add(ListenerDataType.POINT_UPDATES);
|
if (neededListeners.contains(TrackDataType.SAMPLED_OUT_TRACK_POINTS)) {
|
||||||
|
neededListeners.remove(TrackDataType.SAMPLED_OUT_TRACK_POINTS);
|
||||||
|
neededListeners.add(TrackDataType.TRACK_POINTS_TABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Updating internal listeners to types " + neededListeners);
|
Log.d(TAG, "Updating listeners " + neededListeners);
|
||||||
|
|
||||||
// Unnecessary = registered - needed
|
// Unnecessary = registered - needed
|
||||||
Set<ListenerDataType> unnecessaryListeners = EnumSet.copyOf(registeredListeners);
|
Set<TrackDataType> unnecessaryListeners = EnumSet.copyOf(registeredListeners);
|
||||||
unnecessaryListeners.removeAll(neededListeners);
|
unnecessaryListeners.removeAll(neededListeners);
|
||||||
|
|
||||||
// Missing = needed - registered
|
// Missing = needed - registered
|
||||||
Set<ListenerDataType> missingListeners = EnumSet.copyOf(neededListeners);
|
Set<TrackDataType> missingListeners = EnumSet.copyOf(neededListeners);
|
||||||
missingListeners.removeAll(registeredListeners);
|
missingListeners.removeAll(registeredListeners);
|
||||||
|
|
||||||
// Remove all unnecessary listeners.
|
// Remove unnecessary listeners
|
||||||
for (ListenerDataType type : unnecessaryListeners) {
|
for (TrackDataType trackDataType : unnecessaryListeners) {
|
||||||
unregisterListener(type);
|
unregisterListener(trackDataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all missing listeners.
|
// Add missing listeners
|
||||||
for (ListenerDataType type : missingListeners) {
|
for (TrackDataType trackDataType : missingListeners) {
|
||||||
registerListener(type);
|
registerListener(trackDataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now all needed types are registered.
|
// Update registered listeners
|
||||||
registeredListeners.clear();
|
registeredListeners.clear();
|
||||||
registeredListeners.addAll(neededListeners);
|
registeredListeners.addAll(neededListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerListener(ListenerDataType type) {
|
/**
|
||||||
switch (type) {
|
* Registers a listener with data source.
|
||||||
case COMPASS_UPDATES: {
|
*
|
||||||
// Listen to compass
|
* @param trackDataType the listener data type
|
||||||
Sensor compass = dataSources.getSensor(Sensor.TYPE_ORIENTATION);
|
*/
|
||||||
if (compass != null) {
|
private void registerListener(TrackDataType trackDataType) {
|
||||||
Log.d(TAG, "TrackDataHub: Now registering sensor listener.");
|
switch (trackDataType) {
|
||||||
dataSources.registerSensorListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI);
|
case SELECTED_TRACK:
|
||||||
}
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
}
|
case TRACKS_TABLE:
|
||||||
case LOCATION_UPDATES:
|
dataSource.registerContentObserver(TracksColumns.CONTENT_URI, tracksTableObserver);
|
||||||
dataSources.requestLocationUpdates(locationListener);
|
|
||||||
break;
|
break;
|
||||||
case POINT_UPDATES:
|
case WAYPOINTS_TABLE:
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(WaypointsColumns.CONTENT_URI, waypointsTableObserver);
|
||||||
TrackPointsColumns.CONTENT_URI, false, pointObserver);
|
|
||||||
break;
|
break;
|
||||||
case TRACK_UPDATES:
|
case TRACK_POINTS_TABLE:
|
||||||
dataSources.registerContentObserver(TracksColumns.CONTENT_URI, false, trackObserver);
|
dataSource.registerContentObserver(
|
||||||
|
TrackPointsColumns.CONTENT_URI, trackPointsTableObserver);
|
||||||
break;
|
break;
|
||||||
case WAYPOINT_UPDATES:
|
case SAMPLED_OUT_TRACK_POINTS:
|
||||||
dataSources.registerContentObserver(
|
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
|
||||||
WaypointsColumns.CONTENT_URI, false, waypointObserver);
|
|
||||||
break;
|
break;
|
||||||
case DISPLAY_PREFERENCES:
|
case LOCATION:
|
||||||
dataSources.registerOnSharedPreferenceChangeListener(preferenceListener);
|
dataSource.registerLocationListener(currentLocationListener);
|
||||||
|
break;
|
||||||
|
case COMPASS:
|
||||||
|
dataSource.registerCompassListener(compassListener);
|
||||||
|
break;
|
||||||
|
case PREFERENCE:
|
||||||
|
dataSource.registerOnSharedPreferenceChangeListener(preferenceListener);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
case SAMPLED_OUT_POINT_UPDATES:
|
|
||||||
throw new IllegalArgumentException("Should have been mapped to point updates");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unregisterListener(ListenerDataType type) {
|
/**
|
||||||
switch (type) {
|
* Unregisters a listener with data source.
|
||||||
case COMPASS_UPDATES:
|
*
|
||||||
dataSources.unregisterSensorListener(compassListener);
|
* @param trackDataType listener data type
|
||||||
|
*/
|
||||||
|
private void unregisterListener(TrackDataType trackDataType) {
|
||||||
|
switch (trackDataType) {
|
||||||
|
case SELECTED_TRACK:
|
||||||
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
case LOCATION_UPDATES:
|
case TRACKS_TABLE:
|
||||||
dataSources.removeLocationUpdates(locationListener);
|
dataSource.unregisterContentObserver(tracksTableObserver);
|
||||||
break;
|
break;
|
||||||
case POINT_UPDATES:
|
case WAYPOINTS_TABLE:
|
||||||
dataSources.unregisterContentObserver(pointObserver);
|
dataSource.unregisterContentObserver(waypointsTableObserver);
|
||||||
break;
|
break;
|
||||||
case TRACK_UPDATES:
|
case TRACK_POINTS_TABLE:
|
||||||
dataSources.unregisterContentObserver(trackObserver);
|
dataSource.unregisterContentObserver(trackPointsTableObserver);
|
||||||
break;
|
break;
|
||||||
case WAYPOINT_UPDATES:
|
case SAMPLED_OUT_TRACK_POINTS:
|
||||||
dataSources.unregisterContentObserver(waypointObserver);
|
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
|
||||||
break;
|
break;
|
||||||
case DISPLAY_PREFERENCES:
|
case LOCATION:
|
||||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
dataSource.unregisterLocationListener(currentLocationListener);
|
||||||
|
break;
|
||||||
|
case COMPASS:
|
||||||
|
dataSource.unregisterCompassListener(compassListener);
|
||||||
|
break;
|
||||||
|
case PREFERENCE:
|
||||||
|
dataSource.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
case SAMPLED_OUT_POINT_UPDATES:
|
|
||||||
throw new IllegalArgumentException("Should have been mapped to point updates");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unregisters all internal (sensor, position, etc.) listeners. */
|
/**
|
||||||
void unregisterAllListeners() {
|
* Unregisters all listeners with data source.
|
||||||
dataSources.removeLocationUpdates(locationListener);
|
*/
|
||||||
dataSources.unregisterSensorListener(compassListener);
|
public void unregisterAllListeners() {
|
||||||
dataSources.unregisterContentObserver(trackObserver);
|
for (TrackDataType trackDataType : TrackDataType.values()) {
|
||||||
dataSources.unregisterContentObserver(waypointObserver);
|
unregisterListener(trackDataType);
|
||||||
dataSources.unregisterContentObserver(pointObserver);
|
}
|
||||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.EnumSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State for a registered {@link TrackDataListener}.
|
||||||
|
*
|
||||||
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
public class ListenerState {
|
||||||
|
|
||||||
|
private TrackDataListener trackDataListener;
|
||||||
|
private EnumSet<TrackDataType> trackDataTypes;
|
||||||
|
|
||||||
|
private long lastTrackId;
|
||||||
|
private long lastPointId;
|
||||||
|
private int lastSamplingFrequency;
|
||||||
|
private int numberOfLoadedPoints;
|
||||||
|
|
||||||
|
public ListenerState(
|
||||||
|
TrackDataListener trackDataListener, EnumSet<TrackDataType> trackDataTypes) {
|
||||||
|
this.trackDataListener = trackDataListener;
|
||||||
|
this.trackDataTypes = trackDataTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link TrackDataListener}.
|
||||||
|
*/
|
||||||
|
public TrackDataListener getTrackDataListener() {
|
||||||
|
return trackDataListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the track data types.
|
||||||
|
*/
|
||||||
|
public EnumSet<TrackDataType> getTrackDataTypes() {
|
||||||
|
return trackDataTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last track id.
|
||||||
|
*/
|
||||||
|
public long getLastTrackId() {
|
||||||
|
return lastTrackId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last point id.
|
||||||
|
*/
|
||||||
|
public long getLastPointId() {
|
||||||
|
return lastPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last sampling frequency.
|
||||||
|
*/
|
||||||
|
public int getLastSamplingFrequency() {
|
||||||
|
return lastSamplingFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of loaded points.
|
||||||
|
*/
|
||||||
|
public int getNumberOfLoadedPoints() {
|
||||||
|
return numberOfLoadedPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the listener state.
|
||||||
|
*
|
||||||
|
* @param trackId track id
|
||||||
|
* @param pointId point id
|
||||||
|
* @param samplingFrequency sampling frequency
|
||||||
|
* @param loadedPoints number of loaded points
|
||||||
|
*/
|
||||||
|
public void setState(long trackId, long pointId, int samplingFrequency, int loadedPoints) {
|
||||||
|
lastTrackId = trackId;
|
||||||
|
lastPointId = pointId;
|
||||||
|
lastSamplingFrequency = samplingFrequency;
|
||||||
|
numberOfLoadedPoints = loadedPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets state.
|
||||||
|
*/
|
||||||
|
public void resetState() {
|
||||||
|
setState(0L, 0L, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,18 +21,14 @@ 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.TAG;
|
||||||
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
|
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.DoubleBufferedLocationFactory;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
|
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListeners.ListenerRegistration;
|
|
||||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.hardware.GeomagneticField;
|
import android.hardware.GeomagneticField;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
@@ -60,54 +56,23 @@ public class TrackDataHub {
|
|||||||
// Overridable constants
|
// Overridable constants
|
||||||
private final int targetNumPoints;
|
private final int targetNumPoints;
|
||||||
|
|
||||||
/** Types of data that we can expose. */
|
|
||||||
public static enum ListenerDataType {
|
|
||||||
/** Listen to when the selected track changes. */
|
|
||||||
SELECTED_TRACK_CHANGED,
|
|
||||||
|
|
||||||
/** Listen to when the tracks change. */
|
|
||||||
TRACK_UPDATES,
|
|
||||||
|
|
||||||
/** Listen to when the waypoints change. */
|
|
||||||
WAYPOINT_UPDATES,
|
|
||||||
|
|
||||||
/** Listen to when the current track points change. */
|
|
||||||
POINT_UPDATES,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen to sampled-out points.
|
|
||||||
* Listening to this without listening to {@link #POINT_UPDATES}
|
|
||||||
* makes no sense and may yield unexpected results.
|
|
||||||
*/
|
|
||||||
SAMPLED_OUT_POINT_UPDATES,
|
|
||||||
|
|
||||||
/** Listen to updates to the current location. */
|
|
||||||
LOCATION_UPDATES,
|
|
||||||
|
|
||||||
/** Listen to updates to the current heading. */
|
|
||||||
COMPASS_UPDATES,
|
|
||||||
|
|
||||||
/** Listens to changes in display preferences. */
|
|
||||||
DISPLAY_PREFERENCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Listener which receives events from the system. */
|
/** Listener which receives events from the system. */
|
||||||
private class HubDataSourceListener implements DataSourceListener {
|
private class HubDataSourceListener implements DataSourceListener {
|
||||||
@Override
|
@Override
|
||||||
public void notifyTrackUpdated() {
|
public void notifyTracksTableUpdated() {
|
||||||
TrackDataHub.this.notifyTrackUpdated(getListenersFor(ListenerDataType.TRACK_UPDATES));
|
TrackDataHub.this.notifyTrackUpdated(getListenersFor(TrackDataType.TRACKS_TABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyWaypointUpdated() {
|
public void notifyWaypointsTableUpdated() {
|
||||||
TrackDataHub.this.notifyWaypointUpdated(getListenersFor(ListenerDataType.WAYPOINT_UPDATES));
|
TrackDataHub.this.notifyWaypointUpdated(getListenersFor(TrackDataType.WAYPOINTS_TABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyPointsUpdated() {
|
public void notifyTrackPointsTableUpdated() {
|
||||||
TrackDataHub.this.notifyPointsUpdated(true, 0, 0,
|
TrackDataHub.this.notifyPointsUpdated(true, 0, 0,
|
||||||
getListenersFor(ListenerDataType.POINT_UPDATES),
|
getListenersFor(TrackDataType.TRACK_POINTS_TABLE),
|
||||||
getListenersFor(ListenerDataType.SAMPLED_OUT_POINT_UPDATES));
|
getListenersFor(TrackDataType.SAMPLED_OUT_TRACK_POINTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,21 +95,20 @@ public class TrackDataHub {
|
|||||||
@Override
|
@Override
|
||||||
public void notifyLocationChanged(Location loc) {
|
public void notifyLocationChanged(Location loc) {
|
||||||
TrackDataHub.this.notifyLocationChanged(loc,
|
TrackDataHub.this.notifyLocationChanged(loc,
|
||||||
getListenersFor(ListenerDataType.LOCATION_UPDATES));
|
getListenersFor(TrackDataType.LOCATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyHeadingChanged(float heading) {
|
public void notifyHeadingChanged(float heading) {
|
||||||
lastSeenMagneticHeading = heading;
|
lastSeenMagneticHeading = heading;
|
||||||
maybeUpdateDeclination();
|
maybeUpdateDeclination();
|
||||||
TrackDataHub.this.notifyHeadingChanged(getListenersFor(ListenerDataType.COMPASS_UPDATES));
|
TrackDataHub.this.notifyHeadingChanged(getListenersFor(TrackDataType.COMPASS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Application services
|
// Application services
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final MyTracksProviderUtils providerUtils;
|
private final MyTracksProviderUtils providerUtils;
|
||||||
private final SharedPreferences preferences;
|
|
||||||
|
|
||||||
// Get content notifications on the main thread, send listener callbacks in another.
|
// Get content notifications on the main thread, send listener callbacks in another.
|
||||||
// This ensures listener calls are serialized.
|
// This ensures listener calls are serialized.
|
||||||
@@ -152,12 +116,9 @@ public class TrackDataHub {
|
|||||||
private Handler listenerHandler;
|
private Handler listenerHandler;
|
||||||
|
|
||||||
/** Manager for external listeners (those from activities). */
|
/** Manager for external listeners (those from activities). */
|
||||||
private final TrackDataListeners dataListeners;
|
private final TrackDataManager trackDataManager;
|
||||||
|
|
||||||
/** Wrapper for interacting with system data managers. */
|
private DataSource dataSource;
|
||||||
private DataSourcesWrapper dataSources;
|
|
||||||
|
|
||||||
/** Manager for system data listener registrations. */
|
|
||||||
private DataSourceManager dataSourceManager;
|
private DataSourceManager dataSourceManager;
|
||||||
|
|
||||||
/** Condensed listener for system data listener events. */
|
/** Condensed listener for system data listener events. */
|
||||||
@@ -193,24 +154,19 @@ public class TrackDataHub {
|
|||||||
* Builds a new {@link TrackDataHub} instance.
|
* Builds a new {@link TrackDataHub} instance.
|
||||||
*/
|
*/
|
||||||
public synchronized static TrackDataHub newInstance(Context context) {
|
public synchronized static TrackDataHub newInstance(Context context) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(
|
|
||||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
|
||||||
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
|
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||||
return new TrackDataHub(context,
|
return new TrackDataHub(
|
||||||
new TrackDataListeners(),
|
context, new TrackDataManager(), providerUtils, TARGET_DISPLAYED_TRACK_POINTS);
|
||||||
preferences, providerUtils,
|
|
||||||
TARGET_DISPLAYED_TRACK_POINTS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection constructor.
|
* Injection constructor.
|
||||||
*/
|
*/
|
||||||
// @VisibleForTesting
|
// @VisibleForTesting
|
||||||
TrackDataHub(Context ctx, TrackDataListeners listeners, SharedPreferences preferences,
|
TrackDataHub(Context ctx, TrackDataManager trackDataManager, MyTracksProviderUtils providerUtils,
|
||||||
MyTracksProviderUtils providerUtils, int targetNumPoints) {
|
int targetNumPoints) {
|
||||||
this.context = ctx;
|
this.context = ctx;
|
||||||
this.dataListeners = listeners;
|
this.trackDataManager = trackDataManager;
|
||||||
this.preferences = preferences;
|
|
||||||
this.providerUtils = providerUtils;
|
this.providerUtils = providerUtils;
|
||||||
this.targetNumPoints = targetNumPoints;
|
this.targetNumPoints = targetNumPoints;
|
||||||
this.locationFactory = new DoubleBufferedLocationFactory();
|
this.locationFactory = new DoubleBufferedLocationFactory();
|
||||||
@@ -233,12 +189,12 @@ public class TrackDataHub {
|
|||||||
listenerHandlerThread = new HandlerThread("trackDataContentThread");
|
listenerHandlerThread = new HandlerThread("trackDataContentThread");
|
||||||
listenerHandlerThread.start();
|
listenerHandlerThread.start();
|
||||||
listenerHandler = new Handler(listenerHandlerThread.getLooper());
|
listenerHandler = new Handler(listenerHandlerThread.getLooper());
|
||||||
dataSources = newDataSources();
|
dataSource = newDataSource();
|
||||||
dataSourceManager = new DataSourceManager(dataSourceListener, dataSources);
|
dataSourceManager = new DataSourceManager(dataSource, dataSourceListener);
|
||||||
|
|
||||||
// This may or may not register internal listeners, depending on whether
|
// This may or may not register internal listeners, depending on whether
|
||||||
// we already had external listeners.
|
// we already had external listeners.
|
||||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||||
loadSharedPreferences();
|
loadSharedPreferences();
|
||||||
|
|
||||||
// If there were listeners already registered, make sure they become up-to-date.
|
// If there were listeners already registered, make sure they become up-to-date.
|
||||||
@@ -246,8 +202,8 @@ public class TrackDataHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @VisibleForTesting
|
// @VisibleForTesting
|
||||||
protected DataSourcesWrapper newDataSources() {
|
protected DataSource newDataSource() {
|
||||||
return new DataSourcesWrapperImpl(context, preferences);
|
return new DataSource(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -267,7 +223,7 @@ public class TrackDataHub {
|
|||||||
|
|
||||||
started = false;
|
started = false;
|
||||||
|
|
||||||
dataSources = null;
|
dataSource = null;
|
||||||
dataSourceManager = null;
|
dataSourceManager = null;
|
||||||
listenerHandlerThread = null;
|
listenerHandlerThread = null;
|
||||||
listenerHandler = null;
|
listenerHandler = null;
|
||||||
@@ -343,9 +299,9 @@ public class TrackDataHub {
|
|||||||
}
|
}
|
||||||
Log.i(TAG, "Forcing location update");
|
Log.i(TAG, "Forcing location update");
|
||||||
|
|
||||||
Location loc = dataSources.getLastKnownLocation();
|
Location loc = dataSource.getLastKnownLocation();
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
notifyLocationChanged(loc, getListenersFor(ListenerDataType.LOCATION_UPDATES));
|
notifyLocationChanged(loc, getListenersFor(TrackDataType.LOCATION));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,30 +371,31 @@ public class TrackDataHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void registerTrackDataListener(
|
public void registerTrackDataListener(
|
||||||
TrackDataListener listener, EnumSet<ListenerDataType> dataTypes) {
|
TrackDataListener listener, EnumSet<TrackDataType> dataTypes) {
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
ListenerRegistration registration =
|
ListenerState listenerState = trackDataManager.registerListener(listener, dataTypes);
|
||||||
dataListeners.registerTrackDataListener(listener, dataTypes);
|
|
||||||
|
|
||||||
// Don't load any data or start internal listeners if start() hasn't been
|
// Don't load any data or start internal listeners if start() hasn't been
|
||||||
// called. When it is called, we'll do both things.
|
// called. When it is called, we'll do both things.
|
||||||
if (!isStarted()) return;
|
if (!isStarted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loadNewDataForListener(registration);
|
loadNewDataForListener(listenerState);
|
||||||
|
|
||||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterTrackDataListener(TrackDataListener listener) {
|
public void unregisterTrackDataListener(TrackDataListener listener) {
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
dataListeners.unregisterTrackDataListener(listener);
|
trackDataManager.unregisterListener(listener);
|
||||||
|
|
||||||
// Don't load any data or start internal listeners if start() hasn't been
|
// Don't load any data or start internal listeners if start() hasn't been
|
||||||
// called. When it is called, we'll do both things.
|
// called. When it is called, we'll do both things.
|
||||||
if (!isStarted()) return;
|
if (!isStarted()) return;
|
||||||
|
|
||||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
dataSourceManager.updateListeners(getNeededListenerTypes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,33 +403,32 @@ public class TrackDataHub {
|
|||||||
* Reloads all track data received so far into the specified listeners.
|
* Reloads all track data received so far into the specified listeners.
|
||||||
*/
|
*/
|
||||||
public void reloadDataForListener(TrackDataListener listener) {
|
public void reloadDataForListener(TrackDataListener listener) {
|
||||||
ListenerRegistration registration;
|
synchronized (trackDataManager) {
|
||||||
synchronized (dataListeners) {
|
ListenerState listenerState = trackDataManager.getListenerState(listener);
|
||||||
registration = dataListeners.getRegistration(listener);
|
listenerState.resetState();
|
||||||
registration.resetState();
|
loadNewDataForListener(listenerState);
|
||||||
loadNewDataForListener(registration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads all track data received so far into the specified listeners.
|
* Reloads all track data received so far into the specified listeners.
|
||||||
*
|
*
|
||||||
* Assumes it's called from a block that synchronizes on {@link #dataListeners}.
|
* Assumes it's called from a block that synchronizes on {@link #trackDataManager}.
|
||||||
*/
|
*/
|
||||||
private void loadNewDataForListener(final ListenerRegistration registration) {
|
private void loadNewDataForListener(final ListenerState listenerState) {
|
||||||
if (!isStarted()) {
|
if (!isStarted()) {
|
||||||
Log.w(TAG, "Not started, not reloading");
|
Log.w(TAG, "Not started, not reloading");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (registration == null) {
|
if (listenerState == null) {
|
||||||
Log.w(TAG, "Not reloading for null registration");
|
Log.w(TAG, "Not reloading for null listener state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a listener happens to be added after this method but before the Runnable below is
|
// If a listener happens to be added after this method but before the Runnable below is
|
||||||
// executed, it will have triggered a separate call to load data only up to the point this
|
// executed, it will have triggered a separate call to load data only up to the point this
|
||||||
// listener got to. This is ensured by being synchronized on listeners.
|
// listener got to. This is ensured by being synchronized on listeners.
|
||||||
final boolean isOnlyListener = (dataListeners.getNumListeners() == 1);
|
final boolean isOnlyListener = (trackDataManager.getNumberOfListeners() == 1);
|
||||||
|
|
||||||
runInListenerThread(new Runnable() {
|
runInListenerThread(new Runnable() {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -480,30 +436,31 @@ public class TrackDataHub {
|
|||||||
public void run() {
|
public void run() {
|
||||||
// Reload everything if either it's a different track, or the track has been resampled
|
// Reload everything if either it's a different track, or the track has been resampled
|
||||||
// (this also covers the case of a new registration).
|
// (this also covers the case of a new registration).
|
||||||
boolean reloadAll = registration.lastTrackId != selectedTrackId ||
|
boolean reloadAll = listenerState.getLastTrackId() != selectedTrackId ||
|
||||||
registration.lastSamplingFrequency != lastSamplingFrequency;
|
listenerState.getLastSamplingFrequency() != lastSamplingFrequency;
|
||||||
Log.d(TAG, "Doing a " + (reloadAll ? "full" : "partial") + " reload for " + registration);
|
Log.d(TAG, "Doing a " + (reloadAll ? "full" : "partial") + " reload for " + listenerState);
|
||||||
|
|
||||||
TrackDataListener listener = registration.listener;
|
TrackDataListener listener = listenerState.getTrackDataListener();
|
||||||
Set<TrackDataListener> listenerSet = Collections.singleton(listener);
|
Set<TrackDataListener> listenerSet = Collections.singleton(listener);
|
||||||
|
|
||||||
if (registration.isInterestedIn(ListenerDataType.DISPLAY_PREFERENCES)) {
|
EnumSet<TrackDataType> trackDataTypes = listenerState.getTrackDataTypes();
|
||||||
|
|
||||||
|
if (trackDataTypes.contains(TrackDataType.PREFERENCE)) {
|
||||||
reloadAll |= listener.onUnitsChanged(metricUnits);
|
reloadAll |= listener.onUnitsChanged(metricUnits);
|
||||||
reloadAll |= listener.onReportSpeedChanged(reportSpeed);
|
reloadAll |= listener.onReportSpeedChanged(reportSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reloadAll && registration.isInterestedIn(ListenerDataType.SELECTED_TRACK_CHANGED)) {
|
if (reloadAll && trackDataTypes.contains(TrackDataType.SELECTED_TRACK)) {
|
||||||
notifySelectedTrackChanged(selectedTrackId, listenerSet);
|
notifySelectedTrackChanged(selectedTrackId, listenerSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration.isInterestedIn(ListenerDataType.TRACK_UPDATES)) {
|
if (trackDataTypes.contains(TrackDataType.TRACKS_TABLE)) {
|
||||||
notifyTrackUpdated(listenerSet);
|
notifyTrackUpdated(listenerSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean interestedInPoints =
|
boolean interestedInPoints = trackDataTypes.contains(TrackDataType.TRACK_POINTS_TABLE);
|
||||||
registration.isInterestedIn(ListenerDataType.POINT_UPDATES);
|
boolean interestedInSampledOutPoints = trackDataTypes.contains(
|
||||||
boolean interestedInSampledOutPoints =
|
TrackDataType.SAMPLED_OUT_TRACK_POINTS);
|
||||||
registration.isInterestedIn(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
|
||||||
if (interestedInPoints || interestedInSampledOutPoints) {
|
if (interestedInPoints || interestedInSampledOutPoints) {
|
||||||
long minPointId = 0;
|
long minPointId = 0;
|
||||||
int previousNumPoints = 0;
|
int previousNumPoints = 0;
|
||||||
@@ -513,8 +470,8 @@ public class TrackDataHub {
|
|||||||
notifyPointsCleared(listenerSet);
|
notifyPointsCleared(listenerSet);
|
||||||
} else {
|
} else {
|
||||||
// Send only new points
|
// Send only new points
|
||||||
minPointId = registration.lastPointId + 1;
|
minPointId = listenerState.getLastPointId() + 1;
|
||||||
previousNumPoints = registration.numLoadedPoints;
|
previousNumPoints = listenerState.getNumberOfLoadedPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the only listener we have registered, keep the state that we serve to it as
|
// If this is the only listener we have registered, keep the state that we serve to it as
|
||||||
@@ -530,11 +487,11 @@ public class TrackDataHub {
|
|||||||
interestedInSampledOutPoints ? listenerSet : Collections.EMPTY_SET);
|
interestedInSampledOutPoints ? listenerSet : Collections.EMPTY_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration.isInterestedIn(ListenerDataType.WAYPOINT_UPDATES)) {
|
if (trackDataTypes.contains(TrackDataType.WAYPOINTS_TABLE)) {
|
||||||
notifyWaypointUpdated(listenerSet);
|
notifyWaypointUpdated(listenerSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration.isInterestedIn(ListenerDataType.LOCATION_UPDATES)) {
|
if (trackDataTypes.contains(TrackDataType.LOCATION)) {
|
||||||
if (lastSeenLocation != null) {
|
if (lastSeenLocation != null) {
|
||||||
notifyLocationChanged(lastSeenLocation, true, listenerSet);
|
notifyLocationChanged(lastSeenLocation, true, listenerSet);
|
||||||
} else {
|
} else {
|
||||||
@@ -542,7 +499,7 @@ public class TrackDataHub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration.isInterestedIn(ListenerDataType.COMPASS_UPDATES)) {
|
if (trackDataTypes.contains(TrackDataType.COMPASS)) {
|
||||||
notifyHeadingChanged(listenerSet);
|
notifyHeadingChanged(listenerSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -557,8 +514,8 @@ public class TrackDataHub {
|
|||||||
Log.w(TAG, "Not started, not reloading");
|
Log.w(TAG, "Not started, not reloading");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
if (!dataListeners.hasListeners()) {
|
if (trackDataManager.getNumberOfListeners() == 0) {
|
||||||
Log.d(TAG, "No listeners, not reloading");
|
Log.d(TAG, "No listeners, not reloading");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -569,33 +526,33 @@ public class TrackDataHub {
|
|||||||
public void run() {
|
public void run() {
|
||||||
// Ignore the return values here, we're already sending the full data set anyway
|
// Ignore the return values here, we're already sending the full data set anyway
|
||||||
for (TrackDataListener listener :
|
for (TrackDataListener listener :
|
||||||
getListenersFor(ListenerDataType.DISPLAY_PREFERENCES)) {
|
getListenersFor(TrackDataType.PREFERENCE)) {
|
||||||
listener.onUnitsChanged(metricUnits);
|
listener.onUnitsChanged(metricUnits);
|
||||||
listener.onReportSpeedChanged(reportSpeed);
|
listener.onReportSpeedChanged(reportSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifySelectedTrackChanged(selectedTrackId,
|
notifySelectedTrackChanged(selectedTrackId,
|
||||||
getListenersFor(ListenerDataType.SELECTED_TRACK_CHANGED));
|
getListenersFor(TrackDataType.SELECTED_TRACK));
|
||||||
|
|
||||||
notifyTrackUpdated(getListenersFor(ListenerDataType.TRACK_UPDATES));
|
notifyTrackUpdated(getListenersFor(TrackDataType.TRACKS_TABLE));
|
||||||
|
|
||||||
Set<TrackDataListener> pointListeners =
|
Set<TrackDataListener> pointListeners =
|
||||||
getListenersFor(ListenerDataType.POINT_UPDATES);
|
getListenersFor(TrackDataType.TRACK_POINTS_TABLE);
|
||||||
Set<TrackDataListener> sampledOutPointListeners =
|
Set<TrackDataListener> sampledOutPointListeners =
|
||||||
getListenersFor(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
getListenersFor(TrackDataType.SAMPLED_OUT_TRACK_POINTS);
|
||||||
notifyPointsCleared(pointListeners);
|
notifyPointsCleared(pointListeners);
|
||||||
notifyPointsUpdated(true, 0, 0, pointListeners, sampledOutPointListeners);
|
notifyPointsUpdated(true, 0, 0, pointListeners, sampledOutPointListeners);
|
||||||
|
|
||||||
notifyWaypointUpdated(getListenersFor(ListenerDataType.WAYPOINT_UPDATES));
|
notifyWaypointUpdated(getListenersFor(TrackDataType.WAYPOINTS_TABLE));
|
||||||
|
|
||||||
if (lastSeenLocation != null) {
|
if (lastSeenLocation != null) {
|
||||||
notifyLocationChanged(lastSeenLocation, true,
|
notifyLocationChanged(lastSeenLocation, true,
|
||||||
getListenersFor(ListenerDataType.LOCATION_UPDATES));
|
getListenersFor(TrackDataType.LOCATION));
|
||||||
} else {
|
} else {
|
||||||
notifyFixType();
|
notifyFixType();
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyHeadingChanged(getListenersFor(ListenerDataType.COMPASS_UPDATES));
|
notifyHeadingChanged(getListenersFor(TrackDataType.COMPASS));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -630,12 +587,12 @@ public class TrackDataHub {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Set<TrackDataListener> displayListeners =
|
Set<TrackDataListener> displayListeners =
|
||||||
getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
getListenersFor(TrackDataType.PREFERENCE);
|
||||||
|
|
||||||
for (TrackDataListener listener : displayListeners) {
|
for (TrackDataListener listener : displayListeners) {
|
||||||
// TODO: Do the reloading just once for all interested listeners
|
// TODO: Do the reloading just once for all interested listeners
|
||||||
if (listener.onReportSpeedChanged(reportSpeed)) {
|
if (listener.onReportSpeedChanged(reportSpeed)) {
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
reloadDataForListener(listener);
|
reloadDataForListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,11 +608,11 @@ public class TrackDataHub {
|
|||||||
runInListenerThread(new Runnable() {
|
runInListenerThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Set<TrackDataListener> displayListeners = getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
Set<TrackDataListener> displayListeners = getListenersFor(TrackDataType.PREFERENCE);
|
||||||
|
|
||||||
for (TrackDataListener listener : displayListeners) {
|
for (TrackDataListener listener : displayListeners) {
|
||||||
if (listener.onUnitsChanged(metricUnits)) {
|
if (listener.onUnitsChanged(metricUnits)) {
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
reloadDataForListener(listener);
|
reloadDataForListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,7 +640,7 @@ public class TrackDataHub {
|
|||||||
// Notify to everyone.
|
// Notify to everyone.
|
||||||
Log.d(TAG, "Notifying fix type: " + state);
|
Log.d(TAG, "Notifying fix type: " + state);
|
||||||
for (TrackDataListener listener :
|
for (TrackDataListener listener :
|
||||||
getListenersFor(ListenerDataType.LOCATION_UPDATES)) {
|
getListenersFor(TrackDataType.LOCATION)) {
|
||||||
listener.onProviderStateChange(state);
|
listener.onProviderStateChange(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -945,9 +902,9 @@ public class TrackDataHub {
|
|||||||
|
|
||||||
Log.i(TAG, "Resampling point set after " + numLoadedPoints + " points.");
|
Log.i(TAG, "Resampling point set after " + numLoadedPoints + " points.");
|
||||||
resetState();
|
resetState();
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
sampledListeners = getListenersFor(ListenerDataType.POINT_UPDATES);
|
sampledListeners = getListenersFor(TrackDataType.TRACK_POINTS_TABLE);
|
||||||
sampledOutListeners = getListenersFor(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
sampledOutListeners = getListenersFor(TrackDataType.SAMPLED_OUT_TRACK_POINTS);
|
||||||
}
|
}
|
||||||
maxPointId = -1;
|
maxPointId = -1;
|
||||||
minPointId = 0;
|
minPointId = 0;
|
||||||
@@ -1030,12 +987,10 @@ public class TrackDataHub {
|
|||||||
listener.onNewTrackPointsDone();
|
listener.onNewTrackPointsDone();
|
||||||
|
|
||||||
// Update the listener state
|
// Update the listener state
|
||||||
ListenerRegistration registration = dataListeners.getRegistration(listener);
|
ListenerState listenerState = trackDataManager.getListenerState(listener);
|
||||||
if (registration != null) {
|
if (listenerState != null) {
|
||||||
registration.lastTrackId = currentSelectedTrackId;
|
listenerState.setState(currentSelectedTrackId, localLastSeenLocationId,
|
||||||
registration.lastPointId = localLastSeenLocationId;
|
pointSamplingFrequency, localNumLoadedPoints);
|
||||||
registration.lastSamplingFrequency = pointSamplingFrequency;
|
|
||||||
registration.numLoadedPoints = localNumLoadedPoints;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1089,17 +1044,17 @@ public class TrackDataHub {
|
|||||||
listenerHandler.post(runnable);
|
listenerHandler.post(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<TrackDataListener> getListenersFor(ListenerDataType type) {
|
private Set<TrackDataListener> getListenersFor(TrackDataType type) {
|
||||||
synchronized (dataListeners) {
|
synchronized (trackDataManager) {
|
||||||
return dataListeners.getListenersFor(type);
|
return trackDataManager.getListeners(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EnumSet<ListenerDataType> getNeededListenerTypes() {
|
private EnumSet<TrackDataType> getNeededListenerTypes() {
|
||||||
EnumSet<ListenerDataType> neededTypes = dataListeners.getAllRegisteredTypes();
|
EnumSet<TrackDataType> neededTypes = trackDataManager.getRegisteredTrackDataTypes();
|
||||||
|
|
||||||
// We always want preference updates.
|
// We always want preference updates.
|
||||||
neededTypes.add(ListenerDataType.DISPLAY_PREFERENCES);
|
neededTypes.add(TrackDataType.PREFERENCE);
|
||||||
|
|
||||||
return neededTypes;
|
return neededTypes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,159 +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.TAG;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manager for the external data listeners and their listening types.
|
|
||||||
*
|
|
||||||
* @author Rodrigo Damazio
|
|
||||||
*/
|
|
||||||
class TrackDataListeners {
|
|
||||||
|
|
||||||
/** Internal representation of a listener's registration. */
|
|
||||||
static class ListenerRegistration {
|
|
||||||
final TrackDataListener listener;
|
|
||||||
final EnumSet<ListenerDataType> types;
|
|
||||||
|
|
||||||
// State that was last notified to the listener, for resuming after a pause.
|
|
||||||
long lastTrackId;
|
|
||||||
long lastPointId;
|
|
||||||
int lastSamplingFrequency;
|
|
||||||
int numLoadedPoints;
|
|
||||||
|
|
||||||
public ListenerRegistration(TrackDataListener listener,
|
|
||||||
EnumSet<ListenerDataType> types) {
|
|
||||||
this.listener = listener;
|
|
||||||
this.types = types;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInterestedIn(ListenerDataType type) {
|
|
||||||
return types.contains(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetState() {
|
|
||||||
lastTrackId = 0L;
|
|
||||||
lastPointId = 0L;
|
|
||||||
lastSamplingFrequency = 0;
|
|
||||||
numLoadedPoints = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ListenerRegistration [listener=" + listener + ", types=" + types
|
|
||||||
+ ", lastTrackId=" + lastTrackId + ", lastPointId=" + lastPointId
|
|
||||||
+ ", lastSamplingFrequency=" + lastSamplingFrequency
|
|
||||||
+ ", numLoadedPoints=" + numLoadedPoints + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Map of external listener to its registration details. */
|
|
||||||
private final Map<TrackDataListener, ListenerRegistration> registeredListeners =
|
|
||||||
new HashMap<TrackDataListener, ListenerRegistration>();
|
|
||||||
|
|
||||||
/** Map of data type to external listeners interested in it. */
|
|
||||||
private final Map<ListenerDataType, Set<TrackDataListener>> listenerSetsPerType =
|
|
||||||
new EnumMap<ListenerDataType, Set<TrackDataListener>>(ListenerDataType.class);
|
|
||||||
|
|
||||||
public TrackDataListeners() {
|
|
||||||
// Create sets for all data types at startup.
|
|
||||||
for (ListenerDataType type : ListenerDataType.values()) {
|
|
||||||
listenerSetsPerType.put(type, new LinkedHashSet<TrackDataListener>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a listener to send data to.
|
|
||||||
* It is ok to call this method before {@link TrackDataHub#start}, and in that case
|
|
||||||
* the data will only be passed to listeners when {@link TrackDataHub#start} is called.
|
|
||||||
*
|
|
||||||
* @param listener the listener to register
|
|
||||||
* @param dataTypes the type of data that the listener is interested in
|
|
||||||
*/
|
|
||||||
public ListenerRegistration registerTrackDataListener(final TrackDataListener listener, EnumSet<ListenerDataType> dataTypes) {
|
|
||||||
Log.d(TAG, "Registered track data listener: " + listener);
|
|
||||||
if (registeredListeners.containsKey(listener)) {
|
|
||||||
throw new IllegalStateException("Listener already registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
ListenerRegistration registration = new ListenerRegistration(listener, dataTypes);
|
|
||||||
registeredListeners.put(listener, registration);
|
|
||||||
|
|
||||||
for (ListenerDataType type : dataTypes) {
|
|
||||||
// This is guaranteed not to be null.
|
|
||||||
Set<TrackDataListener> typeSet = listenerSetsPerType.get(type);
|
|
||||||
typeSet.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
return registration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters a listener to send data to.
|
|
||||||
*
|
|
||||||
* @param listener the listener to unregister
|
|
||||||
*/
|
|
||||||
public void unregisterTrackDataListener(TrackDataListener listener) {
|
|
||||||
Log.d(TAG, "Unregistered track data listener: " + listener);
|
|
||||||
// Remove and keep the corresponding registration.
|
|
||||||
ListenerRegistration match = registeredListeners.remove(listener);
|
|
||||||
if (match == null) {
|
|
||||||
Log.w(TAG, "Tried to unregister listener which is not registered.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove it from the per-type sets
|
|
||||||
for (ListenerDataType type : match.types) {
|
|
||||||
listenerSetsPerType.get(type).remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenerRegistration getRegistration(TrackDataListener listener) {
|
|
||||||
return registeredListeners.get(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<TrackDataListener> getListenersFor(ListenerDataType type) {
|
|
||||||
return listenerSetsPerType.get(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumSet<ListenerDataType> getAllRegisteredTypes() {
|
|
||||||
EnumSet<ListenerDataType> listeners = EnumSet.noneOf(ListenerDataType.class);
|
|
||||||
for (ListenerRegistration registration : this.registeredListeners.values()) {
|
|
||||||
listeners.addAll(registration.types);
|
|
||||||
}
|
|
||||||
return listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasListeners() {
|
|
||||||
return !registeredListeners.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumListeners() {
|
|
||||||
return registeredListeners.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages register/unregister {@link TrackDataListener} and keeping the state
|
||||||
|
* for each registered listener.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class TrackDataManager {
|
||||||
|
|
||||||
|
// Map of listener to its state
|
||||||
|
private final Map<TrackDataListener, ListenerState>
|
||||||
|
listenerToStateMap = new HashMap<TrackDataListener, ListenerState>();
|
||||||
|
|
||||||
|
// Map of track data type to listeners
|
||||||
|
private final Map<TrackDataType, Set<TrackDataListener>>
|
||||||
|
typeToListenersMap = new EnumMap<TrackDataType, Set<TrackDataListener>>(TrackDataType.class);
|
||||||
|
|
||||||
|
public TrackDataManager() {
|
||||||
|
for (TrackDataType trackDataType : TrackDataType.values()) {
|
||||||
|
typeToListenersMap.put(trackDataType, new LinkedHashSet<TrackDataListener>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a listener.
|
||||||
|
*
|
||||||
|
* @param listener the listener
|
||||||
|
* @param trackDataTypes the track data types the listener is interested
|
||||||
|
*/
|
||||||
|
public ListenerState registerListener(
|
||||||
|
TrackDataListener listener, EnumSet<TrackDataType> trackDataTypes) {
|
||||||
|
if (listenerToStateMap.containsKey(listener)) {
|
||||||
|
throw new IllegalStateException("Listener is already registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
ListenerState listenerState = new ListenerState(listener, trackDataTypes);
|
||||||
|
listenerToStateMap.put(listener, listenerState);
|
||||||
|
|
||||||
|
for (TrackDataType trackDataType : trackDataTypes) {
|
||||||
|
typeToListenersMap.get(trackDataType).add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
return listenerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a listener.
|
||||||
|
*
|
||||||
|
* @param listener the listener
|
||||||
|
*/
|
||||||
|
public void unregisterListener(TrackDataListener listener) {
|
||||||
|
ListenerState removed = listenerToStateMap.remove(listener);
|
||||||
|
if (removed == null) {
|
||||||
|
Log.w(TAG, "Tried to unregister a listener that is not registered.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the listener from the typeToListenersMap
|
||||||
|
for (TrackDataType trackDataType : removed.getTrackDataTypes()) {
|
||||||
|
typeToListenersMap.get(trackDataType).remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of {@link TrackDataListener}.
|
||||||
|
*/
|
||||||
|
public int getNumberOfListeners() {
|
||||||
|
return listenerToStateMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the track listener state.
|
||||||
|
*
|
||||||
|
* @param listener the listener
|
||||||
|
*/
|
||||||
|
public ListenerState getListenerState(TrackDataListener listener) {
|
||||||
|
return listenerToStateMap.get(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the listeners for a {@link TrackDataType}.
|
||||||
|
*
|
||||||
|
* @param type the type
|
||||||
|
*/
|
||||||
|
public Set<TrackDataListener> getListeners(TrackDataType type) {
|
||||||
|
return typeToListenersMap.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the registered {@link TrackDataType}.
|
||||||
|
*/
|
||||||
|
public EnumSet<TrackDataType> getRegisteredTrackDataTypes() {
|
||||||
|
EnumSet<TrackDataType> types = EnumSet.noneOf(TrackDataType.class);
|
||||||
|
for (ListenerState registration : this.listenerToStateMap.values()) {
|
||||||
|
types.addAll(registration.getTrackDataTypes());
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of track data.
|
||||||
|
*
|
||||||
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
public enum TrackDataType {
|
||||||
|
|
||||||
|
SELECTED_TRACK, // selected track changes
|
||||||
|
TRACKS_TABLE, // tracks table changes
|
||||||
|
WAYPOINTS_TABLE, // waypoints table changes
|
||||||
|
TRACK_POINTS_TABLE, // track points table changes
|
||||||
|
SAMPLED_OUT_TRACK_POINTS, // sampled-out track points changes
|
||||||
|
LOCATION, // location changes
|
||||||
|
COMPASS, // compass changes
|
||||||
|
PREFERENCE; // preference changes
|
||||||
|
}
|
||||||
@@ -19,12 +19,12 @@ package com.google.android.apps.mytracks.fragments;
|
|||||||
import com.google.android.apps.mytracks.ChartView;
|
import com.google.android.apps.mytracks.ChartView;
|
||||||
import com.google.android.apps.mytracks.Constants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataType;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
import com.google.android.apps.mytracks.content.Sensor;
|
||||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||||
@@ -360,12 +360,12 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
private synchronized void resumeTrackDataHub() {
|
private synchronized void resumeTrackDataHub() {
|
||||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
TrackDataType.SELECTED_TRACK,
|
||||||
ListenerDataType.TRACK_UPDATES,
|
TrackDataType.TRACKS_TABLE,
|
||||||
ListenerDataType.WAYPOINT_UPDATES,
|
TrackDataType.WAYPOINTS_TABLE,
|
||||||
ListenerDataType.POINT_UPDATES,
|
TrackDataType.TRACK_POINTS_TABLE,
|
||||||
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
TrackDataType.SAMPLED_OUT_TRACK_POINTS,
|
||||||
ListenerDataType.DISPLAY_PREFERENCES));
|
TrackDataType.PREFERENCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ package com.google.android.apps.mytracks.fragments;
|
|||||||
import com.google.android.apps.mytracks.MapOverlay;
|
import com.google.android.apps.mytracks.MapOverlay;
|
||||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataType;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||||
@@ -420,11 +420,11 @@ public class MapFragment extends Fragment
|
|||||||
private synchronized void resumeTrackDataHub() {
|
private synchronized void resumeTrackDataHub() {
|
||||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
TrackDataType.SELECTED_TRACK,
|
||||||
ListenerDataType.WAYPOINT_UPDATES,
|
TrackDataType.WAYPOINTS_TABLE,
|
||||||
ListenerDataType.POINT_UPDATES,
|
TrackDataType.TRACK_POINTS_TABLE,
|
||||||
ListenerDataType.LOCATION_UPDATES,
|
TrackDataType.LOCATION,
|
||||||
ListenerDataType.COMPASS_UPDATES));
|
TrackDataType.COMPASS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
package com.google.android.apps.mytracks.fragments;
|
package com.google.android.apps.mytracks.fragments;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||||
|
import com.google.android.apps.mytracks.content.TrackDataType;
|
||||||
import com.google.android.apps.mytracks.content.Track;
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||||
@@ -257,10 +257,10 @@ public class StatsFragment extends Fragment implements TrackDataListener {
|
|||||||
private synchronized void resumeTrackDataHub() {
|
private synchronized void resumeTrackDataHub() {
|
||||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
TrackDataType.SELECTED_TRACK,
|
||||||
ListenerDataType.TRACK_UPDATES,
|
TrackDataType.TRACKS_TABLE,
|
||||||
ListenerDataType.LOCATION_UPDATES,
|
TrackDataType.LOCATION,
|
||||||
ListenerDataType.DISPLAY_PREFERENCES));
|
TrackDataType.PREFERENCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,23 +15,21 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.content;
|
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.capture;
|
||||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
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.expect;
|
||||||
import static com.google.android.testing.mocking.AndroidMock.isA;
|
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.leq;
|
||||||
import static com.google.android.testing.mocking.AndroidMock.same;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
|
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
|
||||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
import com.google.android.testing.mocking.AndroidMock;
|
import com.google.android.testing.mocking.AndroidMock;
|
||||||
|
import com.google.android.testing.mocking.UsesMocks;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -69,8 +67,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
private MyTracksProviderUtils providerUtils;
|
private MyTracksProviderUtils providerUtils;
|
||||||
private TrackDataHub hub;
|
private TrackDataHub hub;
|
||||||
private TrackDataListeners listeners;
|
private TrackDataManager trackDataManager;
|
||||||
private DataSourcesWrapper dataSources;
|
private DataSource dataSource;
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private TrackDataListener listener1;
|
private TrackDataListener listener1;
|
||||||
private TrackDataListener listener2;
|
private TrackDataListener listener2;
|
||||||
@@ -79,6 +77,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
private MockContext context;
|
private MockContext context;
|
||||||
private float declination;
|
private float declination;
|
||||||
|
|
||||||
|
@UsesMocks({MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class})
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
@@ -90,13 +89,13 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||||
providerUtils = AndroidMock.createMock("providerUtils", MyTracksProviderUtils.class);
|
providerUtils = AndroidMock.createMock("providerUtils", MyTracksProviderUtils.class);
|
||||||
dataSources = AndroidMock.createNiceMock("dataSources", DataSourcesWrapper.class);
|
dataSource = AndroidMock.createMock("dataSource", DataSource.class, context);
|
||||||
|
|
||||||
listeners = new TrackDataListeners();
|
trackDataManager = new TrackDataManager();
|
||||||
hub = new TrackDataHub(context, listeners, sharedPreferences, providerUtils, TARGET_POINTS) {
|
hub = new TrackDataHub(context, trackDataManager, providerUtils, TARGET_POINTS) {
|
||||||
@Override
|
@Override
|
||||||
protected DataSourcesWrapper newDataSources() {
|
protected DataSource newDataSource() {
|
||||||
return dataSources;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,18 +118,18 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
AndroidMock.reset(dataSources);
|
AndroidMock.reset(dataSource);
|
||||||
|
|
||||||
// Expect everything to be unregistered.
|
// Expect everything to be unregistered.
|
||||||
if (preferenceListenerCapture.hasCaptured()) {
|
if (preferenceListenerCapture.hasCaptured()) {
|
||||||
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListenerCapture.getValue());
|
dataSource.unregisterOnSharedPreferenceChangeListener(preferenceListenerCapture.getValue());
|
||||||
}
|
}
|
||||||
dataSources.removeLocationUpdates(isA(LocationListener.class));
|
dataSource.unregisterLocationListener(isA(LocationListener.class));
|
||||||
dataSources.unregisterSensorListener(isA(SensorEventListener.class));
|
dataSource.unregisterCompassListener(isA(SensorEventListener.class));
|
||||||
dataSources.unregisterContentObserver(isA(ContentObserver.class));
|
dataSource.unregisterContentObserver(isA(ContentObserver.class));
|
||||||
AndroidMock.expectLastCall().times(3);
|
AndroidMock.expectLastCall().times(3);
|
||||||
|
|
||||||
AndroidMock.replay(dataSources);
|
AndroidMock.replay(dataSource);
|
||||||
|
|
||||||
hub.stop();
|
hub.stop();
|
||||||
hub = null;
|
hub = null;
|
||||||
@@ -143,8 +142,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture));
|
||||||
eq(TracksColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
|
||||||
|
|
||||||
// Expect the initial loading.
|
// Expect the initial loading.
|
||||||
// Both listeners (registered before and after start) should get the same data.
|
// Both listeners (registered before and after start) should get the same data.
|
||||||
@@ -153,9 +151,9 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.TRACK_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.TRACK_UPDATES));
|
hub.registerTrackDataListener(listener2, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -185,7 +183,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Unregister the other, expect internal unregistration
|
// Unregister the other, expect internal unregistration
|
||||||
dataSources.unregisterContentObserver(observer);
|
dataSource.unregisterContentObserver(observer);
|
||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
@@ -321,8 +319,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
.andReturn(wpt2);
|
.andReturn(wpt2);
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
eq(WaypointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
|
||||||
|
|
||||||
// Expect the initial loading.
|
// Expect the initial loading.
|
||||||
// Both listeners (registered before and after start) should get the same data.
|
// Both listeners (registered before and after start) should get the same data.
|
||||||
@@ -337,9 +334,9 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.WAYPOINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.WAYPOINT_UPDATES));
|
hub.registerTrackDataListener(listener2, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -398,7 +395,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Unregister the other, expect internal unregistration
|
// Unregister the other, expect internal unregistration
|
||||||
dataSources.unregisterContentObserver(observer);
|
dataSource.unregisterContentObserver(observer);
|
||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
@@ -412,8 +409,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -428,7 +425,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -446,7 +443,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener2, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -497,8 +494,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -513,13 +510,13 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Unregister
|
// Unregister
|
||||||
ContentObserver observer = observerCapture.getValue();
|
ContentObserver observer = observerCapture.getValue();
|
||||||
dataSources.unregisterContentObserver(observer);
|
dataSource.unregisterContentObserver(observer);
|
||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
@@ -528,8 +525,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Register again, except only points since unregistered.
|
// Register again, except only points since unregistered.
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -543,7 +540,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
}
|
}
|
||||||
@@ -552,8 +549,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -568,13 +565,13 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Unregister
|
// Unregister
|
||||||
ContentObserver observer = observerCapture.getValue();
|
ContentObserver observer = observerCapture.getValue();
|
||||||
dataSources.unregisterContentObserver(observer);
|
dataSource.unregisterContentObserver(observer);
|
||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
@@ -583,8 +580,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
// Register again after track changed, expect all points.
|
// Register again after track changed, expect all points.
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
locationIterator = new FixedSizeLocationIterator(1, 10);
|
locationIterator = new FixedSizeLocationIterator(1, 10);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -599,7 +596,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.loadTrack(TRACK_ID + 1);
|
hub.loadTrack(TRACK_ID + 1);
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
}
|
}
|
||||||
@@ -608,8 +605,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 200, 4, 25, 71, 120);
|
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 200, 4, 25, 71, 120);
|
||||||
expect(providerUtils.getLocationIterator(
|
expect(providerUtils.getLocationIterator(
|
||||||
@@ -627,9 +624,9 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1,
|
hub.registerTrackDataListener(listener1,
|
||||||
EnumSet.of(ListenerDataType.POINT_UPDATES));
|
EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
hub.registerTrackDataListener(listener2,
|
hub.registerTrackDataListener(listener2,
|
||||||
EnumSet.of(ListenerDataType.POINT_UPDATES, ListenerDataType.SAMPLED_OUT_POINT_UPDATES));
|
EnumSet.of(TrackDataType.TRACK_POINTS_TABLE, TrackDataType.SAMPLED_OUT_TRACK_POINTS));
|
||||||
hub.start();
|
hub.start();
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
@@ -639,8 +636,8 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||||
|
|
||||||
expectStart();
|
expectStart();
|
||||||
dataSources.registerContentObserver(
|
dataSource.registerContentObserver(
|
||||||
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
|
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||||
|
|
||||||
// Deliver 30 points (no sampling happens)
|
// Deliver 30 points (no sampling happens)
|
||||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
|
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
|
||||||
@@ -656,7 +653,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.TRACK_POINTS_TABLE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -702,16 +699,14 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
public void testCompassListen() throws Exception {
|
public void testCompassListen() throws Exception {
|
||||||
AndroidMock.resetToDefault(listener1);
|
AndroidMock.resetToDefault(listener1);
|
||||||
|
|
||||||
Sensor compass = newSensor();
|
expectStart();
|
||||||
expect(dataSources.getSensor(Sensor.TYPE_ORIENTATION)).andReturn(compass);
|
|
||||||
Capture<SensorEventListener> listenerCapture = new Capture<SensorEventListener>();
|
Capture<SensorEventListener> listenerCapture = new Capture<SensorEventListener>();
|
||||||
dataSources.registerSensorListener(capture(listenerCapture), same(compass), anyInt());
|
dataSource.registerCompassListener(capture(listenerCapture));
|
||||||
|
|
||||||
Capture<LocationListener> locationListenerCapture = new Capture<LocationListener>();
|
Capture<LocationListener> locationListenerCapture = new Capture<LocationListener>();
|
||||||
dataSources.requestLocationUpdates(capture(locationListenerCapture));
|
dataSource.registerLocationListener(capture(locationListenerCapture));
|
||||||
|
|
||||||
SensorEvent event = newSensorEvent();
|
SensorEvent event = newSensorEvent();
|
||||||
event.sensor = compass;
|
|
||||||
|
|
||||||
// First, get a dummy heading update.
|
// First, get a dummy heading update.
|
||||||
listener1.onCurrentHeadingChanged(0.0);
|
listener1.onCurrentHeadingChanged(0.0);
|
||||||
@@ -726,7 +721,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1,
|
hub.registerTrackDataListener(listener1,
|
||||||
EnumSet.of(ListenerDataType.COMPASS_UPDATES, ListenerDataType.LOCATION_UPDATES));
|
EnumSet.of(TrackDataType.COMPASS, TrackDataType.LOCATION));
|
||||||
hub.start();
|
hub.start();
|
||||||
|
|
||||||
SensorEventListener sensorListener = listenerCapture.getValue();
|
SensorEventListener sensorListener = listenerCapture.getValue();
|
||||||
@@ -786,9 +781,7 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
|
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
|
||||||
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
|
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
|
||||||
|
|
||||||
Capture<OnSharedPreferenceChangeListener> listenerCapture =
|
expectStart();
|
||||||
new Capture<OnSharedPreferenceChangeListener>();
|
|
||||||
dataSources.registerOnSharedPreferenceChangeListener(capture(listenerCapture));
|
|
||||||
|
|
||||||
expect(listener1.onUnitsChanged(true)).andReturn(false);
|
expect(listener1.onUnitsChanged(true)).andReturn(false);
|
||||||
expect(listener2.onUnitsChanged(true)).andReturn(false);
|
expect(listener2.onUnitsChanged(true)).andReturn(false);
|
||||||
@@ -797,9 +790,9 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
|
|
||||||
replay();
|
replay();
|
||||||
|
|
||||||
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.DISPLAY_PREFERENCES));
|
hub.registerTrackDataListener(listener1, EnumSet.of(TrackDataType.PREFERENCE));
|
||||||
hub.start();
|
hub.start();
|
||||||
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.DISPLAY_PREFERENCES));
|
hub.registerTrackDataListener(listener2, EnumSet.of(TrackDataType.PREFERENCE));
|
||||||
|
|
||||||
verifyAndReset();
|
verifyAndReset();
|
||||||
|
|
||||||
@@ -809,12 +802,12 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
replay();
|
replay();
|
||||||
|
|
||||||
PreferencesUtils.setBoolean(context, R.string.report_speed_key, false);
|
PreferencesUtils.setBoolean(context, R.string.report_speed_key, false);
|
||||||
OnSharedPreferenceChangeListener listener = listenerCapture.getValue();
|
OnSharedPreferenceChangeListener listener = preferenceListenerCapture.getValue();
|
||||||
listener.onSharedPreferenceChanged(
|
listener.onSharedPreferenceChanged(
|
||||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.report_speed_key));
|
sharedPreferences, PreferencesUtils.getKey(context, R.string.report_speed_key));
|
||||||
|
|
||||||
AndroidMock.verify(dataSources, providerUtils, listener1, listener2);
|
AndroidMock.verify(dataSource, providerUtils, listener1, listener2);
|
||||||
AndroidMock.reset(dataSources, providerUtils, listener1, listener2);
|
AndroidMock.reset(dataSource, providerUtils, listener1, listener2);
|
||||||
|
|
||||||
expect(listener1.onUnitsChanged(false)).andReturn(false);
|
expect(listener1.onUnitsChanged(false)).andReturn(false);
|
||||||
expect(listener2.onUnitsChanged(false)).andReturn(false);
|
expect(listener2.onUnitsChanged(false)).andReturn(false);
|
||||||
@@ -829,15 +822,15 @@ public class TrackDataHubTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void expectStart() {
|
private void expectStart() {
|
||||||
dataSources.registerOnSharedPreferenceChangeListener(capture(preferenceListenerCapture));
|
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceListenerCapture));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replay() {
|
private void replay() {
|
||||||
AndroidMock.replay(dataSources, providerUtils, listener1, listener2);
|
AndroidMock.replay(dataSource, providerUtils, listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyAndReset() {
|
private void verifyAndReset() {
|
||||||
AndroidMock.verify(listener1, listener2, dataSources, providerUtils);
|
AndroidMock.verify(listener1, listener2, dataSource, providerUtils);
|
||||||
AndroidMock.reset(listener1, listener2, dataSources, providerUtils);
|
AndroidMock.reset(listener1, listener2, dataSource, providerUtils);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user