web-dev-qa-db-fra.com

Android Google Map comment vérifier si l'emplacement du GPS est à l'intérieur du cercle

J'essaie de détecter si un utilisateur est dans le rayon d'un marqueur, en utilisant l'emplacement gps des utilisateurs. J'ai les coordonnées du marqueur, mais je ne sais pas comment calculer si l'utilisateur est dans la zone. J'ai essayé d'utiliser ce qui suit, mais même lorsque l'emplacement actuel est à l'intérieur du cercle, je reçois toujours le message "extérieur".

public class MapaEscola extends FragmentActivity {

    private GoogleMap googleMap;
    private Serializable escolas;
    private ProgressDialog dialog;
    private Circle mCircle;
    private Marker mMarker;



    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        setContentView(R.layout.maps);

        // Loading map
        initilizeMap();

        // Changing map type
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Showing / hiding your current location
        googleMap.setMyLocationEnabled(true);

        // Enable / Disable zooming controls
        googleMap.getUiSettings().setZoomControlsEnabled(true);

        // Enable / Disable my location button
        googleMap.getUiSettings().setMyLocationButtonEnabled(true);

        // Enable / Disable Compass icon
        googleMap.getUiSettings().setCompassEnabled(true);

        // Enable / Disable Rotate gesture
        googleMap.getUiSettings().setRotateGesturesEnabled(true);

        // Enable / Disable zooming functionality
        googleMap.getUiSettings().setZoomGesturesEnabled(true);

        Bundle extra = getIntent().getBundleExtra("extra");
        ArrayList<Escolas> objects = (ArrayList<Escolas>) extra.getSerializable("array");


        try {

            for(int i = 0; i < objects.size(); i ++) {
                System.out.println(" escolas " + objects.get(i).getLatitude() + " " + objects.get(i).getLongitude());

                float latitude = objects.get(i).getLatitude();
                float longitude = objects.get(i).getLongitude();

                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.316281, -51.155528), 15));

                MarkerOptions options = new MarkerOptions();

                // Setting the position of the marker

                options.position(new LatLng(latitude, longitude));

                googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

                LatLng latLng = new LatLng(latitude, longitude);
                drawMarkerWithCircle(latLng);


                googleMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
                    @Override
                    public void onMyLocationChange(Location location) {
                        float[] distance = new float[2];

                        Location.distanceBetween( mMarker.getPosition().latitude, mMarker.getPosition().longitude,
                                mCircle.getCenter().latitude, mCircle.getCenter().longitude, distance);

                        if( distance[0] > (mCircle.getRadius() / 2)  ){
                            Toast.makeText(getBaseContext(), "Outside", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(getBaseContext(), "Inside", Toast.LENGTH_LONG).show();
                        }

                    }
                });




            }



        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void drawMarkerWithCircle(LatLng position){
        double radiusInMeters = 500.0;
        int strokeColor = 0xffff0000; //red outline
        int shadeColor = 0x44ff0000; //opaque red fill

        CircleOptions circleOptions = new CircleOptions().center(position).radius(radiusInMeters).fillColor(shadeColor).strokeColor(strokeColor).strokeWidth(8);
        mCircle = googleMap.addCircle(circleOptions);

        MarkerOptions markerOptions = new MarkerOptions().position(position);
        mMarker = googleMap.addMarker(markerOptions);
    }



    private void initilizeMap() {

        if (googleMap == null) {
            googleMap = ((MapFragment) getFragmentManager().findFragmentById(
                    R.id.map)).getMap();

            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getApplicationContext(),
                        "Não foi possível carregar o mapa", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    public void onBackPressed() {

        super.onBackPressed();
        finish();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public boolean onOptionsItemSelected(MenuItem item) {


        switch (item.getItemId()) {

            case Android.R.id.home:
                super.onBackPressed();
                finish();

                return true;


        }

        return true;

    }

    @Override
    protected void onResume() {
        super.onResume();
        initilizeMap();
    }


}
16
AND4011002849

Je viens d'exécuter le code mis à jour et j'ai découvert le problème principal.

Vous devez utiliser le Location passé dans le callback onMyLocationChange(), afin qu'il utilise votre emplacement actuel pour savoir si le périphérique est dans le cercle ou non:

googleMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
                @Override
                public void onMyLocationChange(Location location) {
                    float[] distance = new float[2];

                    /*
                    Location.distanceBetween( mMarker.getPosition().latitude, mMarker.getPosition().longitude,
                            mCircle.getCenter().latitude, mCircle.getCenter().longitude, distance);
                            */

                    Location.distanceBetween( location.getLatitude(), location.getLongitude(),
                            mCircle.getCenter().latitude, mCircle.getCenter().longitude, distance);

                    if( distance[0] > mCircle.getRadius() ){
                        Toast.makeText(getBaseContext(), "Outside, distance from center: " + distance[0] + " radius: " + mCircle.getRadius(), Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getBaseContext(), "Inside, distance from center: " + distance[0] + " radius: " + mCircle.getRadius() , Toast.LENGTH_LONG).show();
                    }

                }
            });

