//PERMISOS EN EL ANDROIDMANIFIEST.XML
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        tools:ignore="CoarseFineLocation"></uses-permission>
    <uses-feature android:name="android.hardware.location.gps"></uses-feature>
				
			
				
					<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvUbicacion"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Ubicación GPS"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.693" />

    <TextView
        android:id="@+id/tvDistanciaRecorrida"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Distancia Recorrida:"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="528dp" />

    <TextView
        android:id="@+id/cronometro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="28dp"
        android:text="00:00:000"
        android:textSize="30sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout" />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnIniciar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Iniciar" />

        <Button
            android:id="@+id/btnDetener"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Detener" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
				
			
				
					package com.example.tracking;

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

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView cronometro;
    private Button btnIniciar, btnDetener;
    private long startTime = 0L;
    private Handler customHandler = new Handler();
    long timeInMilliseconds = 0L;
    long timeSwapBuff = 0L;
    long updatedTime = 0L;
    TextView tvUbicacion;
    TextView tvDistanciaRecorrida;
    double distanciaRecorrida = 0;
    Location lastLocation = null;

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

        cronometro = (TextView) findViewById(R.id.cronometro);
        btnIniciar = (Button) findViewById(R.id.btnIniciar);
        btnDetener = (Button) findViewById(R.id.btnDetener);
        tvUbicacion = (TextView)findViewById(R.id.tvUbicacion);
        tvDistanciaRecorrida = (TextView)findViewById(R.id.tvDistanciaRecorrida);

        btnIniciar.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                startTime = SystemClock.uptimeMillis();
                customHandler.postDelayed(updateTimerThread, 0);
                //funcionalidad del gps
                LocationManager locationManager = (LocationManager) MainActivity.this.getSystemService(Context.LOCATION_SERVICE);
                LocationListener locationListener = new LocationListener() {
                    @Override
                    public void onLocationChanged(Location location) {
                        tvUbicacion.setText("Latitud: " + location.getLatitude() + " Longitud: " + location.getLongitude());
                        if (lastLocation != null) {
                            //Si la distancia recorrida es mayor de 5 metros
                            if (location.distanceTo(lastLocation) >= 5) {
                                distanciaRecorrida += location.distanceTo(lastLocation);
                            }
                        }
                        lastLocation = location;
                        tvDistanciaRecorrida.setText("Distancia recorrida: " + distanciaRecorrida + " metros");
                    }

                    @Override
                    public void onStatusChanged(String s, int i, Bundle bundle) {

                    }

                    @Override
                    public void onProviderEnabled(String s) {

                    }

                    @Override
                    public void onProviderDisabled(String s) {

                    }
                };
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
                } else {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
                }
            }
        });

        btnDetener.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                timeSwapBuff += timeInMilliseconds;
                customHandler.removeCallbacks(updateTimerThread);
            }
        });


    }

    private Runnable updateTimerThread = new Runnable() {
        public void run() {
            timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
            updatedTime = timeSwapBuff + timeInMilliseconds;
            int secs = (int) (updatedTime / 1000);
            int mins = secs / 60;
            secs = secs % 60;
            int milliseconds = (int) (updatedTime % 1000);
            cronometro.setText("" + mins + ":" + String.format("%02d", secs) + ":" + String.format("%03d", milliseconds));
            customHandler.postDelayed(this, 0);
        }
    };
}


				
			
				
					//SI QUEREMOS QUE FUNCIONE A MODO DE TAXIMETRO

//Lo de la shared prederence de la hora de inicio es para solucionar el problema cuando la app
//trabaja en segundo plano o se cierra por accidente

package com.example.tracking;

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

