GPS e Mappe Android in Java: Guida Completa

Guida completa a GPS e Mappe Android in Java

GPS e Mappe Android in Java: questa guida illustra, in modo pratico e in Java, come lavorare con la localizzazione GPS e con Google Maps su Android. Vedremo come ottenere la posizione dell’utente con FusedLocationProviderClient, come richiedere i permessi di localizzazione a runtime, come integrare il Google Maps SDK, aggiungere marker, centrare la mappa sulla posizione corrente e calcolare la distanza tra due punti con Location.distanceBetween.

GPS e Mappe Android in Java: localizzazione GPS con Google Maps SDK

1. Concetti di base su GPS e Localizzazione Android

Android fornisce diverse sorgenti di localizzazione (GPS, Wi-Fi, rete cellulare, sensori). L’API consigliata è il Fused Location Provider, fornito dai Google Play Services, che combina automaticamente queste sorgenti per ottenere la posizione migliore con il minor consumo di batteria.

Per usare il Fused Location Provider, devi:

  • Aggiungere la dipendenza dei Google Play Services Location;
  • Richiedere i permessi di localizzazione (foreground e, se serve, background);
  • Creare un’istanza di FusedLocationProviderClient;
  • Richiedere la posizione corrente o aggiornamenti continui;
  • Gestire correttamente il ciclo di vita (avviare/fermare gli aggiornamenti quando serve).

2. Configurazione del progetto Android per GPS e Mappe in Java

Assumiamo un progetto Android con linguaggio Java, minSdkVersion compatibile con i Google Play Services recenti (es. 21+). Di seguito le configurazioni essenziali.

2.1 Dipendenze Gradle per GPS Android in Java

Nel file app/build.gradle (module), aggiungi:

dependencies {
    // Fused Location Provider
    implementation 'com.google.android.gms:play-services-location:21.2.0'

    // Google Maps SDK for Android
    implementation 'com.google.android.gms:play-services-maps:19.0.0'
}

2.2 Permessi di Localizzazione nel Manifest Android

Nel file AndroidManifest.xml dichiara i permessi di localizzazione:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- Opzionale, solo se ti serve il background location (Android 10+ richiede flusso dedicato) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Per Google Maps, aggiungi anche la meta-data con la tua API key (ottenuta dalla Google Cloud Console: Maps SDK for Android abilitato):

<application
    ...>

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="YOUR_API_KEY_HERE" />

    ...

</application>

3. Richiedere i Permessi di Localizzazione Android in Java

Da Android 6.0 (API 23) in poi, i permessi “pericolosi” come la localizzazione vanno richiesti a runtime. Il flusso tipico è:

  • Verificare se il permesso è già concesso con ContextCompat.checkSelfPermission;
  • Se non concesso, mostrare una spiegazione (se necessario) e poi chiamare ActivityCompat.requestPermissions;
  • Gestire il risultato in onRequestPermissionsResult (per Activity) o callback equivalente.

3.1 Esempio Java: Richiesta Permessi GPS Android

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_LOCATION_PERMISSION = 1001;

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

        checkLocationPermission();
    }

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

            // Permesso non ancora concesso
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                // Qui potresti mostrare un dialog che spiega perché ti serve il permesso
                // e poi richiederlo di nuovo
            }

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_LOCATION_PERMISSION);
        } else {
            // Permesso già concesso
            onLocationPermissionGranted();
        }
    }

    private void onLocationPermissionGranted() {
        // Qui puoi iniziare a richiedere la posizione
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUEST_LOCATION_PERMISSION) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                onLocationPermissionGranted();
            } else {
                // Permesso negato: gestisci il caso (disabilita funzionalità, mostra messaggio, ecc.)
            }
        }
    }
}

4. Ottenere la posizione GPS con FusedLocationProviderClient in Java

FusedLocationProviderClient è l’oggetto principale per interagire con il Fused Location Provider. Puoi ottenere:

  • La last known location (posizione recente, veloce ma non sempre aggiornata);
  • La posizione corrente con getCurrentLocation;
  • Aggiornamenti continui tramite requestLocationUpdates e LocationCallback.

4.1 Setup FusedLocationProviderClient in Java Android

public class LocationActivity extends AppCompatActivity {

