I need to use the GPS in Android when the phone is blocked or we exit the application

4

I have in Android a class Map that collects the points of latitude and longitude to be able to realize several calculations like speed, etc.

The fact is that being an app to monitor a cycling route, the GPS should never stop working until the activity is over. The problem occurs when we block the phone or leave the app, since the gps stops updating its position and therefore the values and the route are not matched with reality.

The code I have is the following:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private GoogleMap mMap;
    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 10 meters
    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1; // 1 minute

    // Declaring a Location Manager
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;
    LocationRequest mLocationRequest;
    private Button stopButton;
    private Button pauseButton;
    private TextView distancia;
    private TextView velocidadMedia;
    private TextView velocidadMaxima;
    private TextView desnivelPostivo_txt;
    ArrayList<LatLng> points = new ArrayList<LatLng>();
    Polyline line;
    PolylineOptions lineOptions = null;
    Chronometer crono;
    Double distanciaTotal = 0.0;
    Double distanciaParcial = 0.0;
    double vMaxima = 0.0;
    double desnivelParcial = 0.0;
    double desnivelPositivo = 0.0;
    long TInicio, TFin, tiempo;
    PowerManager.WakeLock wakeLock=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        //layoutMaps=(LinearLayout)findViewById(R.id.layoutMaps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        stopButton = (Button) findViewById(R.id.stop_button);
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mGoogleApiClient.disconnect();
                //Marcamos el final en el ultimo punto tomado
                MarkerOptions markerOptions = new MarkerOptions();
                markerOptions.position(points.get(points.size() - 1));
                markerOptions.title("EEE");
                markerOptions.snippet("AAAA");
                markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                mCurrLocationMarker = mMap.addMarker(markerOptions);
                //Paramos el crono y sacamos un mensaje
                crono.stop();
                Toast.makeText(getApplicationContext(), "Actividad terminada", Toast.LENGTH_LONG).show();
            }
        });
        pauseButton = (Button) findViewById(R.id.pauseButton);
        pauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pauseButton.setBackgroundResource(R.drawable.start);
                mGoogleApiClient.disconnect();
                crono.stop();
            }
        });
        //Creamos el cronometro y lo ponemos en marcha
        crono = (Chronometer) findViewById(R.id.cronometro);
        crono.setBase(SystemClock.elapsedRealtime());
        crono.start();
        //Inicializamos distancia,velocidad y desnivel
        distancia = (TextView) findViewById(R.id.distancia);
        velocidadMedia = (TextView) findViewById(R.id.velocidadMedia);
        velocidadMedia.setText("Velocidad Media= " + 0.0 + " km/h");
        velocidadMaxima = (TextView) findViewById(R.id.velocidadMaxima);
        velocidadMaxima.setText("Velocidad Máxima= " + 0.0 + " km/h");
        desnivelPostivo_txt = (TextView) findViewById(R.id.desnivelPositivo_txt);
        desnivelPostivo_txt.setText("Desnivel Positivo= " + 0.0 + " m");
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        //Creamos el mapa
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        //Initialize Google Play Services
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                buildGoogleApiClient();
                mMap.setMyLocationEnabled(true);
            }
        } else {
            buildGoogleApiClient();
            mMap.setMyLocationEnabled(true);
        }

    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .enableAutoManage(this, this)
                .build();
        mGoogleApiClient.connect();
    }


     @Override
     public void onResume() {
         super.onResume();
         if (mGoogleApiClient != null &&
                 ContextCompat.checkSelfPermission(this,
                         android.Manifest.permission.ACCESS_FINE_LOCATION)
                         == PackageManager.PERMISSION_GRANTED) {
             LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
         }
     }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = new LocationRequest();
        //Tomamos la posicion cada 10segundos
        mLocationRequest.setInterval(10000);
        //establecer explícitamente el intervalo más rápido para las actualizaciones de ubicación
        mLocationRequest.setFastestInterval(5000);
        //Establecemos que al menos tiene que haber 25 metros entre cada actualizacion
        //mLocationRequest.setSmallestDisplacement(25);
        //Le damos alta prioridad al GPS
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Toast.makeText(getApplicationContext(), "Error de conexion", Toast.LENGTH_LONG).show();
    }

    public boolean checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Asking user if explanation is needed
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

                //Prompt the user once explanation has been shown
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);


            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted. Do the
                    // contacts-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mMap.setMyLocationEnabled(true);
                    }

                } else {

                    // Permission denied, Disable the functionality that depends on this permission.
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }

            // other 'case' lines to check for other permissions this app might request.
            // You can add here other case statements according to your requirement.
        }
    }


    @Override
    public void onLocationChanged(Location location) {
        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "MyWakelockTag");
        wakeLock.acquire();
        System.out.println("EEEEEEEEEEEEEEE: Estoy en LocationChanged");
        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }
        //Creamos las nuevas coordenadas
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        //Igualamos el desnivel parcial a la altura que nos encontremos
        desnivelParcial = mLastLocation.getAltitude();
        //Añadimos las cordenadas a la lista de puntos
        points.add(latLng);
        //Marcamos el inicio solo con el primer punto
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(points.get(0));
        markerOptions.title("Francisco Diaz Barrancas");
        markerOptions.snippet("Soy Francisco");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
        mCurrLocationMarker = mMap.addMarker(markerOptions);

        //movemos la camara al sitio donde nos encontramos solo la primera vez
        if (points.size() == 1) {
            mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
            mMap.animateCamera(CameraUpdateFactory.zoomTo(12));
            TFin = System.currentTimeMillis();
        }
        //Tomamos el tiempo para la velocidad Maxima
        TInicio = TFin;
        TFin = System.currentTimeMillis();

        //Pintamos la linea que marca la ruta
        line = mMap.addPolyline(new PolylineOptions()
                .addAll(points)
                .width(10)
                .color(Color.BLUE));


        //Calculamos la distancia desde el primer punto hasta el ultimo punto sumando, cuando hay mas de dos puntos cogemos los dos ultimos
        //Ademas calculamos el desnivel acumulado pasandole las posiciones
        if (points.size() < 2) {
            calcularDistancia(points.get(0), points.get(points.size() - 1));
        } else {
            calcularDistancia(points.get(points.size() - 2), points.get(points.size() - 1));
        }


        //Calculamos velocidadMedia
        calcularVelocidadMedia();
        //Calculamos velocidadMaximo
        calcularVelocidadMaxima();
        //Calculamos desnivel positivo
        calcularDesnivelPositivo(location);
    }

    //Metodo que calcula distancia entre dos puntos
    public void calcularDistancia(LatLng from, LatLng to) {
        distanciaParcial = SphericalUtil.computeDistanceBetween(from, to);
        distanciaTotal = distanciaTotal + SphericalUtil.computeDistanceBetween(from, to);
        distancia.setText(formatDistance(distanciaTotal));
    }

    //Pasamos a km cuando pasemos de 1000m
    public String formatDistance(double distance) {
        String texto = null;
        double rounded = 0;
        if (distance >= 1000) {
            distance = distance / 1000;
            rounded = (double) Math.round(distance * 100) / 100;
            texto = "Distancia= " + rounded + " km";
        } else {
            rounded = (double) Math.round(distance * 100) / 100;
            texto = "Distancia= " + rounded + " m";
        }
        return texto;
    }

    //Calculamos la velocidad media de la actividad en tiempo real, con lo cual tenemos que ir comparando con los dos ultimos puntos
    public void calcularVelocidadMedia() {
        String texto = null;
        //obtenemos el tiempo del crono en segundos
        double tiempoTotal = (SystemClock.elapsedRealtime() - crono.getBase()) / 1000;
        //Calculamos la velocidad en km/h
        double velocidad = (distanciaTotal / 1000) / (tiempoTotal / 3600);
        double rounded = (double) Math.round(velocidad * 100) / 100;
        velocidadMedia.setText("Velocidad Media= " + rounded + " km/h");

    }

    //Calculamos la velocidad Maxima y actualizamos cuando sea superior
    public void calcularVelocidadMaxima() {
        String texto = null;
        //Calculamos la velocidad en km/h
        double segundos = (TFin - TInicio) / 1000;
        double velocidad = (distanciaParcial / 1000) / (segundos / 3600);
        if (velocidad > vMaxima) {
            vMaxima = (double) Math.round(velocidad * 100) / 100;
            velocidadMaxima.setText("Velocidad Máxima= " + vMaxima + " km/h");
        }
    }

    public void calcularDesnivelPositivo(Location location) {
        desnivelPositivo = location.getAltitude() - desnivelParcial;
        if (desnivelPositivo > 0) {
            desnivelPositivo = desnivelPositivo + desnivelParcial;
            double rounded = (double) Math.round(desnivelPositivo * 100) / 100;
            desnivelPostivo_txt.setText("Desnivel Positivo= " + rounded + " m");
        }
    }

}
    