import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private TextView cronometro;
    private Button btnIniciar, btnDetener;
    private long startTime = 0L;
    private Handler customHandler = new Handler();
    long timeInMilliseconds = 0L;
    long timeSwapBuff = 0L;
    long updatedTime = 0L;
    TextView tvUbicacion;
    TextView tvDistanciaRecorrida;
    TextView tvCostoTotal;
    double distanciaRecorrida = 0;
    Location lastLocation = null;

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

        cronometro = (TextView) findViewById(R.id.cronometro);
        btnIniciar = (Button) findViewById(R.id.btnIniciar);
        btnDetener = (Button) findViewById(R.id.btnDetener);
        tvUbicacion = (TextView)findViewById(R.id.tvUbicacion);
        tvDistanciaRecorrida = (TextView)findViewById(R.id.tvDistanciaRecorrida);
        tvCostoTotal = (TextView)findViewById(R.id.tvCostoTotal);

        // Obtener una instancia de SharedPreferences
        SharedPreferences sharedPreferences = getSharedPreferences("misPreferencias", MODE_PRIVATE);

        btnIniciar.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {


                // Obtener la hora actual en milisegundos
                long horaInicio = System.currentTimeMillis();
                // Guardar la hora de inicio en shared preferences
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putLong("horaInicio", horaInicio);
                editor.apply();

                startTime = SystemClock.uptimeMillis();
                customHandler.postDelayed(updateTimerThread, 0);
                //funcionalidad del gps
                LocationManager locationManager = (LocationManager) MainActivity.this.getSystemService(Context.LOCATION_SERVICE);
                LocationListener locationListener = new LocationListener() {
                    @Override
                    public void onLocationChanged(Location location) {
                        tvUbicacion.setText("Latitud: " + location.getLatitude() + " Longitud: " + location.getLongitude());
                        if (lastLocation != null) {
                            //Si la distancia recorrida es mayor de 5 metros
                            if (location.distanceTo(lastLocation) >= 5) {
                                distanciaRecorrida += location.distanceTo(lastLocation);
                            }
                        }
                        lastLocation = location;
                        tvDistanciaRecorrida.setText("Distancia recorrida: " + distanciaRecorrida + " metros");
                    }

                    @Override
                    public void onStatusChanged(String s, int i, Bundle bundle) {

                    }

                    @Override
                    public void onProviderEnabled(String s) {

                    }

                    @Override
                    public void onProviderDisabled(String s) {

                    }
                };
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
                } else {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
                }
            }
        });

        btnDetener.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                // Detener el hilo del cronómetro
                // Actualizar la variable timeSwapBuff con la diferencia entre el tiempo actual y el tiempo de inicio
                timeSwapBuff += timeInMilliseconds;
                customHandler.removeCallbacks(updateTimerThread);

                // Obtener la hora de inicio guardada en shared preferences
                long horaInicio = sharedPreferences.getLong("horaInicio", 0);
                // Obtener la hora actual en milisegundos
                long horaActual = System.currentTimeMillis();
                // Calcular la diferencia entre las dos horas en milisegundos
                long diferencia = horaActual - horaInicio;
                // Convertir la diferencia a minutos
                long minutos = diferencia / 1000 / 60;
                // Mostrar los minutos transcurridos en el TextView
                //tvSegundos.setText(String.valueOf(minutos));


                // Calcular el costo total de la carrera
                double costoTotal = 6800; // Carrera mínima
                double valorPorMetro = 124; // Valor por cada 78 metros
                double valorPorSegundoEspera = 200; // Valor de espera por 60 segundos

                // Convertir el tiempo en milisegundos a segundos
                double tiempoTotal = (double)timeInMilliseconds / 1000;

                // Código a ejecutar si distanciaRecorrida es menor o igual a 2400 metros
                if (distanciaRecorrida >= 2400) {
                    // Calcular el costo de la distancia recorrida
                    costoTotal += valorPorMetro * (distanciaRecorrida / 78);
                }

                if(minutos >= 1 ){
                    // Calcular el costo del tiempo de espera
                    costoTotal += valorPorSegundoEspera * ((minutos * 60)  / 60.0);
                }

                tvCostoTotal.setText("$"+Math.round(costoTotal));

                // Mostrar el costo total en un toast
                Context context = getApplicationContext();
                CharSequence text = "Costo total: $" + Math.round(costoTotal);
                int duration = Toast.LENGTH_SHORT;
                Toast toast = Toast.makeText(context, text, duration);
                toast.show();
            }
        });

    }

    private Runnable updateTimerThread = new Runnable() {
        public void run() {
            timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
            updatedTime = timeSwapBuff + timeInMilliseconds;
            int secs = (int) (updatedTime / 1000);
            int mins = secs / 60;
            secs = secs % 60;
            int milliseconds = (int) (updatedTime % 1000);
            cronometro.setText("" + mins + ":" + String.format("%02d", secs) + ":" + String.format("%03d", milliseconds));
            customHandler.postDelayed(this, 0);
        }
    };
}