2
* Copyright 2008 Google Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
* use this file except in compliance with the License. You may obtain a copy of
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
* License for the specific language governing permissions and limitations under
16
package org.opensatnav.android.contribute.services;
18
import java.util.Timer;
19
import java.util.TimerTask;
21
import org.opensatnav.android.R;
22
import org.opensatnav.android.OpenSatNavConstants;
23
import org.opensatnav.android.SatNavActivity;
24
import org.opensatnav.android.contribute.content.IProviderUtils;
25
import org.opensatnav.android.contribute.content.Track;
26
import org.opensatnav.android.contribute.content.TracksColumns;
27
import org.opensatnav.android.contribute.content.Waypoint;
28
import org.opensatnav.android.contribute.content.WaypointsColumns;
29
import org.opensatnav.android.contribute.services.AbsoluteLocationListenerPolicy;
30
import org.opensatnav.android.contribute.services.LocationListenerPolicy;
31
import org.opensatnav.android.contribute.util.MyTracksUtils;
32
import org.opensatnav.android.contribute.util.StringUtils;
33
import org.opensatnav.android.contribute.util.constants.OSMConstants;
34
import org.opensatnav.android.services.LocationHandler;
35
import org.opensatnav.android.stats.TripStatistics;
37
import org.opensatnav.android.contribute.services.ITrackRecordingService;
39
import android.app.Notification;
40
import android.app.NotificationManager;
41
import android.app.PendingIntent;
42
import android.app.Service;
43
import android.content.ContentValues;
44
import android.content.Context;
45
import android.content.Intent;
46
import android.content.SharedPreferences;
47
import android.database.Cursor;
48
import android.database.sqlite.SQLiteException;
49
import android.location.Location;
50
import android.location.LocationListener;
51
import android.location.LocationManager;
52
import android.net.Uri;
53
import android.os.Bundle;
54
import android.os.Handler;
55
import android.os.IBinder;
56
import android.os.PowerManager;
57
import android.os.PowerManager.WakeLock;
58
import android.util.Log;
61
* A background service that registers a location listener and records track
62
* points. Track points are saved to the MyTracksProvider.
64
* @author Leif Hendrik Wilden
66
public class TrackRecordingService extends Service implements LocationListener {
69
private static final String STATISTICS_ICON_URL =
70
"http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png";
72
private NotificationManager notificationManager;
73
private LocationManager locationManager;
74
private WakeLock wakeLock;
76
private int minRecordingInterval =
77
OpenSatNavConstants.DEFAULT_MIN_RECORDING_INTERVAL;
78
private int minRecordingDistance =
79
OpenSatNavConstants.DEFAULT_MIN_RECORDING_DISTANCE;
80
private int maxRecordingDistance =
81
OpenSatNavConstants.DEFAULT_MAX_RECORDING_DISTANCE;
82
private int minRequiredAccuracy =
83
OpenSatNavConstants.DEFAULT_MIN_REQUIRED_ACCURACY;
84
private long recordingTrackId = -1;
86
private long currentWaypointId = -1;
89
* For debugging. Keep track of calls to onCreate().
91
private boolean onCreateWasCalled = false;
93
/** The timer posts a runnable to the main thread via this handler. */
94
private final Handler handler = new Handler();
97
* Utilities to deal with the database.
99
private IProviderUtils providerUtils;
101
private TripStatistics stats = new TripStatistics();
102
private TripStatistics waypointStats = new TripStatistics();
105
* Current length of the recorded track. This length is calculated from the
106
* recorded points (as compared to each location fix). It's used to overlay
107
* waypoints precisely in the elevation profile chart.
109
private double length = 0;
112
* Status announcer executer.
114
private PeriodicTaskExecuter executer;
116
private SplitManager splitManager;
119
* The interval in milliseconds that we have requested to be notfied of gps
122
private long currentRecordingInterval = 0;
125
* The policy used to decide how often we should request gps updates.
127
private LocationListenerPolicy locationListenerPolicy =
128
new AbsoluteLocationListenerPolicy(0);
131
* The old location handler
133
protected static LocationHandler mLocationHandler;
136
* Task invoked by a timer periodically to make sure the location listener is
139
private TimerTask checkLocationListener = new TimerTask() {
142
if (!onCreateWasCalled) {
143
Log.e(OpenSatNavConstants.LOG_TAG,
144
"TrackRecordingService is running, but onCreate not called.");
147
handler.post(new Runnable() {
149
Log.d(OpenSatNavConstants.LOG_TAG,
150
"Re-registering location listener with TrackRecordingService.");
151
unregisterLocationListener();
152
registerLocationListener();
156
Log.w(OpenSatNavConstants.LOG_TAG,
157
"Track recording service is paused. That should not be.");
163
* This timer invokes periodically the checkLocationListener timer task.
165
private final Timer timer = new Timer();
168
* Is the phone currently moving?
170
private boolean isMoving = true;
173
* Is the service currently recording a track?
175
private boolean isRecording = false;
178
* Last good location the service has received from the location listener
180
private Location lastLocation = null;
183
* Last valid location (i.e. not a marker) that was recorded.
185
private Location lastValidLocation = null;
192
* Inserts a new location in the track points db and updates the corresponding
193
* track in the track db.
195
* @param recordingTrack the track that is currently being recorded
196
* @param location the location to be inserted
197
* @param lastRecordedLocation the last recorded location before this one (or
199
* @param lastRecordedLocationId the id of the last recorded location (or -1
201
* @param trackId the id of the track
202
* @return true if successful. False if SQLite3 threw an exception.
204
private boolean insertLocation(Track recordingTrack, Location location,
205
Location lastRecordedLocation, long lastRecordedLocationId,
208
// Keep track of length along recorded track (needed when a waypoint is
210
if (MyTracksUtils.isValidLocation(location)) {
211
if (lastValidLocation != null) {
212
length += location.distanceTo(lastValidLocation);
214
lastValidLocation = location;
217
// Insert the new location:
219
Uri pointUri = providerUtils.insertTrackPoint(location, trackId);
220
int pointId = Integer.parseInt(pointUri.getLastPathSegment());
222
// Update the current track:
223
if (lastRecordedLocation != null
224
&& lastRecordedLocation.getLatitude() < 90) {
225
ContentValues values = new ContentValues();
226
if (recordingTrack.getStartId() < 0) {
227
values.put(TracksColumns.STARTID, pointId);
228
recordingTrack.setStartId(pointId);
230
values.put(TracksColumns.STOPID, pointId);
231
values.put(TracksColumns.STOPTIME, System.currentTimeMillis());
232
values.put(TracksColumns.NUMPOINTS,
233
recordingTrack.getNumberOfPoints() + 1);
234
values.put(TracksColumns.MINLAT, stats.getBottom());
235
values.put(TracksColumns.MAXLAT, stats.getTop());
236
values.put(TracksColumns.MINLON, stats.getLeft());
237
values.put(TracksColumns.MAXLON, stats.getRight());
238
values.put(TracksColumns.TOTALDISTANCE, stats.getTotalDistance());
239
values.put(TracksColumns.TOTALTIME, stats.getTotalTime());
240
values.put(TracksColumns.MOVINGTIME, stats.getMovingTime());
241
values.put(TracksColumns.AVGSPEED, stats.getAverageSpeed());
242
values.put(TracksColumns.AVGMOVINGSPEED, stats.getAverageMovingSpeed());
243
values.put(TracksColumns.MAXSPEED, stats.getMaxSpeed());
244
values.put(TracksColumns.MINELEVATION, stats.getMinElevation());
245
values.put(TracksColumns.MAXELEVATION, stats.getMaxElevation());
246
values.put(TracksColumns.ELEVATIONGAIN, stats.getTotalElevationGain());
247
values.put(TracksColumns.MINGRADE, stats.getMinGrade());
248
values.put(TracksColumns.MAXGRADE, stats.getMaxGrade());
249
getContentResolver().update(TracksColumns.CONTENT_URI,
250
values, "_id=" + recordingTrack.getId(), null);
251
updateCurrentWaypoint();
253
} catch (SQLiteException e) {
254
// Insert failed, most likely because of SqlLite error code 5
255
// (SQLite_BUSY). This is expected to happen extremely rarely (if our
256
// listener gets invoked twice at about the same time).
257
Log.w(OpenSatNavConstants.LOG_TAG,
258
"Caught SQLiteException: " + e.getMessage(), e);
261
splitManager.updateSplits();
265
private void updateCurrentWaypoint() {
266
if (currentWaypointId >= 0) {
267
ContentValues values = new ContentValues();
268
values.put(WaypointsColumns.STARTTIME, waypointStats.getStartTime());
269
values.put(WaypointsColumns.LENGTH, length);
270
values.put(WaypointsColumns.DURATION,
271
System.currentTimeMillis() - stats.getStartTime());
272
values.put(WaypointsColumns.TOTALDISTANCE,
273
waypointStats.getTotalDistance());
274
values.put(WaypointsColumns.TOTALTIME, waypointStats.getTotalTime());
275
values.put(WaypointsColumns.MOVINGTIME, waypointStats.getMovingTime());
276
values.put(WaypointsColumns.AVGSPEED, waypointStats.getAverageSpeed());
277
values.put(WaypointsColumns.AVGMOVINGSPEED,
278
waypointStats.getAverageMovingSpeed());
279
values.put(WaypointsColumns.MAXSPEED, waypointStats.getMaxSpeed());
280
values.put(WaypointsColumns.MINELEVATION,
281
waypointStats.getMinElevation());
282
values.put(WaypointsColumns.MAXELEVATION,
283
waypointStats.getMaxElevation());
284
values.put(WaypointsColumns.ELEVATIONGAIN,
285
waypointStats.getTotalElevationGain());
286
values.put(WaypointsColumns.MINGRADE, waypointStats.getMinGrade());
287
values.put(WaypointsColumns.MAXGRADE, waypointStats.getMaxGrade());
288
getContentResolver().update(WaypointsColumns.CONTENT_URI,
289
values, "_id=" + currentWaypointId, null);
294
* Tries to acquire a partial wake lock if not already acquired. Logs errors
295
* and gives up trying in case the wake lock cannot be acquired.
297
public void acquireWakeLock() {
299
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
301
Log.e(OpenSatNavConstants.LOG_TAG,
302
"TrackRecordingService: Power manager not found!");
305
if (wakeLock == null) {
306
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
307
OpenSatNavConstants.LOG_TAG);
308
if (wakeLock == null) {
309
Log.e(OpenSatNavConstants.LOG_TAG,
310
"TrackRecordingService: Could not create wake lock (null).");
314
if (!wakeLock.isHeld()) {
316
if (!wakeLock.isHeld()) {
317
Log.e(OpenSatNavConstants.LOG_TAG,
318
"TrackRecordingService: Could not acquire wake lock.");
321
} catch (RuntimeException e) {
322
Log.e(OpenSatNavConstants.LOG_TAG,
323
"TrackRecordingService: Caught unexpected exception: "
324
+ e.getMessage(), e);
329
* Shows the notification message and icon in the notification bar.
331
public void showNotification() {
333
Notification notification = new Notification(R.drawable.icon, getString(R.string.start_trace_ticker), System.currentTimeMillis());
334
PendingIntent contentIntent = PendingIntent.getActivity(
335
this, 0 /* requestCode */, new Intent(this, SatNavActivity.class),
337
notification.setLatestEventInfo(this, getString(R.string.app_name),
338
getString(R.string.tracing_notification_text), contentIntent);
339
notification.flags += Notification.FLAG_NO_CLEAR;
340
notificationManager.notify(1, notification);
342
notificationManager.cancelAll();
346
public void registerLocationListener() {
347
if (locationManager == null) {
348
Log.e(OpenSatNavConstants.LOG_TAG,
349
"TrackRecordingService: Do not have any location manager.");
352
Log.d(OpenSatNavConstants.LOG_TAG,
353
"Preparing to register location listener w/ TrackRecordingService...");
355
long desiredInterval = locationListenerPolicy.getDesiredPollingInterval();
356
locationManager.requestLocationUpdates(
357
OpenSatNavConstants.GPS_PROVIDER, desiredInterval,
358
locationListenerPolicy.getMinDistance(),
359
// , 0 /* minDistance, get all updates to properly time pauses */
360
TrackRecordingService.this);
361
currentRecordingInterval = desiredInterval;
362
Log.d(OpenSatNavConstants.LOG_TAG,
363
"...location listener now registered w/ TrackRecordingService @ "
364
+ currentRecordingInterval);
365
} catch (RuntimeException e) {
366
Log.e(OpenSatNavConstants.LOG_TAG,
367
"Could not register location listener: " + e.getMessage(), e);
371
public void unregisterLocationListener() {
372
if (locationManager == null) {
373
Log.e(OpenSatNavConstants.LOG_TAG,
374
"TrackRecordingService: Do not have any location manager.");
377
locationManager.removeUpdates(this);
378
Log.d(OpenSatNavConstants.LOG_TAG,
379
"Location listener now unregistered w/ TrackRecordingService.");
382
private void restoreStats() {
383
if (recordingTrackId < 0) {
387
Track track = providerUtils.getTrack(recordingTrackId);
392
stats = new TripStatistics(track.getStartTime());
395
splitManager.restore();
397
lastValidLocation = null;
399
Waypoint waypoint = providerUtils.getFirstWaypoint(recordingTrackId);
400
if (waypoint != null) {
401
currentWaypointId = waypoint.getId();
402
waypointStats = new TripStatistics(waypoint);
404
// This should never happen, but we got to do something so life goes on:
405
waypointStats = new TripStatistics(track.getStartTime());
406
currentWaypointId = -1;
409
Cursor cursor = null;
411
cursor = providerUtils.getLocationsCursor(
412
recordingTrackId, -1, OSMConstants.MAX_LOADED_TRACK_POINTS,
414
if (cursor != null) {
415
if (cursor.moveToLast()) {
417
Location location = providerUtils.createLocation(cursor);
418
if (MyTracksUtils.isValidLocation(location)) {
419
stats.addLocation(location, location.getTime());
420
if (lastValidLocation != null) {
421
length += location.distanceTo(lastValidLocation);
423
lastValidLocation = location;
425
} while (cursor.moveToPrevious());
427
stats.setMovingTime(track.getMovingTime());
428
stats.pauseAt(track.getStopTime());
431
Log.e(OpenSatNavConstants.LOG_TAG, "Could not get track points cursor.");
433
} catch (RuntimeException e) {
434
Log.e(OpenSatNavConstants.LOG_TAG, "Error while restoring track.", e);
436
if (cursor != null) {
441
splitManager.calculateNextSplit();
445
* Location listener implementation: =================================
449
public void onLocationChanged(Location location) {
453
// Don't record if the service has been asked to pause recording:
455
Log.w(OpenSatNavConstants.LOG_TAG,
456
"Not recording because recording has been paused.");
460
// This should never happen, but just in case (we really don't want the
463
if (location == null) {
464
Log.w(OpenSatNavConstants.LOG_TAG,
465
"Location changed, but location is null.");
469
// Don't record if the accuracy is too bad:
470
if (location.getAccuracy() > minRequiredAccuracy) {
471
Log.d(OpenSatNavConstants.LOG_TAG,
472
"Not recording. Bad accuracy.");
476
// At least one track must be available for appending points:
477
Track recordingTrack = providerUtils.getTrack(recordingTrackId);
478
if (recordingTrack == null) {
479
Log.d(OpenSatNavConstants.LOG_TAG,
480
"Not recording. No track to append to available.");
484
if (MyTracksUtils.isValidLocation(location)) {
485
long now = System.currentTimeMillis();
486
stats.addLocation(location, now);
487
waypointStats.addLocation(location, now);
490
// Update the idle time if needed.
491
locationListenerPolicy.updateIdleTime(stats.getIdleTime());
492
if (currentRecordingInterval
493
!= locationListenerPolicy.getDesiredPollingInterval()) {
494
registerLocationListener();
497
Location lastRecordedLocation = providerUtils.getLastLocation();
498
long lastRecordedLocationId =
499
providerUtils.getLastLocationId(recordingTrackId);
500
double distanceToLastRecorded = Double.POSITIVE_INFINITY;
501
if (lastRecordedLocation != null) {
502
distanceToLastRecorded = location.distanceTo(lastRecordedLocation);
504
double distanceToLast = Double.POSITIVE_INFINITY;
505
if (lastLocation != null) {
506
distanceToLast = location.distanceTo(lastLocation);
509
// If the user has been stationary for two recording just record the first
510
// two and ignore the rest. This code will only have an effect if the
511
// maxRecordingDistance = 0
512
if (distanceToLast == 0) {
514
Log.d(OpenSatNavConstants.LOG_TAG, "Found two identical locations.");
516
if (lastLocation != null && lastRecordedLocation != null
517
&& !lastRecordedLocation.equals(lastLocation)) {
518
// Need to write the last location. This will happen when
519
// lastRecordedLocation.distance(lastLocation) <
520
// minRecordingDistance
521
if (!insertLocation(recordingTrack, lastLocation,
522
lastRecordedLocation, lastRecordedLocationId,
526
lastRecordedLocationId++;
529
Log.d(OpenSatNavConstants.LOG_TAG,
530
"Not recording. More than two identical locations.");
532
} else if (distanceToLastRecorded > minRecordingDistance) {
533
if (lastLocation != null && !isMoving) {
534
// Last location was the last stationary location. Need to go back and
536
if (!insertLocation(recordingTrack, lastLocation,
537
lastRecordedLocation, lastRecordedLocationId, recordingTrackId)) {
540
lastRecordedLocationId++;
544
// If separation from last recorded point is too large insert a
546
// to indicate end of a segment:
547
boolean startNewSegment =
548
lastRecordedLocation != null
549
&& lastRecordedLocation.getLatitude() < 90
550
&& distanceToLastRecorded > maxRecordingDistance
551
&& recordingTrack.getStartId() >= 0;
552
if (startNewSegment) {
553
// Insert a separator point to indicate start of new track:
554
Log.d(OpenSatNavConstants.LOG_TAG, "Inserting a separator.");
555
Location separator = new Location(OpenSatNavConstants.GPS_PROVIDER);
556
separator.setLongitude(0);
557
separator.setLatitude(100);
558
//TODO: This seems like a bit of a hack, see if this can be nicer
559
separator.setTime(lastRecordedLocation.getTime());
560
providerUtils.insertTrackPoint(separator, recordingTrackId);
563
if (!insertLocation(recordingTrack, location, lastRecordedLocation,
564
lastRecordedLocationId, recordingTrackId)) {
568
Log.d(OpenSatNavConstants.LOG_TAG, String.format(
569
"Not recording. Distance to last recorded point (%f m) is less than"
570
+ " %d m.", distanceToLastRecorded, minRecordingDistance));
573
// Probably important enough to rethrow.
574
Log.e(OpenSatNavConstants.LOG_TAG, "Error in onLocationChanged", e);
576
} catch (RuntimeException e) {
577
// Safe usually to trap exceptions.
578
Log.e(OpenSatNavConstants.LOG_TAG,
579
"Trapping exception in onLocationChanged", e);
582
lastLocation = location;
586
public void onProviderDisabled(String provider) {
591
public void onProviderEnabled(String provider) {
596
public void onStatusChanged(String provider, int status, Bundle extras) {
601
* SharedPreferencesChangeListener interface implementation. Note that
602
* services don't currently receive this event (Android platform limitation).
603
* This should be called from an activity whenever settings change.
607
* Notifies that preferences have changed.
608
* Call this with key == null to update all preferences in one call.
610
* @param key the key that changed (may be null to update all preferences)
612
public void onSharedPreferenceChanged(String key) {
613
Log.d(OpenSatNavConstants.LOG_TAG,
614
"TrackRecordingService.onSharedPreferenceChanged");
615
SharedPreferences sharedPreferences =
616
getSharedPreferences(OpenSatNavConstants.SETTINGS_NAME, 0);
617
if (sharedPreferences == null) {
618
Log.w(OpenSatNavConstants.LOG_TAG,
619
"TrackRecordingService: Couldn't get shared preferences.");
623
if (key == null || key.equals(OpenSatNavConstants.MIN_RECORDING_DISTANCE)) {
624
minRecordingDistance = sharedPreferences.getInt(
625
OpenSatNavConstants.MIN_RECORDING_DISTANCE,
626
OpenSatNavConstants.DEFAULT_MIN_RECORDING_DISTANCE);
627
Log.d(OpenSatNavConstants.LOG_TAG,
628
"TrackRecordingService: minRecordingDistance = "
629
+ minRecordingDistance);
631
/*if (key == null || key.equals(OpenSatNavConstants.MAX_RECORDING_DISTANCE)) {
632
maxRecordingDistance = sharedPreferences.getInt(
633
OpenSatNavConstants.MAX_RECORDING_DISTANCE,
634
OpenSatNavConstants.DEFAULT_MAX_RECORDING_DISTANCE);
636
maxRecordingDistance = OpenSatNavConstants.DEFAULT_MAX_RECORDING_DISTANCE;
637
/**Fix this, and put it in settins */
640
if (key == null || key.equals(OpenSatNavConstants.MIN_RECORDING_INTERVAL)) {
641
minRecordingInterval = sharedPreferences.getInt(
642
OpenSatNavConstants.MIN_RECORDING_INTERVAL,
643
OpenSatNavConstants.DEFAULT_MIN_RECORDING_INTERVAL);
644
switch (minRecordingInterval) {
649
// minDist: 5 meters Choose battery life over moving time accuracy.
650
locationListenerPolicy =
651
new AdaptiveLocationListenerPolicy(30000, 300000, 5);
657
// minDist: 0 meters get all updates to properly measure moving time.
658
locationListenerPolicy =
659
new AdaptiveLocationListenerPolicy(1000, 30000, 0);
662
locationListenerPolicy =
663
new AbsoluteLocationListenerPolicy(minRecordingInterval * 1000);
666
if (key == null || key.equals(OpenSatNavConstants.MIN_REQUIRED_ACCURACY)) {
667
minRequiredAccuracy = sharedPreferences.getInt(
668
OpenSatNavConstants.MIN_REQUIRED_ACCURACY,
669
OpenSatNavConstants.DEFAULT_MIN_REQUIRED_ACCURACY);
671
if (key == null || key.equals(OpenSatNavConstants.RECORDING_TRACK)) {
673
sharedPreferences.getLong(OpenSatNavConstants.RECORDING_TRACK, -1);
676
/*if (key == null || key.equals(OpenSatNavConstants.SPLIT_FREQUENCY)) {
677
splitManager.setSplitFrequency(
678
sharedPreferences.getInt(OpenSatNavConstants.SPLIT_FREQUENCY, 0));
680
if (key == null || key.equals(OpenSatNavConstants.SIGNAL_SAMPLING_FREQUENCY)) {
681
signalManager.setFrequency(sharedPreferences.getInt(
682
OpenSatNavConstants.SIGNAL_SAMPLING_FREQUENCY, -1), this);
684
if (key == null || key.equals(OpenSatNavConstants.METRIC_UNITS)) {
685
splitManager.setMetricUnits(
686
sharedPreferences.getBoolean(OpenSatNavConstants.METRIC_UNITS, true));
688
/**TODO: Put these in settings too: */
689
splitManager.setSplitFrequency(0);
691
splitManager.setMetricUnits(true);
695
registerLocationListener();
700
* Application lifetime events: ============================
704
public void onCreate() {
705
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.onCreate");
707
onCreateWasCalled = true;
710
providerUtils = IProviderUtils.Factory.get(this);
711
notificationManager =
712
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
714
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
715
splitManager = new SplitManager(this);
717
onSharedPreferenceChanged(null);
719
registerLocationListener();
720
Log.v("TTT", "Before");
722
Log.v("TTT", "After");
724
* After 5 min, check every minute that location listener still is
725
* registered and spit out additional debugging info to the logs:
727
timer.schedule(checkLocationListener, 1000 * 60 * 5, 1000 * 60);
733
public void onDestroy() {
734
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.onDestroy");
735
if (wakeLock != null && wakeLock.isHeld()) {
740
unregisterLocationListener();
741
if (executer != null) {
744
splitManager.shutdown();
749
public IBinder onBind(Intent intent) {
750
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.onBind");
755
public boolean onUnbind(Intent intent) {
756
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.onUnbind");
757
return super.onUnbind(intent);
761
public boolean stopService(Intent name) {
762
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.stopService");
763
unregisterLocationListener();
764
return super.stopService(name);
767
public long insertWaypointMarker(Waypoint waypoint) {
768
if (waypoint.getLocation() != null) {
769
waypoint.setLength(length);
770
waypoint.setDuration(
771
waypoint.getLocation().getTime() - stats.getStartTime());
772
Uri uri = providerUtils.insertWaypoint(waypoint);
773
return Long.parseLong(uri.getLastPathSegment());
779
* Inserts a statistics marker. A statistics marker holds the stats for the
780
* last segment up to this marker.
782
* @param location the location where to insert
783
* @return the unique id of the inserted marker
785
public long insertStatisticsMarker(Location location) {
786
Waypoint waypoint = new Waypoint();
787
waypoint.setTrackId(recordingTrackId);
788
waypoint.setType(Waypoint.TYPE_STATISTICS);
789
waypoint.setName(TrackRecordingService.this.getString(R.string.statistics));
790
waypointStats.fillStatisticsForWaypoint(waypoint);
791
StringUtils utils = new StringUtils(TrackRecordingService.this);
792
waypoint.setDescription(utils.generateWaypointDescription(waypoint));
793
waypoint.setLocation(location);
794
waypoint.setIcon(STATISTICS_ICON_URL);
795
waypoint.setLength(length);
796
final long time = System.currentTimeMillis();
797
waypoint.setDuration(time - stats.getStartTime());
798
waypoint.setStartTime(waypointStats.getStartTime());
799
waypoint.setStartId(providerUtils.getLastLocationId(recordingTrackId));
800
Uri uri = providerUtils.insertWaypoint(waypoint);
801
waypointStats = new TripStatistics(time);
802
updateCurrentWaypoint();
803
return Long.parseLong(uri.getLastPathSegment());
807
* The ITrackRecordingService is defined through IDL.
809
private final ITrackRecordingService.Stub binder =
810
new ITrackRecordingService.Stub() {
812
public boolean isRecording() {
817
public long getRecordingTrackId() {
818
return recordingTrackId;
822
public boolean hasRecorded() {
823
return providerUtils.getLastTrackId() >= 0;
827
public long startNewTrack() {
828
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.startNewTrack");
829
Track track = new Track();
830
track.setName("new");
831
track.setStartTime(System.currentTimeMillis());
832
track.setStartId(-1);
833
Uri trackUri = providerUtils.insertTrack(track);
834
long trackId = Long.parseLong(trackUri.getLastPathSegment());
835
track.setId(trackId);
836
track.setName(String.format(getString(R.string.new_track), trackId));
837
providerUtils.updateTrack(track);
838
recordingTrackId = trackId;
839
currentWaypointId = insertStatisticsMarker(null);
842
stats = new TripStatistics(track.getStartTime());
845
registerLocationListener();
846
splitManager.restore();
852
* Insert the given waypoint marker. Users can insert waypoint markers
853
* to tag locations with a name, description, category etc.
855
* @param waypoint a waypoint
856
* @return the unique id of the inserted marker
859
public long insertWaypointMarker(Waypoint waypoint) {
860
return TrackRecordingService.this.insertWaypointMarker(waypoint);
864
* Insert a statistics marker. A statistics marker holds the stats for
865
* the last segment up to this marker.
867
* @param location the location where to insert
868
* @return the unique id of the inserted marker
871
public long insertStatisticsMarker(Location location) {
872
return TrackRecordingService.this.insertStatisticsMarker(location);
876
public void endCurrentTrack() {
877
Log.d(OpenSatNavConstants.LOG_TAG, "TrackRecordingService.endCurrentTrack");
879
Track recordingTrack = providerUtils.getTrack(recordingTrackId);
880
if (recordingTrack != null) {
881
recordingTrack.setStopTime(System.currentTimeMillis());
882
recordingTrack.setTotalTime(
883
recordingTrack.getStopTime() - recordingTrack.getStartTime());
884
long lastRecordedLocationId =
885
providerUtils.getLastLocationId(recordingTrackId);
886
ContentValues values = new ContentValues();
887
if (lastRecordedLocationId >= 0
888
&& recordingTrack.getStopId() >= 0) {
889
values.put(TracksColumns.STOPID, lastRecordedLocationId);
891
values.put(TracksColumns.STOPTIME, recordingTrack.getStopTime());
892
values.put(TracksColumns.TOTALTIME, recordingTrack.getTotalTime());
893
getContentResolver().update(TracksColumns.CONTENT_URI, values,
894
"_id=" + recordingTrack.getId(), null);
897
recordingTrackId = -1;
901
public void deleteAllTracks() {
903
providerUtils.deleteAllTracks();
907
public void recordLocation(Location loc) {
908
onLocationChanged(loc);
912
public void sharedPreferenceChanged(String key) {
913
Log.d(OpenSatNavConstants.LOG_TAG,
914
"TrackRecordingService.sharedPrefereneChange");
915
onSharedPreferenceChanged(key);
919
TripStatistics getTripStatistics() {
923
Location getLastLocation() {
927
long getRecordingTrackId() {
928
return recordingTrackId;