Android Open Source - activity-tracker Generic Workout






From Project

Back to project page activity-tracker.

License

The source code is released under:

MIT License

If you think the Android project activity-tracker listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.hopto.mjancola.model;
//from   ww  w  . j a v  a 2 s  .co m
import android.content.Context;
import android.location.Location;
import android.util.Log;
import com.google.android.gms.location.DetectedActivity;
import org.hopto.mjancola.utility.Converter;
import org.hopto.mjancola.utility.SettingsHelper;
import org.hopto.mjancola.utility.WorkoutDataSource;

public class GenericWorkout implements GenericMovement
{
    private static final long   MIN_DISTANCE_MILES_TIMES_ONEHUNDRED = 10L;  // tenth of a mile
    private final        String TAG                                 = "****" + GenericWorkout.class.getSimpleName();
    //public static  long   STOP_THRESHOLD_MS; //                   = 1000L * 60L * 3L;  // 3 minutes
    //public static  long   ACTIVITY_CHANGE_THRESHOLD_MS; //        = 1000L * 20L;  // 20 seconds
    private static final String NO_ACTIVITY                         = "NONE";
    private              String pendingActivity                     = NO_ACTIVITY;
    //private static double MIN_SPEED; //                           = 2.0 * LearningMode.MPH_TO_METERS_PER_SEC;
    //public static  double MIN_DURATION_MS; //                     = 1 * 60 * 1000; // 1 minutes
    private WorkoutType workoutType;
    long stopPendingTime              = NO;  // time when zero speed detected
    long differentActivityPendingTime = NO;  // time when different activity detected

    private String startReason;
    private long   exceedsSpeedPendingTime;
    private static final long NO = 0L;
    private WorkoutDataSource dataSource;

    double currentSpeed;
    private Workout workout;
    private Context context;
    private static SettingsHelper settings;

    // TEST CODE
//        private static double testSpeed = (3* .44704);
//        private double[] testLatitudes = {40.095253, 40.095270, 40.095270, 40.091867};
//        private double[] testLongitudes = {-75.211375, -75.211390, -75.211222, -75.224662};
//        private static final double START_LATITUDE    = 40.095253; // 40.095253, -75.211375
//    private static final double START_LONGITUDE   = -75.211375;
//    private static final double SMALL_CHANGE_LATITUDE = 40.095270; // 40.095270, -75.211390
//    private static final double SMALL_CHANGE_LONGITUDE =  -75.211390;
//    private static final double END_LATITUDE       = 40.095136; // 40.095136, -75.211222
//    private static final double END_LONGITUDE = -75.211222;
//    private static int counter = 0;
// END TEST CODE

    public static GenericWorkout createWithData( WorkoutType workoutType, Workout workout, String startReason, Context context )
    {
        settings = SettingsHelper.getInstance(context);
        GenericWorkout newWorkout = new GenericWorkout();
        newWorkout.workoutType = workoutType;
// TEST CODE
//        testSpeed = testSpeed + (5 * .44704);

        newWorkout.workout = workout;
        newWorkout.startReason = startReason;
        newWorkout.context = context;

        newWorkout.dataSource = WorkoutDataSource.create( context );
        newWorkout.currentSpeed = 0L;
        return newWorkout;
    }

    public static GenericWorkout create( WorkoutType workoutType, Context context, String startReason )
    {
        Workout newWorkout = new Workout(workoutType.getName(), workoutType.getDistanceThreshold());
        return createWithData( workoutType, newWorkout, startReason, context );
    }



    @Override
    public long getDurationMS()
    {
        return workout.getDurationMS();
    }

    @Override
    public GenericMovement addLocation( Location location )
    {
        // according to Google, all locations will have Lat/Long
        // so first add the speed to the array
        appendDataPoint(new DataPoint(location.getTime(), location.getLatitude(), location.getLongitude()));
// TEST CODE
//        counter++;
//        if (counter < testLatitudes.length)
//        {
//            appendDataPoint(new DataPoint(location.getTime(), testLatitudes[counter], testLongitudes[counter]));
//        }
// END TEST CODE
        double speed = 0;
        if (location.hasSpeed() == true)
        {
            speed = location.getSpeed();
        }
// TEST CODE
//          double speed = testSpeed;
        GenericMovement newMovement = addSpeed(speed);
        if (newMovement != null)
        {
            return newMovement;
        }

        return null;

    }


