Search code examples
javaandroidgpsandroid-gps

Need to get updated location/data from onLocationChanged


Just a warning: I'm really not proud of this code that I've written, but I just need it to work anyhow. Don't judge me too harshly.

Hey everyone, I'm programming a speedometer android app, and I'm running into a basic issue. I need to calculate the distance between two GPS coordinates using the Android location service (I know the Fused Location Provider is superior but please bear with this).

The location listener classes are in a Java file called CurrentLocationListener.java. So far, I've been able to get the two coordinates and get the distance between the updated coordinate and the old coordinate inside the above java file, but I need some way of passing it to the MainActivity.java file where I can update my UI with the said distance. The codes for the two java files are below:

MainActivity.java

package com.example.speedometer;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.Thread;

public class MainActivity extends AppCompatActivity {

    CurrentLocationListener currentLocationListener;
    LocationManager locationManager;
    TextView textCurrentSpeed, textOdometer, textAvgSpeed;
//    MainActivity mainActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        mainActivity = this;

        currentLocationListener = new CurrentLocationListener();
        textCurrentSpeed = findViewById(R.id.dispCurrentSpeed);
        textOdometer = findViewById(R.id.dispOdometer);
        textAvgSpeed = findViewById(R.id.dispAvgSpeed);

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            Toast.makeText(this, "Location permission not granted. Please grant permission.", Toast.LENGTH_LONG).show();
            alertbox();
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 5, currentLocationListener);
    }

    protected void alertbox()
    {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }
    }

    public void updateLocation() {
        Location location = null;
        double[] coords = new double[2];

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "Permission to gps not granted. Grant permissions and try again or restart the application.", Toast.LENGTH_LONG).show();
            alertbox();
        }
        else {
            location = locationManager.getLastKnownLocation(Context.LOCATION_SERVICE);
        }

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5, currentLocationListener);

        if (location == null)
        {
            location = currentLocationListener.getLocation();
        }
        else {
            Toast.makeText(this, "unknown location", Toast.LENGTH_LONG).show();
        }

    }

    @SuppressLint("SetTextI18n")
    protected void main()
    {
        double oldlat, newlat, oldlong, newlong;
        double[] coords;
        double odometer = 0, timeElapsed = 0, distanceTravelled, currentSpeed, avgSpeed;
        double startTime, endTime;

//        coords = updateLocation();
//        oldlong = coords[0];
//        oldlat = coords[1];



//        while(true)
//        {
//            startTime = System.nanoTime();
//            try
//            {
//                Thread.sleep(10000);
//            } catch (InterruptedException e)
//            {
//                e.printStackTrace();
//            }
//
//            coords = updateLocation();
//
//            newlong = coords[0];
//            newlat = coords[1];
//            System.out.println(newlat + " " + newlong);
//
//            distanceTravelled = earthDistance(oldlat, oldlong, newlat, newlong);
//
//            odometer += distanceTravelled;
//
//            endTime = System.nanoTime();
//
//            timeElapsed += (endTime - startTime);
//            currentSpeed = (distanceTravelled)/((endTime-startTime)/1e9); // m/s to km/hr
//            avgSpeed = (odometer/1000)/(timeElapsed/1e9);
//
////            System.out.println("odo: " + odometer);
////            System.out.println("currspeed: " + currentSpeed);
//            System.out.println("dist: " + distanceTravelled);
//
//            textCurrentSpeed.setText(currentSpeed + " m/s");
//            textOdometer.setText((odometer) + " m");
//            textAvgSpeed.setText(avgSpeed + " km/hr");
//
//            oldlat = newlat;
//            oldlong = newlong;
//        }
    }


    protected double earthDistance(double lat1, double lon1, double lon2, double lat2)
    {

        final double R = 6371e3; // Radius of the earth

        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return R * c;
    }

    public void setTextFields(double distance)
    {
        System.out.println(distance);
    }

    public void buttonStart(View MainActivity)
    {
//        main();
        updateLocation();
    }
}

CurrentLocationListener.java

package com.example.speedometer;

import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.Message;
import android.widget.TextView;
import android.view.View;
import android.content.Context;

public class CurrentLocationListener implements LocationListener {
    Location myLocation;
    double templat = 404, templong = 404;
    double odometer = 0, totalTime = 0, currentDist, currentSpeed, avgSpeed;
    TextView textCurrentSpeed, textOdometer, textAvgSpeed;
    MainActivity mainActivity;


    public Location getLocation()
    {
        return myLocation;
    }

    @Override
    public void onLocationChanged(Location location)
    {
//        textCurrentSpeed = mainActivity.findViewById(R.id.dispCurrentSpeed);
//        textOdometer = mainActivity.findViewById(R.id.dispOdometer);
//        textAvgSpeed = mainActivity.findViewById(R.id.dispAvgSpeed);
        double startTime, endTime;
        myLocation = location;
        if (templat == 404 && templong == 404)
        {
            templat = location.getLatitude();
            templong = location.getLongitude();
        }
        else
        {
            currentDist = earthDistance(location.getLatitude(), location.getLongitude(), templong, templat);
            templat = location.getLatitude();
            templong = location.getLongitude();
            System.out.println("dist: " + currentDist);
            odometer += currentDist;
            totalTime += 10;
            currentSpeed = currentDist/10;
            avgSpeed = odometer/totalTime;

            mainActivity.setTextFields(odometer);
//            textCurrentSpeed.setText(currentSpeed + " m/s");
        }
//        System.out.println("update");
//        System.out.println(location.getLatitude() + " " + location.getLongitude());
    }

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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    protected double earthDistance(double lat1, double lon1, double lon2, double lat2)
    {

        final double R = 6371e3; // Radius of the earth

        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return R * c;
    }
}

My main objective is to update the TextView fields with the calculated values, like the Odometer reading. I know there is a lot of repeated code and comments, but I am honestly out of my depth and desperately need help. Let me know if any more information is needed. Thanks in advance.


Solution

  • You can make your MainActivity implements LocationListener:

    public class MainActivity 
    extends 
    AppCompactActivity implements 
    LocationListener {
    //Rest of the code
    
    @Override
    public void 
    onLocationChanged(Location 
    location){
    //do your stuff       
     }
    
    @Override
    public void onStatusChanged(String 
    provider, int status, Bundle 
    extras) {
    //do your stuff
    }
    
    @Override
    public void 
    onProviderEnabled(String provider) 
    {
    //do your stuff
    }
    
    @Override
    public void 
    onProviderDisabled(String 
    provider) {
    //do your stuff
    }
        }