Voici l'exemple de travail complet que j'ai exécuté, c'est une version simplifiée de votre code d'origine:

public class MainActivity extends ActionBarActivity {

    private GoogleMap googleMap;
    private Serializable escolas;
    private ProgressDialog dialog;
    private Circle mCircle;
    private Marker mMarker;



    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        setContentView(R.layout.activity_main);

        // Loading map
        initilizeMap();

        // Changing map type
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Showing / hiding your current location
        googleMap.setMyLocationEnabled(true);

        // Enable / Disable zooming controls
        googleMap.getUiSettings().setZoomControlsEnabled(true);

        // Enable / Disable my location button
        googleMap.getUiSettings().setMyLocationButtonEnabled(true);

        // Enable / Disable Compass icon
        googleMap.getUiSettings().setCompassEnabled(true);

        // Enable / Disable Rotate gesture
        googleMap.getUiSettings().setRotateGesturesEnabled(true);

        // Enable / Disable zooming functionality
        googleMap.getUiSettings().setZoomGesturesEnabled(true);

       // Bundle extra = getIntent().getBundleExtra("extra");
        //ArrayList<Escolas> objects = (ArrayList<Escolas>) extra.getSerializable("array");


        try {
               //test outside
               double mLatitude = 37.77657;
               double mLongitude = -122.417506;


                //test inside
                //double mLatitude = 37.7795516;
                //double mLongitude = -122.39292;


                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLatitude, mLongitude), 15));

                MarkerOptions options = new MarkerOptions();

                // Setting the position of the marker

                options.position(new LatLng(mLatitude, mLongitude));

                //googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

                LatLng latLng = new LatLng(mLatitude, mLongitude);
                drawMarkerWithCircle(latLng);


                googleMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
                    @Override
                    public void onMyLocationChange(Location location) {
                        float[] distance = new float[2];

                        /*
                        Location.distanceBetween( mMarker.getPosition().latitude, mMarker.getPosition().longitude,
                                mCircle.getCenter().latitude, mCircle.getCenter().longitude, distance);
                                */

                        Location.distanceBetween( location.getLatitude(), location.getLongitude(),
                                mCircle.getCenter().latitude, mCircle.getCenter().longitude, distance);

                        if( distance[0] > mCircle.getRadius()  ){
                            Toast.makeText(getBaseContext(), "Outside, distance from center: " + distance[0] + " radius: " + mCircle.getRadius(), Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(getBaseContext(), "Inside, distance from center: " + distance[0] + " radius: " + mCircle.getRadius() , Toast.LENGTH_LONG).show();
                        }

                    }
                });




        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void drawMarkerWithCircle(LatLng position){
        double radiusInMeters = 500.0;
        int strokeColor = 0xffff0000; //red outline
        int shadeColor = 0x44ff0000; //opaque red fill

        CircleOptions circleOptions = new CircleOptions().center(position).radius(radiusInMeters).fillColor(shadeColor).strokeColor(strokeColor).strokeWidth(8);
        mCircle = googleMap.addCircle(circleOptions);

        MarkerOptions markerOptions = new MarkerOptions().position(position);
        mMarker = googleMap.addMarker(markerOptions);
    }



    private void initilizeMap() {

        if (googleMap == null) {
            googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(
                    R.id.map)).getMap();

            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getApplicationContext(),
                        "Não foi possível carregar o mapa", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    public void onBackPressed() {

        super.onBackPressed();
        finish();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public boolean onOptionsItemSelected(MenuItem item) {


        switch (item.getItemId()) {

            case Android.R.id.home:
                super.onBackPressed();
                finish();

                return true;


        }

        return true;

    }

    @Override
    protected void onResume() {
        super.onResume();
        initilizeMap();
    }


}

Résultats de l'intérieur du cercle:

Inside

Résultats hors du cercle:

Outside

17
Daniel Nugent

Salut, j'ai le mien qui fonctionne correctement avec ce code

//Getting current location
private void getCurrentLocation() {
    mMap.clear();
    //Creating a location object
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        //Getting longitude and latitude
        longitude = location.getLongitude();
        latitude = location.getLatitude();
        //moving the map to location
        moveMap();
    }

    Circle circle = mMap.addCircle(new CircleOptions()
                    .center(new LatLng(54.773097, -6.557841))
                    .radius(55)
                    .strokeColor(Color.RED)
    );



    pLong  = location.getLongitude();
    pLat = location.getLatitude();

    float[] distance = new float[2];


    Location.distanceBetween(pLat, pLong,
            circle.getCenter().latitude, circle.getCenter().longitude, distance);

    if( distance[0] > circle.getRadius()  ){
        Toast.makeText(getBaseContext(), "You are not in a bunker", Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(getBaseContext(), "You are inside a bunker", Toast.LENGTH_LONG).show();
    }

}

à l'intérieur du cercle

en dehors du cercle

2
matthewoak

@Daniel Nugent: imho getRadius() renverra le rayon et non le diamètre donc le "/2" Est faux

@WARpoluido: Je ne vois pas que la variable mMarker est mise à jour lorsque l'emplacement change. Pourquoi n'utilisez-vous pas la valeur donnée à onMyLocationChange()?

Location.distanceBetween( mCircle.getCenter().latitude, mCircle.getCenter().longitude, location.getLatitude(), location.getLongitude(), distance);
if( distance[0] > mCircle.getRadius() ){
...
2
casiosmu

La solution acceptée de Daniel Nugent n'est plus aussi bonne parce que setOnMyLocationChangeListener est obsolète maintenant.

Voici comment le faire en fragment - changez getActivity() avec this pour Activity:

private boolean mLocationPermissionGranted;

// The geographical location where the device is currently located. That is, the last-known
// location retrieved by the Fused Location Provider.
private Location mLastKnownLocation;
private long UPDATE_INTERVAL = 10 * 1000;  /* 10 secs */
private long FASTEST_INTERVAL = 2000; /* 2 sec */
private FusedLocationProviderClient mFusedLocationProviderClient;

private void addLocationChangeListener(){
        // Construct a FusedLocationProviderClient.
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());

        // Create the location request to start receiving updates
        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        //mLocationRequest.setMaxWaitTime(0);
        //mLocationRequest.setSmallestDisplacement(0);

        // Create LocationSettingsRequest object using location request
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();

        // Check whether location settings are satisfied
        // https://developers.google.com/Android/reference/com/google/Android/gms/location/SettingsClient
        SettingsClient settingsClient = LocationServices.getSettingsClient(getActivity());
        settingsClient.checkLocationSettings(locationSettingsRequest);


        // new Google API SDK v11 uses getFusedLocationProviderClient(this)
        if (mLocationPermissionGranted) {
            mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest,
                    new LocationCallback() {
                        @Override
                        public void onLocationResult(LocationResult locationResult) {
                            // do work here
                            Location location = locationResult.getLastLocation();
                        }
                    },
                    Looper.myLooper());
        } else {
            getLocationPermission();
        }
    }
0
nasko700