    private void appendDataPoint(DataPoint newData)
    {
        workout.addData(newData);
    }

    GenericMovement addSpeed( double speed )
    {
        currentSpeed = speed;

        if (currentSpeed <= settings.getMinSpeedMetersPerSecond())
        {
            // exceed no longer pending
            exceedsSpeedPendingTime = NO;

            if (stopPendingTime != NO)
            {
                long stopPending = System.currentTimeMillis() - stopPendingTime;
                if (stopPending > settings.getStopThresholdMS() )
                {
                    persistSelf(LearningMode.TIME_REASON);
                    return new LearningMode(context);
                }
            }
            else
            {
                // start the stop timer
                stopPendingTime = System.currentTimeMillis();
            }

        }
        else if (currentSpeed > workoutType.getMaxSpeed())
        {
            // stop no longer pending
            stopPendingTime = NO;

            if (exceedsSpeedPendingTime != NO)
            {
                long pendingTime = System.currentTimeMillis() - exceedsSpeedPendingTime;
//                if (pendingTime > workoutType.getTimeThreshold() )
                // must be at increased speed for at least 20 seconds to actually promote
                if (pendingTime > (20L*1000L) )
                {
                    // pass the data on to the next type
                    if (workoutType.getNext() != null)
                    {
                        return GenericWorkout.createWithData(workoutType.getNext(), workout, LearningMode.TIME_REASON, context);
                    }
                    else
                    {
                        // we are going faster than any known activity
                        // discard and start again
                        return new LearningMode(context);
                    }
                }
                // else noop
            }
            else
            {
                exceedsSpeedPendingTime = System.currentTimeMillis();
            }
        }
        else
        {
            // in range
            stopPendingTime = NO;
            exceedsSpeedPendingTime = NO;
            // TODO
            // add to average
        }

        return null;
    }