asked by Francisco Díaz Barrancas 01.11.2016 в 19:22
source

2 answers

2

Francisco, the problem with Android is that when leaving the main activity, for energy consumption and other situations the application remains frozen, so that what you run within the activity will stay waiting, I recommend that the route traces from an IntentService, saving the data where you need it (be it webservice, to SQLite, a file, etc)

I append you again the page that could help you create an IntentService.

link

    
answered by 02.11.2016 в 23:18
0

Here is an example of a service with the gps, I hope you serve

public class GPS_Service extends Service{

private LocationListener listener;
private LocationManager locationManager;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {

    listener = new LocationListener() {
        @Override
        public void onLocationChanged(final Location location) {
            Intent i = new Intent("location_update");
            i.putExtra("coordinates",location.getLongitude()+" "+location.getLatitude());
            sendBroadcast(i);
        }

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

        }

        @Override
        public void onProviderEnabled(String s) {

        }

        @Override
        public void onProviderDisabled(String s) {
            Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);
        }
    };

    locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    //noinspection MissingPermission
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,30000,0,listener);
}

@Override
public void onDestroy() {
    super.onDestroy();
    if(locationManager != null){
        //noinspection MissingPermission
        locationManager.removeUpdates(listener);
    }
}}
    
answered by 18.04.2017 в 18:03