How to get the GPS distance moved in my position tracking app? Android, java

510 views Asked by At

So I have gotten the GPS to track and log my position continously from when I "press play". And I want to display the distance traveled, the average speed, the ascent and descent during the time spent.

I am logging my position with my "LocationsService.java"-class using the startLocationService(), which is looping through the LocationCallback (i think). I used the code I got from @TDIScott to create a hashmap that I put into a list.

public List<Map<Long, Location>> locationHistory = new ArrayList<>();

private LocationCallback locationCallback = new LocationCallback(){
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if(locationResult != null && locationResult.getLastLocation() != null){
            double latitude = locationResult.getLastLocation().getLatitude();
            double longitude = locationResult.getLastLocation().getLongitude();
            int altitude = (int) locationResult.getLastLocation().getAltitude();
            double speed = locationResult.getLastLocation().getSpeed();
            Log.d("LOCATION_UPDATE", latitude + ", " + longitude + ", " + altitude + ", " + speed + ", " + System.currentTimeMillis() + ", " + locationResult.getLastLocation());

            Map<Long, Location> temp = new HashMap<>();
            temp.put(System.currentTimeMillis(), locationResult.getLastLocation());
            locationHistory.add(temp);
        }
    }
};

private void startLocationService() {
    String channelId = "location_notification_channel";
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Intent resultIntent = new Intent();
    PendingIntent pendingIntent = PendingIntent.getActivity(
            getApplicationContext(),
            0,
            resultIntent,
            PendingIntent.FLAG_UPDATE_CURRENT
    );
    NotificationCompat.Builder builder = new NotificationCompat.Builder(
            getApplicationContext(),
            channelId
    );
    builder.setSmallIcon(R.mipmap.ic_launcher);
    builder.setContentTitle("iAthletics is recording"); //Endre til iAthletics is recording
    builder.setDefaults(NotificationCompat.DEFAULT_ALL);
    builder.setContentText("Running");
    builder.setContentIntent(pendingIntent);
    builder.setAutoCancel(false);
    builder.setPriority(NotificationCompat.PRIORITY_MAX);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (notificationManager != null && notificationManager.getNotificationChannel(channelId) == null) {
            NotificationChannel notificationChannel = new NotificationChannel(channelId, "Location Service", NotificationManager.IMPORTANCE_HIGH);
            notificationChannel.setDescription("This channel is used by location service");
            notificationManager.createNotificationChannel(notificationChannel);
        }
    }

    LocationRequest locationRequest = new LocationRequest();
    locationRequest.setInterval(1000);
    locationRequest.setFastestInterval(500);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); //TODO Husk eventuell permission check hvis det ikke funker
    startForeground(Constants.LOCATION_SERVICE_ID, builder.build());
}

Updated question: How can I access the location-objects in the list created in the "LocationSevice.java"-class, and calculate the average speed, distance, ascent and descent? From the activity-class.

PS: I have tried the second code provided by TDIScott and it does not work.

If it is needed, here is how the locationobject is stored in the log and probably in the list:

Location[fused 59,896346,10,621862 hAcc=31 et=+4d21h21m52s480ms alt=65.79999542236328 vel=0.10678082 bear=100.58679 vAcc=11 sAcc=??? bAcc=??? {Bundle[mParcelledData.dataSize=52]

2

There are 2 answers

4
Scott Johnson On

You can either store the data in a list of LocationResult so you say the distance between two times in more detail or just add them up as you go along.

Storing:

    List<Map<Long,LocationResult> locationHistory = new ArrayList();
    private LocationCallback locationCallback = new LocationCallback(){
@Override
public void onLocationResult(LocationResult locationResult) {
    super.onLocationResult(locationResult);
    if(locationResult != null && locationResult.getLastLocation() != null){
        double latitude = locationResult.getLastLocation().getLatitude();
        double longitude = locationResult.getLastLocation().getLongitude();
        int altitude = (int) locationResult.getLastLocation().getAltitude();
        Log.d("LOCATION_UPDATE", latitude + ", " + longitude + ", " + altitude);

        Map<Long, LocationResult> temp = new HashMap<>();
        temp.put(System.currentTimeMillis(), locationResult);

        locationHistory.add(temp);
    }
}
};

With the above, you now have a key of time in milliseconds and a value of LocationResult.

You can iterate via

    Map<Long, LocationResult> locationHistory = new HashMap<>();
    LocationResult temp = null;
    float distance = 0;
    for (Map.Entry<Long, LocationResult> entry : locationHistory.entrySet()) {
        if(temp != null){
            distance += temp.distanceTo(entry.getValue());
            temp = entry.getValue();
        }
    }

    textView.setText(String.valueOf(distance));

Now you have the LocationResult, add them up and do what you need. Be that calculate the distance, rise and decrease in altitude etc.

1
Akshay Mondal On

You can check for any package available for geolocation.