    private boolean speedInRange(double speed)
    {
        if ((speed >= workoutType.getMinSpeed()) && (speed <= workoutType.getMaxSpeed()))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private void persistSelf(String endReason)
    {
        // TODO - might need another variant of this method which
        // does not subtract if we are persisting due to a different reason - i.e
        // different Motion Detected
        long actualDurationMS = getDurationMS();
        if (endReason.equals(LearningMode.TIME_REASON))  //
        {
            actualDurationMS = actualDurationMS - settings.getStopThresholdMS();
        }


        if ((actualDurationMS > settings.getMinDurationMS()) &&
            (Double.valueOf(Converter.formatDistance(Converter.formatDistanceTimeOneHundred( getDistance() ))) > MIN_DISTANCE_MILES_TIMES_ONEHUNDRED ))
        {
//            public WorkoutDAO createWorkout( String type, long start, long distance, long duration, long avgSpeed, String startReason, String endReason )
            if (dataSource.createWorkout( workoutType.getName(),
                                          workout.getStartTimeMillis(),
                                          Converter.formatDistanceTimeOneHundred(getDistance()),
                                          actualDurationMS,
                                          0L,
                                          startReason,
                                          endReason ) == null)
            {
                // failed, try to add an error log
                dataSource.createWorkout("FAILED", workout.getStartTimeMillis(), 0L, 0L, 0L, "", "");
            }


        }
        // else noop


    }

    @Override
    public GenericMovement addDetectedActivity( DetectedActivity motion )
    {
        String newActivity = Converter.getMovementFromDetectedActivity(motion, context);
        if (newActivity != null)
        {
            if ( !newActivity.equals( getName() ))
            {
                // if same activity (other than current), keep adding, otherwise reset
                if ( pendingActivity.equals( newActivity ))
                {
                    long changePending = System.currentTimeMillis() - differentActivityPendingTime;
                    if (changePending > settings.getActivityChangeThresholdMS() )
                    {
                        // detected something other than what we were doing with a high level of confidence
                        // CAR to WALK - save and start new
                        // WALK to CAR - generally, promote but could be save and start new

                        // if walking, allow promote to run, bike, drive
                        // else if run, allow promote to bike, drive
                        // else if bike, allow promote to drive

                        if (pendingActivity.equals( LearningMode.CAR_NAME ))
                        {
                            if ( (getName().equals( LearningMode.BIKE_NAME )) ||
                                 (getName().equals( LearningMode.RUN_NAME )) ||
                                 (getName().equals( LearningMode.WALK_NAME )) )
                            {
                                return GenericWorkout.createWithData(LearningMode.driving, workout, LearningMode.CAR_NAME, context);
                            }
                        }
                        else if (pendingActivity.equals( LearningMode.BIKE_NAME))
                        {
                            if ( (getName().equals( LearningMode.RUN_NAME )) ||
                                 (getName().equals( LearningMode.WALK_NAME )) )
                            {
                                return GenericWorkout.createWithData(LearningMode.biking, workout, LearningMode.BIKE_NAME, context);
                            }

                        }
                        else if (pendingActivity.equals( LearningMode.RUN_NAME ))
                        {
                            if (getName().equals( LearningMode.WALK_NAME ))
                            {
                                return GenericWorkout.createWithData(LearningMode.running, workout, LearningMode.WALK_NAME, context);
                            }
                        }
                        else if ( (pendingActivity.equals(LearningMode.IDLE)) ||
                                  (pendingActivity.equals( LearningMode.TILT)) ||
                                  (pendingActivity.equals(LearningMode.UNKNOWN)) )
                        {
                            // just ignore for now - Speed zeros will capture this
                            Log.e( TAG, getName() + ": detected: " + newActivity + " ignoring" );
                        }
                        else if ( (pendingActivity.equals( LearningMode.FOOT_NAME )) &&
                                  (( getName().equals( LearningMode.WALK_NAME )) || (getName().equals( LearningMode.RUN_NAME )) ) )
                        {
                            // ignore ON_FOOT detection if this is a walk or run
                            resetPendingActivity( newActivity );
                        }
                        else // else activity demotion, save and start new
                        {
                            persistSelf( newActivity );
                            return new LearningMode( context );
                        }
                    }
                }
                else
                {
                    // got some other activity
                    resetPendingActivity( newActivity );
                }
            }
            else  // detected current activity - reset
            {
                // reset change timer
                resetPendingActivity( NO_ACTIVITY );
                Log.e( TAG, getName() + ": detected: " + newActivity + " ignoring" );
            }
        }
        return null;

    }

    private void resetPendingActivity( String newActivity )
    {
        differentActivityPendingTime = System.currentTimeMillis();
        pendingActivity = newActivity;
    }

    public String getName()
    {
        return workoutType.getName();
    }

    @Override
    public double getSpeed()
    {
        return currentSpeed;
    }

    @Override
    public double getDistance()
    {
        return workout.getDistance();
    }
}




Java Source Code List

org.hopto.mjancola.ActivityTrackerApplication.java
org.hopto.mjancola.activity.ActivityRecognitionActivity.java
org.hopto.mjancola.activity.ActivityTracker.java
org.hopto.mjancola.activity.DemoDetailsList.java
org.hopto.mjancola.activity.DemoDetails.java
org.hopto.mjancola.activity.EditWorkoutDAOActivity.java
org.hopto.mjancola.activity.FeatureView.java
org.hopto.mjancola.activity.LegalInfoActivity.java
org.hopto.mjancola.activity.ListWorkoutsActivity.java
org.hopto.mjancola.activity.MyLocationDemoActivity.java
org.hopto.mjancola.activity.SpeedActivity.java
org.hopto.mjancola.activity.UserSettingsActivity.java
org.hopto.mjancola.adapter.WorkoutDAOAdapter.java
org.hopto.mjancola.fragment.EditWorkoutDAOFragment.java
org.hopto.mjancola.model.DataPoint.java
org.hopto.mjancola.model.GenericMovement.java
org.hopto.mjancola.model.GenericWorkout.java
org.hopto.mjancola.model.LearningMode.java
org.hopto.mjancola.model.MyMovement.java
org.hopto.mjancola.model.WorkoutTotal.java
org.hopto.mjancola.model.WorkoutType.java
org.hopto.mjancola.model.Workout.java
org.hopto.mjancola.service.ActivityRecognitionService.java
org.hopto.mjancola.service.MovementListenerService.java
org.hopto.mjancola.service.MovementTrackerService.java
org.hopto.mjancola.utility.Converter.java
org.hopto.mjancola.utility.MySQLiteHelper.java
org.hopto.mjancola.utility.SettingsHelper.java
org.hopto.mjancola.utility.WorkoutDAO.java
org.hopto.mjancola.utility.WorkoutDataSource.java