Navigation Menu

Skip to content

Commit

Permalink
Added Tracker.create, which provides a more straightforward interface…
Browse files Browse the repository at this point in the history
…. No need to faff around with binding to a service or any of that nonsense.
  • Loading branch information
jezhiggins committed Mar 4, 2015
1 parent eb9eb00 commit 671c5c9
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 44 deletions.
@@ -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
@@ -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);
}
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -69,84 +71,93 @@ 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);

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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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() {
Expand Down Expand Up @@ -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
@@ -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);

Expand Down
Expand Up @@ -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();
Expand All @@ -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.
Expand Down
@@ -0,0 +1,6 @@
package net.cyclestreets.track;

public interface TrackerControl {
void start();
void stop();
} // TrackerControl

0 comments on commit 671c5c9

Please sign in to comment.