Angel Angel - 4 months ago 15
Java Question

Using CountDown Timer

I'm using a

CountDownTimer
but it doesn't seem to be working properly. I need to capture speed; if it goes above a certain speed, do nothing.. I'm just logging speed. But if it goes under a certain speed, I need to fire up a notification after a three minute countdown timer.

Can someone look at my code and see what I'm doing wrong? If the speed goes above, it's fine.. it does not run the timer, but the issue is when it goes under a certain speed. Sometimes the timer works, other times, no. Sometimes it just logs 0 and doesn't show the timer.

I know it's in the conditions, I've just been looking at it over and over, and I can't see what may be wrong. Four eyes are better than two?

Any help is appreciated. Thanks.

public class SpeedManagerService extends Service implements IBaseGpsListener {

private static final String TAG = "SpeedCheckerService";
public boolean timer_started = false;
float nCurrentSpeed = 0;

CountDownTimer timer = new CountDownTimer( 180000, 1000 ) {

public void onTick(long millisUntilFinished) {
Log.i( "Current Ride", "Timer countdown: " + millisUntilFinished / 1000 +
" seconds." );
timer_started = true;
if (nCurrentSpeed > 0)
timer.cancel();
}

public void onFinish() {
Intent resultIntent = new Intent( SpeedManagerService.this, CurrentRide.class );
NotificationCompat.Builder builder = new NotificationCompat
.Builder( SpeedManagerService.this );
builder.setContentText( "Click to save Current Ride info" );
builder.setSmallIcon( R.mipmap.ic_launcher );
builder.setContentTitle( "Did you just pay for a Ride?" );
builder.setContentIntent( PendingIntent.getActivity( SpeedManagerService.this, 0,
resultIntent, 0 ) );
NotificationManagerCompat.from( SpeedManagerService.this ).notify( 0,
builder.build() );
}
}
.start();

@Override
public void onCreate() {
Log.i( TAG, "Service onCreate" );

LocationManager locationManager = (LocationManager) this.
getSystemService( Context.LOCATION_SERVICE );
if (ActivityCompat.checkSelfPermission( this, android.Manifest.permission
.ACCESS_FINE_LOCATION )
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this,
android.Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager
.PERMISSION_GRANTED) {

return;
}
locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, this );
SpeedManagerService.this.updateSpeed( null );
}

// On start, run speed service, and return sticky so if error, service will restart
// on its own
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i( TAG, "Service onStartCommand" );
updateSpeed( null );
return Service.START_STICKY;
}

public void updateSpeed(SpeedLocation location) {
Log.i( "Current Ride: ", "User is in a Vehicle. Speed is: " +
Math.round( nCurrentSpeed * 2.23694 / 3.6f ) + " mph. " );

// If a location exists, get speed
if (location != null) {
nCurrentSpeed = location.getSpeed();
}

// If speed is 0 and timer starts, don't start
if(nCurrentSpeed == 0 && timer_started) {
timer_started=false;
}

// In meters/second, if speed goes above 8 mph, then it will just log the speed as miles/hour.

if (nCurrentSpeed >= 8) {
}
// However, if speed falls below 5 mph, then countdown timer
// of 3 minutes will begin.
if (nCurrentSpeed <= 5 || nCurrentSpeed == 0) {
timer_started = true;

timer.start();
}
}


// Binder returns null because it's not used
@Override
public IBinder onBind(Intent intent) {
return null;
}

// If location changes, update location and speed.
@Override
public void onLocationChanged(Location location) {
if (location != null) {
SpeedLocation myLocation = new SpeedLocation( location, true );
this.updateSpeed( myLocation );
}
}

// If provider is disabled, timer won't run either
@Override
public void onProviderDisabled(String provider) {
timer_started = false;
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onGpsStatusChanged(int event) {
}
}


Here's a part of the logcat I get:

07-05 17:42:17.742 17023-17023/ I/Current Ride:: User is in a Vehicle. Speed is: 3 mph.
07-05 17:42:17.752 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.752 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.762 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.
07-05 17:42:17.772 17023-17023/ I/Current Ride: Timer countdown: 179 seconds.


and it will do this like 25 times before the next mileage is shown.

Answer

Judging by your comments, you require to make a slightly more sophisticated method of determining stopping. Something like this might be in order when starting your timer:

    if (nCurrentSpeed <= 5 && !timerStarted) {
        // Flag to indicate if vehicle has come to a complete stop
        vehicleStopped = (nCurrentSpeed == 0);
        // Indicate the timer is running
        timerStarted = true;
        timer.start();
    }

Then every tick:

    public void onTick(long millisUntilFinished) {
        Log.i( "Current Ride", "Timer countdown: " + millisUntilFinished / 1000 +
                " seconds." );
        if (vehicleStopped)
        {
            // Vehicle should have stopped, but it has started moving again
            if (nCurrentSpeed > 0)
            {
                timer.cancel();
                timerStarted = false;
            }
        }
        else if (nCurrentSpeed == 0)
        {
            // If vehicle has just slowed down,
            // once speed drops to zero we have stopped
            vehicleStopped = true;
        }
    }

The above seems to meet your requirements.

Comments