    private FusedLocationProviderClient fusedLocationClient;
    private LocationRequest locationRequest;
    private LocationCallback locationCallback;

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

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        // Configura la richiesta di localizzazione
        locationRequest = LocationRequest.create();
        locationRequest.setPriority(Priority.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(5000);      // 5 secondi
        locationRequest.setFastestInterval(2000); // 2 secondi

        // Callback per aggiornamenti continui
        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                for (Location location : locationResult.getLocations()) {
                    if (location != null) {
                        double lat = location.getLatitude();
                        double lng = location.getLongitude();
                        // Usa la posizione (aggiorna UI, invia al server, ecc.)
                    }
                }
            }
        };

        // Esegui solo dopo che il permesso è concesso
        startLocationUpdates();
    }

    @SuppressLint("MissingPermission")
    private void startLocationUpdates() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            // Gestisci richiesta permessi prima di chiamare questo metodo
            return;
        }

        fusedLocationClient.requestLocationUpdates(locationRequest,
                locationCallback,
                Looper.getMainLooper());
    }

    private void stopLocationUpdates() {
        fusedLocationClient.removeLocationUpdates(locationCallback);
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopLocationUpdates();
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Se desideri, puoi riavviare gli aggiornamenti qui (dopo verifica permessi)
    }
}

4.2 Ottenere la Posizione GPS Corrente in Android

Se ti serve solo la posizione una tantum (per esempio per centrare una mappa), puoi usare getCurrentLocation (API recente) o getLastLocation.

@SuppressLint("MissingPermission")
private void getCurrentLocationOnce() {
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        // Richiedi i permessi prima
        return;
    }

    fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
            .addOnSuccessListener(location -> {
                if (location != null) {
                    double lat = location.getLatitude();
                    double lng = location.getLongitude();
                    // Usa lat e lng
                }
            })
            .addOnFailureListener(e -> {
                // Gestisci l'errore
            });
}

5. Usare Google Maps SDK per Android in Java

Il Google Maps SDK per Android permette di mostrare mappe interattive nella tua app, con zoom, rotazione, marker, polilinee e molto altro.

5.1 Layout XML con SupportMapFragment per Mappe Android

Crea un layout, ad esempio activity_maps.xml:

<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

5.2 Activity Java con Google Maps Android

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;

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

        // Ottieni il SupportMapFragment e ricevi notifica quando la mappa è pronta
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        if (mapFragment != null) {
            mapFragment.getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Opzioni iniziali della mappa (es: tipo mappa)
        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Esempio: aggiungi un marker a Roma e sposta la camera
        LatLng roma = new LatLng(41.9028, 12.4964);
        mMap.addMarker(new MarkerOptions().position(roma).title("Roma"));
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(roma, 12f));
    }
}

6. Aggiungere marker su Mappe Android in Java

I marker rappresentano punti d’interesse (POI) sulla mappa. Puoi personalizzare titolo, snippet, icona e molto altro.

private void addMarkersExample() {
    if (mMap == null) return;

    LatLng milano = new LatLng(45.4642, 9.19);
    LatLng torino = new LatLng(45.0703, 7.6869);

    mMap.addMarker(new MarkerOptions()
            .position(milano)
            .title("Milano")
            .snippet("Duomo di Milano"));

    mMap.addMarker(new MarkerOptions()
            .position(torino)
            .title("Torino")
            .snippet("Mole Antonelliana"));
}
FusedLocationProviderClient Android: localizzazione GPS e posizione utente in Java

Puoi anche personalizzare l’icona del marker usando icon(BitmapDescriptorFactory.fromResource(R.drawable.tua_icona)).

7. Centrare la Mappa Android sulla Posizione GPS Corrente

Per centrare la mappa sulla posizione attuale dell’utente, devi combinare FusedLocationProviderClient con Google Maps. Segue un esempio in cui, quando la mappa è pronta, otteniamo la posizione corrente e spostiamo la camera.

public class MapsCurrentLocationActivity extends FragmentActivity
        implements OnMapReadyCallback {

    private GoogleMap mMap;
    private FusedLocationProviderClient fusedLocationClient;

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

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        if (mapFragment != null) {
            mapFragment.getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        enableMyLocationAndCenter();
    }

    @SuppressLint("MissingPermission")
    private void enableMyLocationAndCenter() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    1001);
            return;
        }

        // Mostra il pulsante "La mia posizione" sulla mappa
        mMap.setMyLocationEnabled(true);

        fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
                .addOnSuccessListener(location -> {
                    if (location != null && mMap != null) {
                        LatLng currentLatLng = new LatLng(location.getLatitude(),
                                location.getLongitude());

                        mMap.addMarker(new MarkerOptions()
                                .position(currentLatLng)
                                .title("La mia posizione"));

                        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f));
                    }
                });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 1001) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                enableMyLocationAndCenter();
            }
        }
    }
}

8. Calcolare la distanza GPS tra due punti in Android

Android fornisce il metodo statico Location.distanceBetween, che calcola la distanza in metri tra due coordinate (latitudine/longitudine) usando il modello ellissoidale WGS84.

