2 votes

Comment arrêter le gestionnaire lorsque getAccuracy() est inférieur à 100 % ?

Bonjour, je suis en train de créer une application de carte Android qui va obtenir l'emplacement de l'utilisateur, mais lorsque les utilisateurs ouvrent leur carte parfois l'emplacement n'est pas précis et va lentement indiquer votre emplacement.

J'ai essayé ceci. Mais il appelle toujours le gestionnaire et les TOASTS ne s'arrêtent pas.

private LocationManager locationManager;

private Handler handler = new Handler();

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

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {

        }

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

        }

        @Override
        public void onProviderEnabled(String provider) {
              handler.postDelayed(runnable,3000);
        }

        @Override
        public void onProviderDisabled(String provider) {

            handler.removeCallbacks(runnable);
        }
    });

      private Runnable runnable = new Runnable() {
    @Override
    public void run() {

      getCurrentLocation();

        Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show();

        handler.postDelayed(this, 3000);
    }
};

   private void getCurrentLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        longitude = location.getLongitude();
        latitude = location.getLatitude();

        moveMap();

        Integer loc = Math.round(location.getAccuracy());
        textings.setText(Integer.toString(loc));

        if(loc <= 100)
    {
        handler.removeCallbacks(runnable);

        Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
    }

    }
}

//Function to move the map
private void moveMap() {

    LatLng latLng = new LatLng(latitude, longitude);

    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
    mMap.addMarker(new MarkerOptions().position(latLng).draggable(false));

}

J'ai ajouté un gestionnaire qui s'exécute toutes les 5 secondes pour vérifier l'emplacement de l'utilisateur et qui s'arrête lorsque la donnée getAccuracy est égale ou inférieure à 100. Comment dois-je m'y prendre ?

3voto

RobCo Points 2957

GetCurrentLocation peut appeler handler.removeCallbacks(runnable); mais alors le runnable appellera toujours handler.postDelayed(this, 3000); juste après.

Pour résoudre ce problème, il faut que le Runnable vérifie s'il doit se réafficher.

Une solution serait de faire en sorte que getCurrentLocation renvoie un booléen indiquant s'il a réussi (assez) :

private boolean getCurrentLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && 
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return false;
    }
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        longitude = location.getLongitude();
        latitude = location.getLatitude();

        moveMap();

        Integer loc = Math.round(location.getAccuracy());
        textings.setText(Integer.toString(loc));

        if(loc <= 100) {
            handler.removeCallbacks(runnable);
            Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
            return true;
        }
    }
    return false;
}

Ensuite, dans votre Runnable, vérifiez si vous avez besoin d'une autre exécution :

@Override
public void run() {
    if(!getCurrentLocation()) {
        handler.postDelayed(this, 3000);
    }
}

Cependant Tout cela étant dit, vous devriez simplement vérifier l'emplacement dans le onLocationChanged de votre LocationListener et faire quelque chose si cet emplacement est suffisamment précis. Dans ce cas, vous n'avez pas du tout besoin du Runnable.

2voto

albert c braun Points 1593

Vous devriez définitivement accepter la réponse de RobCo comme étant la bonne, car elle répond directement à votre question et offre également un aperçu clé supplémentaire (c'est-à-dire que vous n'avez pas vraiment besoin du Runnable).

Mais j'étais curieux de voir à quoi ressemblerait l'approche de RobCo, et j'ai donc créé une mise en œuvre possible de celle-ci.

Il s'avère que si nous évitons le Runnable et que nous nous appuyons plutôt sur les callbacks de Google, nous pouvons nous en sortir en utilisant uniquement la nouvelle API de fournisseur de localisation (LocatonServices.FusedLocationApi). L'ancienne API LocationManager peut tout simplement être éliminée.

Ainsi, dans cette mise en œuvre, je laisse le service de localisation de Google déclencher des rappels si/quand la localisation change (au lieu d'utiliser une interrogation périodique du client) :

public class MainActivity extends AppCompatActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener,
        GoogleApiClient.ConnectionCallbacks,
        com.google.android.gms.location.LocationListener {

    private static final String TAG = MainActivity.class.getSimpleName();

    private static final int PERMISSION_REQUEST_CODE = 10001;
    public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds
    private GoogleApiClient googleApiClient;

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

        googleApiClient = new GoogleApiClient.Builder(this, this, this)
                .enableAutoManage(this, this)
                .addApi(LocationServices.API)
                .build();

        googleApiClient.connect();
    }

    private void requestPermission() {
        ActivityCompat.requestPermissions(this,
                new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
    }

    private void initLocationServices() {
        try {
            // make initial, synchronous request for current location
            Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
            if (location != null) {
                moveMap(location);
            }

            // request future location updates which will come in as callbacks later, when available
            LocationRequest locationRequest = new LocationRequest();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
            LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
        } catch (SecurityException se) {
            Log.w(TAG, "App does not have sufficient permission to request location. " +
                    "Requesting permission now...");
            requestPermission();
        }
    }

    private void moveMap(Location location) {
        Log.v(TAG, "moveMap");

        // TODO: actual map moving code goes here
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage());
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
            Log.v(TAG, "User granted permission. Will request current location.");
            initLocationServices();
        } else {
            Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed.");
        }
    }

    @Override
    public void onLocationChanged(Location newLocation) {
        Log.v(TAG, "onLocationChanged:" + newLocation.toString());
        moveMap(newLocation);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED)
                && (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) {
            initLocationServices();
        } else {
            Log.w(TAG, "onCreate: requesting sufficient permission from user");
            requestPermission();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.v(TAG, "onConnectionSuspended");
    }
}

L'inconvénient de cette mise en œuvre particulière est que l'activité principale implémente plusieurs interfaces, ce qui ajoute un peu de confusion (que font toutes ces méthodes ici ?, etc.).

Je ne sais pas. Peut-être que c'est utile. En tout cas, bonne chance avec votre application.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X