diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Controller.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Controller.java new file mode 100644 index 000000000..870913262 --- /dev/null +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Controller.java @@ -0,0 +1,73 @@ +package net.cyclestreets.track; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; + +class Controller + implements TrackerControl, + ServiceConnection { + public static TrackerControl create(final Context context, final TrackListener listener) { + Controller control = new Controller(context, listener); + + Intent rService = new Intent(context, RecordingService.class); + context.bindService(rService, control, Context.BIND_AUTO_CREATE); + + return control; + } // create + + private final Context context_; + private final TrackListener listener_; + private IRecordService rs_; + private boolean shouldStart_; + private boolean unbound_; + + private Controller( + final Context context, + final TrackListener listener) { + context_ = context; + listener_ = listener; + } // Controller + + @Override + public void onServiceConnected( + final ComponentName name, + final IBinder service) { + rs_ = (IRecordService)service; + rs_.setListener(listener_); + + if (shouldStart_ == true) + rs_.startRecording(); + } // onServiceConnected + + @Override + public void onServiceDisconnected(ComponentName name) {} + + @Override + public void start() { + if (rs_ == null) + shouldStart_ = true; + else + rs_.startRecording(); + } // start + + @Override + public void stop() { + if (unbound_) + return; + + unbound_ = true; + + final TripData trip = rs_.stopRecording(); + context_.unbindService(this); + + if (listener_ != null) { + if (trip.dataAvailable()) + listener_.completed(trip); + else + listener_.abandoned(trip); + } + } // stop +} // Controller diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/IRecordService.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/IRecordService.java index 4231122ca..78e2575ff 100644 --- a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/IRecordService.java +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/IRecordService.java @@ -1,10 +1,10 @@ package net.cyclestreets.track; -public interface IRecordService { +interface IRecordService { public int getState(); public TripData startRecording(); - public void stopRecording(); + public TripData stopRecording(); public void setListener(TrackListener ra); } diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/JourneyOverlay.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/JourneyOverlay.java index 5b2c1df77..a9c8bf9df 100644 --- a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/JourneyOverlay.java +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/JourneyOverlay.java @@ -36,7 +36,7 @@ public static JourneyOverlay InProgressJourneyOverlay(final Context context, private final CycleMapView mapView_; private boolean initial_ = true; - private final TripData trip_; + private TripData trip_; private final Paint rideBrush_; private Path ridePath_; private int zoomLevel_ = -1; @@ -68,6 +68,11 @@ private void inProgress() { inProgress_ = true; } // inProgress + public void update(final TripData trip) { + trip_ = trip; + mapView_.invalidate(); + } // update + @Override public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) { if (shadow) diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/RecordingService.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/RecordingService.java index e67552e57..42694fd22 100644 --- a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/RecordingService.java +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/RecordingService.java @@ -20,12 +20,14 @@ import android.os.Handler; import android.os.IBinder; -public class RecordingService extends Service implements LocationListener { +class RecordingService + extends Service + implements LocationListener { private static int updateDistance = 5; // metres private static int updateTime = 5000; // milliseconds private static final int NOTIFICATION_ID = 1; - private TrackListener listener; + private TrackListener trackListener_; private LocationManager locationManager_ = null; // Bike bell variables @@ -69,50 +71,50 @@ public void onDestroy() { } // onDestroy @Override - public IBinder onBind(final Intent intent) { - return new MyServiceBinder(this); + public IBinder onBind( + final Intent intent) { + return new ServiceBinder(this); } @Override - public int onStartCommand(final Intent intent, final int flags, final int startId) { + public int onStartCommand( + final Intent intent, + final int flags, + final int startId) { return Service.START_STICKY; } // onStartCommand - private static class MyServiceBinder extends Binder implements IRecordService { + private static class ServiceBinder extends Binder implements IRecordService { private final RecordingService rs_; - public MyServiceBinder(final RecordingService rs) { + public ServiceBinder(final RecordingService rs) { rs_ = rs; } // MyServiceBinder public int getState() { return rs_.state_; } - public boolean hasRiderStopped() { - return rs_.hasRiderStopped(); - } public TripData startRecording() { return rs_.startRecording(); } - public void stopRecording() { - if (rs_.trip_.dataAvailable()) - rs_.finishRecording(); - else - rs_.cancelRecording(); + public TripData stopRecording() { + return rs_.stopRecording(); } // stopRecording - public void setListener(TrackListener ra) { - rs_.listener = ra; - rs_.notifyUpdate(); + public void setListener( + final TrackListener ra) { + rs_.trackListener_ = ra; } } // class MyServiceBinder // ---end SERVICE methods ------------------------- - public TripData startRecording() { + private TripData startRecording() { if (state_ == STATE_RECORDING) return trip_; - startForeground(NOTIFICATION_ID, createNotification("Recording ...", Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT)); + startForeground(NOTIFICATION_ID, createNotification( + "Recording ...", + Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT)); state_ = STATE_RECORDING; trip_ = TripData.createTrip(this); @@ -120,33 +122,42 @@ public TripData startRecording() { curSpeedMph_ = 0.0f; // Start listening for GPS updates! - locationManager_.requestLocationUpdates(LocationManager.GPS_PROVIDER, updateTime, updateDistance, this); + locationManager_.requestLocationUpdates( + LocationManager.GPS_PROVIDER, + updateTime, + updateDistance, + this); startTimers(); + if (trackListener_ != null) + trackListener_.started(trip_); + return trip_; } - public long finishRecording() { + private TripData stopRecording() { + if (trip_.dataAvailable()) + finishRecording(); + else + cancelRecording(); + return trip_; + } // stopRecording + + private void finishRecording() { state_ = STATE_FULL; clearUp(); trip_.recordingStopped(); - - listener.completed(trip_); - - return trip_.id(); } - public void cancelRecording() { + private void cancelRecording() { if (trip_ != null) trip_.dropTrip(); clearUp(); - listener.abandoned(trip_); - state_ = STATE_IDLE; } // cancelRecording @@ -193,13 +204,15 @@ private void stopTimers() { // LocationListener implementation: @Override - public void onLocationChanged(Location loc) { + public void onLocationChanged( + final Location loc) { updateTripStats(loc); trip_.addPointNow(loc); notifyUpdate(); } // onLocationChanged - private void updateTripStats(Location newLocation) { + private void updateTripStats( + final Location newLocation) { final float spdConvert = 2.2369f; // Stats should only be updated if accuracy is decent @@ -227,8 +240,9 @@ private NotificationManager nm() { return (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); } // nm - private Notification createNotification(final String tickerText, - final int flags) { + private Notification createNotification( + final String tickerText, + final int flags) { final Notification notification = new Notification(R.drawable.icon25, tickerText, System.currentTimeMillis()); notification.flags = flags; final Intent notificationIntent = new Intent(this, RecordingService.class); @@ -237,8 +251,9 @@ private Notification createNotification(final String tickerText, return notification; } // createNotification - private void showNotification(final String tickerText, - final int flags) { + private void showNotification( + final String tickerText, + final int flags) { final Notification notification = createNotification(tickerText, flags); nm().notify(NOTIFICATION_ID, notification); } // showNotification @@ -253,8 +268,7 @@ private void remindUser() { } // remindUser private void clearNotifications() { - NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationManager.cancel(NOTIFICATION_ID); + nm().cancel(NOTIFICATION_ID); } // clearNotifications private boolean hasRiderStopped() { @@ -282,12 +296,12 @@ private boolean hasRiderStopped() { } // checkForAutoStop private void notifyUpdate() { - if (listener == null) + if (trackListener_ == null) return; - listener.updateStatus(curSpeedMph_, trip_); + trackListener_.updateStatus(curSpeedMph_, trip_); if (hasRiderStopped()) - listener.riderHasStopped(trip_); + trackListener_.riderHasStopped(trip_); } // notifyStatusUpdate } // RecordingService diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackListener.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackListener.java index bdfbd48ab..8db64a5a0 100644 --- a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackListener.java +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackListener.java @@ -1,6 +1,8 @@ package net.cyclestreets.track; public interface TrackListener { + void started(TripData trip); + void updateStatus(float currentMph, TripData trip); void riderHasStopped(TripData trip); diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Tracker.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Tracker.java index 140e973cb..f68b1f3e3 100644 --- a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Tracker.java +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/Tracker.java @@ -9,11 +9,14 @@ import java.util.List; public class Tracker { + public static TrackerControl create(final Context context, final TrackListener listener) { + return Controller.create(context, listener); + } // create + public static void checkStatus(final Context context, final StatusCallback callback) { // check to see if already recording here Intent rService = new Intent(context, RecordingService.class); ServiceConnection sc = new ServiceConnection() { - public void onServiceDisconnected(ComponentName name) {} public void onServiceConnected(ComponentName name, IBinder service) { IRecordService rs = (IRecordService)service; int state = rs.getState(); @@ -28,6 +31,7 @@ public void onServiceConnected(ComponentName name, IBinder service) { context.unbindService(this); // race? this says we no longer care } + public void onServiceDisconnected(ComponentName name) {} }; // This needs to block until the onServiceConnected (above) completes. // Thus, we can check the recording status before continuing on. diff --git a/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackerControl.java b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackerControl.java new file mode 100644 index 000000000..7397be9ce --- /dev/null +++ b/libraries/cyclestreets-track/src/main/java/net/cyclestreets/track/TrackerControl.java @@ -0,0 +1,6 @@ +package net.cyclestreets.track; + +public interface TrackerControl { + void start(); + void stop(); +} // TrackerControl