Several fixes to the service and more test coverage.

Notably:
1) Fixed isRecording to not return false if service is down (for instance, it may be being restarted)
2) Added more checks to prevent from invalid starting/stopping (if in already in progress/not started).
This commit is contained in:
Bartlomiej Niechwiej
2010-10-24 14:16:43 -07:00
parent fc06701009
commit 2dc1d914c0
5 changed files with 246 additions and 50 deletions
@@ -298,13 +298,13 @@ public class ChartActivity extends Activity implements
public void onChange(boolean selfChange) {
Log.d(MyTracksConstants.TAG, "ChartActivity: ContentObserver.onChange");
// Check for any new locations and append them to the currently
// recording track:
if (!MyTracks.getInstance().isRecording()) {
// recording track.
if (recordingTrackId < 0) {
// No track is being recorded. We should not be here.
return;
}
if (selectedTrackId != recordingTrackId) {
// no track, or one other than the recording track is selected, don't
// No track, or one other than the recording track is selected, don't
// bother.
return;
}
@@ -26,9 +26,9 @@ import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.GpxImporter;
import com.google.android.apps.mytracks.io.SendToDocs;
import com.google.android.apps.mytracks.io.SendToMyMaps;
import com.google.android.apps.mytracks.io.SendToMyMaps.OnSendCompletedListener;
import com.google.android.apps.mytracks.io.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory;
import com.google.android.apps.mytracks.io.SendToMyMaps.OnSendCompletedListener;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
@@ -65,9 +65,9 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager.BadTokenException;
import android.widget.RelativeLayout;
import android.widget.TabHost;
@@ -233,20 +233,35 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
/**
* Checks whether we have a track recording session in progress.
* In some cases, when the service has crashed or has been restarted
* by the system, we fall back to the shared preferences.
*
* @return true if the activity is bound to the track recording service and
* the service is recording a track.
* the service is recording a track or in case the service is down,
* based on settings from the shared preferences.
*/
public boolean isRecording() {
if (trackRecordingService == null) {
return false;
// Fall back to alternative check method.
return isRecordingBasedOnSharedPreferences();
}
try {
return trackRecordingService.isRecording();
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "MyTracks: Remote exception.", e);
return false;
// Fall back to alternative check method.
return isRecordingBasedOnSharedPreferences();
}
}
private boolean isRecordingBasedOnSharedPreferences() {
// TrackRecordingServices guarantees that recordingTrackId is set to
// -1 if the track has been stopped.
// TODO: Refresh recordingTrackId.
return recordingTrackId >= 0;
}
/*
* Application lifetime events:
@@ -303,6 +318,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
recordingTrackId =
prefs.getLong(getString(R.string.recording_track_key), -1);
prefs.registerOnSharedPreferenceChangeListener(this);
Log.d(MyTracksConstants.TAG, "recordingTrackId: " + recordingTrackId
+ ", selectedTrackId: " + selectedTrackId);
if (recordingTrackId > 0) {
Intent startIntent = new Intent(this, TrackRecordingService.class);
startService(startIntent);
}
}
// This will show the eula until the user accepts or quits the app.
@@ -331,12 +331,7 @@ public class MyTracksMap extends MapActivity
@Override
public void onChange(boolean selfChange) {
Log.d(MyTracksConstants.TAG, "MyTracksMap: ContentObserver.onChange");
// Check for any new locations and append them to the currently
// recording track:
if (!MyTracks.getInstance().isRecording()) {
// No track is being recorded. We should not be here.
return;
}
if (!isRecordingSelected()) {
// No track, or one other than the recording track is selected,
// don't bother.
@@ -451,6 +446,10 @@ public class MyTracksMap extends MapActivity
Log.d(MyTracksConstants.TAG, "MyTracksMap.onResume");
super.onResume();
// Reload all preferences as they might have changed meanwhile.
reloadSharedPreferences(
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0), null);
// Make sure any updates that might have happened are propagated to the
// Map overlay:
observer.onChange(false);
@@ -786,7 +785,7 @@ public class MyTracksMap extends MapActivity
menu.setHeaderTitle(R.string.tracklist_this_track);
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
R.string.tracklist_edit_track);
if (!MyTracks.getInstance().isRecording() || !isRecordingSelected()) {
if (!isRecordingSelected()) {
menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0,
R.string.tracklist_send_to_google);
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
@@ -910,26 +909,7 @@ public class MyTracksMap extends MapActivity
uiHandler.post(new Runnable() {
@Override
public void run() {
if (key.equals(getString(R.string.min_required_accuracy_key))) {
minRequiredAccuracy = sharedPreferences.getInt(
getString(R.string.min_required_accuracy_key),
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY);
} else if (key.equals(getString(R.string.selected_track_key))) {
long selectedTrackId =
sharedPreferences.getLong(
getString(R.string.selected_track_key),
-1);
setSelectedTrack(selectedTrackId);
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(
getString(R.string.recording_track_key),
-1);
if (isATrackSelected()) {
mapOverlay.setShowEndMarker(!isRecordingSelected());
mapView.postInvalidate();
}
}
reloadSharedPreferences(sharedPreferences, key);
}
});
}
@@ -1009,6 +989,29 @@ public class MyTracksMap extends MapActivity
}
};
private void reloadSharedPreferences(SharedPreferences sharedPreferences,
String key) {
if (key == null ||
key.equals(getString(R.string.min_required_accuracy_key))) {
minRequiredAccuracy = sharedPreferences.getInt(
getString(R.string.min_required_accuracy_key),
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY);
}
if (key == null || key.equals(getString(R.string.selected_track_key))) {
long selectedTrackId = sharedPreferences.getLong(
getString(R.string.selected_track_key), -1);
setSelectedTrack(selectedTrackId);
}
if (key == null || key.equals(getString(R.string.recording_track_key))) {
recordingTrackId = sharedPreferences.getLong(
getString(R.string.recording_track_key), -1);
if (isATrackSelected()) {
mapOverlay.setShowEndMarker(!isRecordingSelected());
mapView.postInvalidate();
}
}
}
private void readAllNewTrackPoints() {
int numPoints = mapOverlay.getNumLocations();
if (numPoints >= MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS) {
@@ -745,6 +745,7 @@ public class TrackRecordingService extends Service implements LocationListener {
"TrackRecordingService: Not resuming, because the previous track ("
+ recordingTrack + ") doesn't exist or is too old");
isRecording = false;
prefManager.setRecordingTrack(recordingTrackId = -1);
stopSelfResult(startId);
return;
}
@@ -805,6 +806,11 @@ public class TrackRecordingService extends Service implements LocationListener {
}
public long insertWaypointMarker(Waypoint waypoint) {
if (!isRecording()) {
throw new IllegalStateException(
"Unable to insert waypoint marker while not recording!");
}
if (waypoint.getLocation() != null) {
waypoint.setLength(length);
waypoint.setDuration(waypoint.getLocation().getTime()
@@ -823,6 +829,11 @@ public class TrackRecordingService extends Service implements LocationListener {
* @return the unique id of the inserted marker
*/
public long insertStatisticsMarker(Location location) {
if (!isRecording()) {
throw new IllegalStateException(
"Unable to insert statistics marker while not recording!");
}
StringUtils utils = new StringUtils(TrackRecordingService.this);
// Create a new waypoint to save
@@ -930,13 +941,15 @@ public class TrackRecordingService extends Service implements LocationListener {
"_id=" + recordingTrack.getId(), null);
}
showNotification();
recordingTrackId = -1;
prefManager.setRecordingTrack(recordingTrackId);
prefManager.setRecordingTrack(recordingTrackId = -1);
}
@Override
public void deleteAllTracks() {
endCurrentTrack();
if (isRecording()) {
throw new IllegalStateException(
"Cannot delete all tracks while recording!");
}
providerUtils.deleteAllTracks();
}
@@ -969,12 +982,13 @@ public class TrackRecordingService extends Service implements LocationListener {
recordingTrackId = Long.parseLong(trackUri.getLastPathSegment());
track.setId(recordingTrackId);
track.setName(String.format(getString(R.string.new_track), recordingTrackId));
isRecording = true;
isMoving = true;
providerUtils.updateTrack(track);
statsBuilder = new TripStatisticsBuilder(startTime);
waypointStatsBuilder = new TripStatisticsBuilder(startTime);
currentWaypointId = insertStatisticsMarker(null);
isRecording = true;
isMoving = true;
setUpAnnouncer();
length = 0;
showNotification();