private float calculateDistanceInKm(double startLat, double startLng,
                                   double endLat, double endLng) {
    float[] results = new float[1];

    Location.distanceBetween(startLat, startLng,
            endLat, endLng,
            results);

    float distanceInMeters = results[0];
    return distanceInMeters / 1000f; // km
}

private void exampleDistance() {
    // Roma
    double romaLat = 41.9028;
    double romaLng = 12.4964;

    // Milano
    double milanoLat = 45.4642;
    double milanoLng = 9.19;

    float distanceKm = calculateDistanceInKm(romaLat, romaLng, milanoLat, milanoLng);

    Log.d("DISTANZA", "Distanza Roma-Milano: " + distanceKm + " km");
}

9. Esempio pratico completo: GPS e Mappe Android in Java

Di seguito un esempio che unisce i concetti visti: un’Activity con una mappa che:

  • Richiede il permesso di localizzazione;
  • Mostra la posizione corrente dell’utente su una mappa;
  • Aggiunge un marker su un punto fisso (es. un ufficio o negozio);
  • Calcola e mostra in log la distanza tra l’utente e il POI.
public class FullExampleMapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private static final int REQUEST_LOCATION_PERMISSION = 2001;

    private GoogleMap mMap;
    private FusedLocationProviderClient fusedLocationClient;

    // Punto fisso (es. negozio/ufficio)
    private static final LatLng POI = new LatLng(45.4642, 9.19); // Milano

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

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        if (mapFragment != null) {
            mapFragment.getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        checkLocationPermissionAndEnable();
    }

    private void checkLocationPermissionAndEnable() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_LOCATION_PERMISSION);
        } else {
            enableLocationFeatures();
        }
    }

    @SuppressLint("MissingPermission")
    private void enableLocationFeatures() {
        if (mMap == null) return;

        // Abilita il layer "La mia posizione"
        mMap.setMyLocationEnabled(true);

        // Aggiungi marker sul POI
        mMap.addMarker(new MarkerOptions()
                .position(POI)
                .title("Punto di interesse"));

        // Ottieni la posizione corrente e centra la mappa
        fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
                .addOnSuccessListener(location -> {
                    if (location != null) {
                        LatLng currentLatLng = new LatLng(location.getLatitude(),
                                location.getLongitude());

                        // Marker posizione utente
                        mMap.addMarker(new MarkerOptions()
                                .position(currentLatLng)
                                .title("Tu sei qui"));

                        // Centra la mappa tra utente e POI (zoom medio)
                        LatLngBounds.Builder builder = new LatLngBounds.Builder();
                        builder.include(currentLatLng);
                        builder.include(POI);
                        LatLngBounds bounds = builder.build();

                        int padding = 100; // pixel di padding dai bordi
                        mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));

                        // Calcola distanza tra utente e POI
                        float[] results = new float[1];
                        Location.distanceBetween(
                                currentLatLng.latitude, currentLatLng.longitude,
                                POI.latitude, POI.longitude,
                                results
                        );
                        float distanceMeters = results[0];
                        float distanceKm = distanceMeters / 1000f;

                        Log.d("DISTANZA", "Distanza utente - POI: " + distanceKm + " km");
                    }
                })
                .addOnFailureListener(e -> Log.e("MAPS", "Errore nel recupero posizione", e));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUEST_LOCATION_PERMISSION) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                enableLocationFeatures();
            } else {
                // Permesso negato, puoi centrare la mappa sul POI o usare coordinate di default
                if (mMap != null) {
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(POI, 12f));
                }
            }
        }
    }
}

10. Buone pratiche per GPS e Localizzazione Android

  • Consumo di batteria: usa getCurrentLocation o getLastLocation quando possibile invece di aggiornamenti continui;
  • Gestione errori: gestisci il caso in cui la posizione sia nulla (GPS disattivato, servizi di localizzazione disabilitati, nessun fix);
  • Privacy: mostra all’utente perché raccogli la posizione e come verrà utilizzata; rispetta le policy di Google Play e le normative (es. GDPR);
  • Permessi background: richiedili solo se strettamente necessari (es. tracciamento in background), spiegando chiaramente il motivo;
  • UI chiara: offri un pulsante “centra su di me” e indicatori chiari dei POI, con info facilmente leggibili.

Con questi esempi hai una base solida per integrare localizzazione GPS e mappe nella tua app Android in Java. Da qui puoi estendere con polilinee (percorsi), geofencing, salvataggio delle posizioni su database e molto altro.

Commenti

Rispondi

Scopri di più da App Tutorial

Abbonati ora per continuare a leggere e avere accesso all'archivio completo.

Continua a leggere