forked from upstream-mirrors/OpenTracks
Add methods to TrackRecordingService to start and stop GPS.
No longer unregister location listener before registering it.
This commit is contained in:
+102
-56
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.services;
|
|||||||
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
import com.google.android.apps.mytracks.Constants;
|
||||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||||
|
import com.google.android.apps.mytracks.TrackListActivity;
|
||||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||||
@@ -44,7 +45,6 @@ import com.google.android.gms.location.LocationListener;
|
|||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -88,7 +88,7 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
public static final String
|
public static final String
|
||||||
RESUME_TRACK_EXTRA_NAME = "com.google.android.apps.mytracks.RESUME_TRACK";
|
RESUME_TRACK_EXTRA_NAME = "com.google.android.apps.mytracks.RESUME_TRACK";
|
||||||
|
|
||||||
public static final double PAUSE_LATITUDE = 100.0;
|
public static final double PAUSE_LATITUDE = 100.0;
|
||||||
public static final double RESUME_LATITUDE = 200.0;
|
public static final double RESUME_LATITUDE = 200.0;
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ public class TrackRecordingService extends Service {
|
|||||||
Log.w(TAG, "track is null, but recordingTrackId not -1L. " + recordingTrackId);
|
Log.w(TAG, "track is null, but recordingTrackId not -1L. " + recordingTrackId);
|
||||||
updateRecordingState(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, true);
|
updateRecordingState(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, true);
|
||||||
}
|
}
|
||||||
showNotification();
|
showNotification(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ public class TrackRecordingService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
showNotification();
|
showNotification(false);
|
||||||
|
|
||||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
checkLocationListener.cancel();
|
checkLocationListener.cancel();
|
||||||
@@ -403,7 +403,7 @@ public class TrackRecordingService extends Service {
|
|||||||
|
|
||||||
WaypointType waypointType = waypointCreationRequest.getType();
|
WaypointType waypointType = waypointCreationRequest.getType();
|
||||||
boolean isStatistics = waypointType == WaypointType.STATISTICS;
|
boolean isStatistics = waypointType == WaypointType.STATISTICS;
|
||||||
|
|
||||||
// Get name
|
// Get name
|
||||||
String name;
|
String name;
|
||||||
if (waypointCreationRequest.getName() != null) {
|
if (waypointCreationRequest.getName() != null) {
|
||||||
@@ -423,7 +423,7 @@ public class TrackRecordingService extends Service {
|
|||||||
String category = waypointCreationRequest.getCategory() != null ? waypointCreationRequest
|
String category = waypointCreationRequest.getCategory() != null ? waypointCreationRequest
|
||||||
.getCategory()
|
.getCategory()
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
// Get tripStatistics, description, and icon
|
// Get tripStatistics, description, and icon
|
||||||
TripStatistics tripStatistics;
|
TripStatistics tripStatistics;
|
||||||
String description;
|
String description;
|
||||||
@@ -462,10 +462,10 @@ public class TrackRecordingService extends Service {
|
|||||||
length = 0.0;
|
length = 0.0;
|
||||||
duration = 0L;
|
duration = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert waypoint
|
// Insert waypoint
|
||||||
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId, waypointType,
|
Waypoint waypoint = new Waypoint(name, description, category, icon, recordingTrackId,
|
||||||
length, duration, -1L, -1L, location, tripStatistics);
|
waypointType, length, duration, -1L, -1L, location, tripStatistics);
|
||||||
Uri uri = myTracksProviderUtils.insertWaypoint(waypoint);
|
Uri uri = myTracksProviderUtils.insertWaypoint(waypoint);
|
||||||
return Long.parseLong(uri.getLastPathSegment());
|
return Long.parseLong(uri.getLastPathSegment());
|
||||||
}
|
}
|
||||||
@@ -473,11 +473,16 @@ public class TrackRecordingService extends Service {
|
|||||||
/**
|
/**
|
||||||
* Starts the service as a foreground service.
|
* Starts the service as a foreground service.
|
||||||
*
|
*
|
||||||
* @param notification the notification for the foreground service
|
* @param pendingIntent the notification pending intent
|
||||||
|
* @param messageId the notification message id
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected void startForegroundService(Notification notification) {
|
protected void startForegroundService(PendingIntent pendingIntent, int messageId) {
|
||||||
startForeground(1, notification);
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setContentIntent(
|
||||||
|
pendingIntent).setContentText(getString(messageId))
|
||||||
|
.setContentTitle(getString(R.string.my_tracks_app_name)).setOngoing(true)
|
||||||
|
.setSmallIcon(R.drawable.my_tracks_notification_icon).setWhen(System.currentTimeMillis());
|
||||||
|
startForeground(1, builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -567,7 +572,7 @@ public class TrackRecordingService extends Service {
|
|||||||
// Update database
|
// Update database
|
||||||
track.setId(trackId);
|
track.setId(trackId);
|
||||||
track.setName(TrackNameUtils.getTrackName(this, trackId, now, null));
|
track.setName(TrackNameUtils.getTrackName(this, trackId, now, null));
|
||||||
|
|
||||||
String category = PreferencesUtils.getString(
|
String category = PreferencesUtils.getString(
|
||||||
this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
|
||||||
track.setCategory(category);
|
track.setCategory(category);
|
||||||
@@ -592,7 +597,8 @@ public class TrackRecordingService extends Service {
|
|||||||
trackTripStatisticsUpdater = new TripStatisticsUpdater(tripStatistics.getStartTime());
|
trackTripStatisticsUpdater = new TripStatisticsUpdater(tripStatistics.getStartTime());
|
||||||
|
|
||||||
long markerStartTime;
|
long markerStartTime;
|
||||||
Waypoint waypoint = myTracksProviderUtils.getLastWaypoint(recordingTrackId, WaypointType.STATISTICS);
|
Waypoint waypoint = myTracksProviderUtils.getLastWaypoint(
|
||||||
|
recordingTrackId, WaypointType.STATISTICS);
|
||||||
if (waypoint != null && waypoint.getTripStatistics() != null) {
|
if (waypoint != null && waypoint.getTripStatistics() != null) {
|
||||||
markerStartTime = waypoint.getTripStatistics().getStopTime();
|
markerStartTime = waypoint.getTripStatistics().getStopTime();
|
||||||
} else {
|
} else {
|
||||||
@@ -661,18 +667,13 @@ public class TrackRecordingService extends Service {
|
|||||||
* @param trackStarted true if track is started, false if track is resumed
|
* @param trackStarted true if track is started, false if track is resumed
|
||||||
*/
|
*/
|
||||||
private void startRecording(boolean trackStarted) {
|
private void startRecording(boolean trackStarted) {
|
||||||
acquireWakeLock();
|
|
||||||
|
|
||||||
// Update instance variables
|
// Update instance variables
|
||||||
sensorManager = SensorManagerFactory.getSystemSensorManager(this);
|
sensorManager = SensorManagerFactory.getSystemSensorManager(this);
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
currentSegmentHasLocation = false;
|
currentSegmentHasLocation = false;
|
||||||
|
|
||||||
// Register notifications
|
startGps();
|
||||||
registerLocationListener();
|
|
||||||
|
|
||||||
// Send notifications
|
|
||||||
showNotification();
|
|
||||||
sendTrackBroadcast(trackStarted ? R.string.track_started_broadcast_action
|
sendTrackBroadcast(trackStarted ? R.string.track_started_broadcast_action
|
||||||
: R.string.track_resumed_broadcast_action, recordingTrackId);
|
: R.string.track_resumed_broadcast_action, recordingTrackId);
|
||||||
|
|
||||||
@@ -681,6 +682,15 @@ public class TrackRecordingService extends Service {
|
|||||||
splitExecutor.restore();
|
splitExecutor.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts gps.
|
||||||
|
*/
|
||||||
|
private void startGps() {
|
||||||
|
acquireWakeLock();
|
||||||
|
registerLocationListener();
|
||||||
|
showNotification(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends the current track.
|
* Ends the current track.
|
||||||
*/
|
*/
|
||||||
@@ -705,19 +715,6 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
endRecording(true, trackId);
|
endRecording(true, trackId);
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the last valid track point in the current segment. Returns null if not available.
|
|
||||||
*
|
|
||||||
* @param trackId the track id
|
|
||||||
*/
|
|
||||||
private Location getLastValidTrackPointInCurrentSegment(long trackId) {
|
|
||||||
if (!currentSegmentHasLocation) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return myTracksProviderUtils.getLastValidTrackPoint(trackId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -767,15 +764,36 @@ public class TrackRecordingService extends Service {
|
|||||||
}
|
}
|
||||||
lastLocation = null;
|
lastLocation = null;
|
||||||
|
|
||||||
// Unregister notifications
|
|
||||||
unregisterLocationListener();
|
|
||||||
|
|
||||||
// Send notifications
|
|
||||||
showNotification();
|
|
||||||
sendTrackBroadcast(trackStopped ? R.string.track_stopped_broadcast_action
|
sendTrackBroadcast(trackStopped ? R.string.track_stopped_broadcast_action
|
||||||
: R.string.track_paused_broadcast_action, trackId);
|
: R.string.track_paused_broadcast_action, trackId);
|
||||||
|
stopGps(trackStopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops gps.
|
||||||
|
*
|
||||||
|
* @param stop true to stop self
|
||||||
|
*/
|
||||||
|
private void stopGps(boolean stop) {
|
||||||
|
unregisterLocationListener();
|
||||||
|
showNotification(false);
|
||||||
releaseWakeLock();
|
releaseWakeLock();
|
||||||
|
if (stop) {
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last valid track point in the current segment. Returns null if not
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* @param trackId the track id
|
||||||
|
*/
|
||||||
|
private Location getLastValidTrackPointInCurrentSegment(long trackId) {
|
||||||
|
if (!currentSegmentHasLocation) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return myTracksProviderUtils.getLastValidTrackPoint(trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -818,7 +836,7 @@ public class TrackRecordingService extends Service {
|
|||||||
Log.d(TAG, "Ignore onLocationChangedAsync. Poor accuracy.");
|
Log.d(TAG, "Ignore onLocationChangedAsync. Poor accuracy.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix for phones that do not set the time field
|
// Fix for phones that do not set the time field
|
||||||
if (location.getTime() == 0L) {
|
if (location.getTime() == 0L) {
|
||||||
location.setTime(System.currentTimeMillis());
|
location.setTime(System.currentTimeMillis());
|
||||||
@@ -828,7 +846,7 @@ public class TrackRecordingService extends Service {
|
|||||||
long idleTime = 0L;
|
long idleTime = 0L;
|
||||||
if (lastValidTrackPoint != null && location.getTime() > lastValidTrackPoint.getTime()) {
|
if (lastValidTrackPoint != null && location.getTime() > lastValidTrackPoint.getTime()) {
|
||||||
idleTime = location.getTime() - lastValidTrackPoint.getTime();
|
idleTime = location.getTime() - lastValidTrackPoint.getTime();
|
||||||
}
|
}
|
||||||
locationListenerPolicy.updateIdleTime(idleTime);
|
locationListenerPolicy.updateIdleTime(idleTime);
|
||||||
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
|
if (currentRecordingInterval != locationListenerPolicy.getDesiredPollingInterval()) {
|
||||||
registerLocationListener();
|
registerLocationListener();
|
||||||
@@ -900,7 +918,7 @@ public class TrackRecordingService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Do not insert if inserted already
|
// Do not insert if inserted already
|
||||||
if (lastValidTrackPoint != null && lastValidTrackPoint.getTime() == location.getTime()) {
|
if (lastValidTrackPoint != null && lastValidTrackPoint.getTime() == location.getTime()) {
|
||||||
Log.w(TAG, "Ignore insertLocation. location time same as last valid track point time.");
|
Log.w(TAG, "Ignore insertLocation. location time same as last valid track point time.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -959,8 +977,6 @@ public class TrackRecordingService extends Service {
|
|||||||
*/
|
*/
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
unregisterLocationListener();
|
|
||||||
|
|
||||||
if (myTracksLocationManager == null) {
|
if (myTracksLocationManager == null) {
|
||||||
Log.e(TAG, "locationManager is null.");
|
Log.e(TAG, "locationManager is null.");
|
||||||
return;
|
return;
|
||||||
@@ -1028,21 +1044,32 @@ public class TrackRecordingService extends Service {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification.
|
* Shows the notification.
|
||||||
|
*
|
||||||
|
* @param isGpsStarted true if GPS is started
|
||||||
*/
|
*/
|
||||||
private void showNotification() {
|
private void showNotification(boolean isGpsStarted) {
|
||||||
if (isRecording() && !isPaused()) {
|
if (isRecording()) {
|
||||||
Intent intent = IntentUtils.newIntent(this, TrackDetailActivity.class)
|
if (isPaused()) {
|
||||||
.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, recordingTrackId);
|
stopForegroundService();
|
||||||
PendingIntent pendingIntent = TaskStackBuilder.create(this)
|
} else {
|
||||||
.addParentStack(TrackDetailActivity.class).addNextIntent(intent)
|
Intent intent = IntentUtils.newIntent(this, TrackDetailActivity.class)
|
||||||
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, recordingTrackId);
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setContentIntent(
|
PendingIntent pendingIntent = TaskStackBuilder.create(this)
|
||||||
pendingIntent).setContentText(getString(R.string.track_record_notification))
|
.addParentStack(TrackDetailActivity.class).addNextIntent(intent)
|
||||||
.setContentTitle(getString(R.string.my_tracks_app_name)).setOngoing(true)
|
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
.setSmallIcon(R.drawable.my_tracks_notification_icon).setWhen(System.currentTimeMillis());
|
startForegroundService(pendingIntent, R.string.track_record_notification);
|
||||||
startForegroundService(builder.build());
|
}
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
stopForegroundService();
|
// Not recording
|
||||||
|
if (isGpsStarted) {
|
||||||
|
Intent intent = IntentUtils.newIntent(this, TrackListActivity.class);
|
||||||
|
PendingIntent pendingIntent = TaskStackBuilder.create(this)
|
||||||
|
.addNextIntent(intent).getPendingIntent(0, 0);
|
||||||
|
startForegroundService(pendingIntent, R.string.gps_starting);
|
||||||
|
} else {
|
||||||
|
stopForegroundService();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,6 +1130,25 @@ public class TrackRecordingService extends Service {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startGps() {
|
||||||
|
if (!canAccess()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!trackRecordingService.isRecording()) {
|
||||||
|
trackRecordingService.startGps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopGps() {
|
||||||
|
if (!canAccess()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!trackRecordingService.isRecording()) {
|
||||||
|
trackRecordingService.stopGps(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long startNewTrack() {
|
public long startNewTrack() {
|
||||||
if (!canAccess()) {
|
if (!canAccess()) {
|
||||||
|
|||||||
+12
-2
@@ -23,6 +23,16 @@ import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
|||||||
*/
|
*/
|
||||||
interface ITrackRecordingService {
|
interface ITrackRecordingService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts gps.
|
||||||
|
*/
|
||||||
|
void startGps();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops gps.
|
||||||
|
*/
|
||||||
|
void stopGps();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts recording a new track.
|
* Starts recording a new track.
|
||||||
*
|
*
|
||||||
@@ -85,14 +95,14 @@ interface ITrackRecordingService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current sensor data. Returns null if there is no data.
|
* Gets the current sensor data. Returns null if there is no data.
|
||||||
|
|
||||||
* @return a byte array of the binary version of the Sensor.SensorDataSet object.
|
* @return a byte array of the binary version of the Sensor.SensorDataSet object.
|
||||||
*/
|
*/
|
||||||
byte[] getSensorData();
|
byte[] getSensorData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current sensor manager state.
|
* Gets the current sensor manager state.
|
||||||
*
|
*
|
||||||
* return a Sensor.SensorState enum value.
|
* return a Sensor.SensorState enum value.
|
||||||
*/
|
*/
|
||||||
int getSensorState();
|
int getSensorState();
|
||||||
|
|||||||
+7
-6
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
package com.google.android.apps.mytracks.services;
|
package com.google.android.apps.mytracks.services;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.test.ServiceTestCase;
|
import android.test.ServiceTestCase;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -11,15 +11,16 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TrackRecordingService} that can be used with {@link ServiceTestCase}.
|
* A {@link TrackRecordingService} that can be used with
|
||||||
* {@link ServiceTestCase} throws a null pointer exception when the service
|
* {@link ServiceTestCase}. {@link ServiceTestCase} throws a null pointer
|
||||||
* calls {@link Service#startForeground(int, android.app.Notification)} and
|
* exception when the service calls
|
||||||
|
* {@link Service#startForeground(int, android.app.Notification)} and
|
||||||
* {@link Service#stopForeground(boolean)}.
|
* {@link Service#stopForeground(boolean)}.
|
||||||
* <p>
|
* <p>
|
||||||
* See http://code.google.com/p/android/issues/detail?id=12122
|
* See http://code.google.com/p/android/issues/detail?id=12122
|
||||||
* <p>
|
* <p>
|
||||||
* Wrap these two methods in wrappers and override them.
|
* Wrap these two methods in wrappers and override them.
|
||||||
*
|
*
|
||||||
* @author Jimmy Shih
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
public class TestRecordingService extends TrackRecordingService {
|
public class TestRecordingService extends TrackRecordingService {
|
||||||
@@ -27,7 +28,7 @@ public class TestRecordingService extends TrackRecordingService {
|
|||||||
private static final String TAG = TestRecordingService.class.getSimpleName();
|
private static final String TAG = TestRecordingService.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startForegroundService(Notification notification) {
|
protected void startForegroundService(PendingIntent pendingIntent, int messageId) {
|
||||||
try {
|
try {
|
||||||
Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class);
|
Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class);
|
||||||
setForegroundMethod.invoke(this, true);
|
setForegroundMethod.invoke(this, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user