Una delle caratteristiche uniche delle app mobile è il rilevamento della posizione. Gli utenti di dispositivi mobili portano con sé i propri dispositivi ovunque e aggiungono la posizione della tua app offre agli utenti un'esperienza più contestuale.
Esempi di codice
Il repository ApiDemos su GitHub include esempi che mostrano l'utilizzo della posizione su una mappa:
Kotlin
- MyLocationDemoActivity: utilizzo del livello La mia posizione, incluse le autorizzazioni di runtime
- LocationSourceDemoActivity: utilizzo di un parametro personalizzato
LocationSource
- CurrentPlaceDetailsOnMap: trovare la località attuale posizione di un dispositivo Android e visualizzazione dei dettagli del luogo (attività o altro punto d'interesse) in quella posizione. Consulta il tutorial su come mostrare i dettagli del luogo attuale su una mappa.
Java
- MyLocationDemoActivity: utilizzo dell'elemento Livello La mia posizione, incluse le autorizzazioni di runtime
- LocationSourceDemoActivity: utilizzo di un
LocationSource
personalizzato - CurrentPlaceDetailsOnMap: trova la posizione attuale di un dispositivo Android e mostra i dettagli del luogo (attività o altro punto d'interesse) in quella posizione. Guarda il tutorial su come mostrare dettagli del luogo attuale su una mappa.
Utilizzare i dati sulla posizione
I dati sulla posizione disponibili per un dispositivo Android includono la posizione attuale del dispositivo, individuata utilizzando una combinazione di tecnologie, la direzione e il metodo di movimento e se il dispositivo ha attraversato un confine geografico predefinito o un recinto virtuale. In base alle esigenze della tua applicazione, puoi scegliere tra diversi modi per lavorare con la posizione dati:
- Il livello La mia posizione consente di visualizzare facilmente la posizione sulla mappa. Non fornisce dati.
- L'API Location di Google Play Services è consigliata per tutte le richieste programmatiche relative ai dati sulla posizione.
- L'interfaccia di
LocationSource
ti consente di fornire un fornitore di servizi di localizzazione personalizzato.
Autorizzazioni di accesso alla posizione
Se la tua app deve accedere alla posizione dell'utente, devi richiedere l'autorizzazione entro il giorno aggiungendo le autorizzazioni di accesso alla posizione di Android pertinenti alla tua app.
Android offre due autorizzazioni di accesso alla posizione: ACCESS_COARSE_LOCATION
e
ACCESS_FINE_LOCATION
. L'autorizzazione che scegli determina l'accuratezza
località restituita dall'API.
android.permission.ACCESS_COARSE_LOCATION
– Consente all'API di restituire la posizione approssimativa del dispositivo. La fornisce una stima della posizione del dispositivo in base ai servizi di geolocalizzazione, come descritta nella documentazione sulla posizione approssimativa la precisione.android.permission.ACCESS_FINE_LOCATION
– Consente all'API di determinare una posizione il più precisa possibile dal dei fornitori di località disponibili, incluso il Global Positioning System (GPS), Wi-Fi e dati mobili.
Aggiungi le autorizzazioni al file manifest dell'app
Se la posizione approssimativa è necessaria solo per il funzionamento dell'app, aggiungi l'autorizzazione ACCESS_COARSE_LOCATION
al file manifest dell'app:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ... </manifest>
Tuttavia, se è necessaria la posizione esatta, aggiungi entrambi ACCESS_COARSE_LOCATION
e ACCESS_FINE_LOCATION
autorizzazioni al file manifest dell'app:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ... </manifest>
Richiedi autorizzazioni di runtime
Android 6.0 (Marshmallow) introduce un nuovo modello per la gestione delle autorizzazioni, che semplifica la procedura per gli utenti quando installano e eseguono l'upgrade delle app. Se la tua app ha come target il livello API 23 o versioni successive, puoi utilizzare il nuovo modello di autorizzazioni.
Se la tua app supporta il nuovo modello di autorizzazioni e sul dispositivo è installato Android 6.0 (Marshmallow) o versioni successive, l'utente non deve concedere alcuna autorizzazione quando installano o eseguono l'upgrade dell'app. L'app deve verificare se disponga dell'autorizzazione necessaria in fase di runtime e, se lo fa, richiedi l'autorizzazione non ce l'ha. Il sistema mostra all'utente una finestra di dialogo che richiede l'autorizzazione.
Per un'esperienza utente ottimale, è importante richiedere l'autorizzazione nel contesto. Se la posizione è essenziale per il funzionamento della tua app, devi richiedere l'autorizzazione di accesso alla posizione all'avvio dell'app. Un buon modo per farlo è con una temperatura schermata di benvenuto o procedura guidata che spieghi agli utenti perché l'autorizzazione è obbligatorio.
Se l'app richiede l'autorizzazione solo per parte della sua funzionalità, deve richiedere l'autorizzazione di accesso alla posizione nel momento in cui l'app esegue che richiede l'autorizzazione.
L'app deve gestire agevolmente il caso in cui l'utente non concede autorizzazione. Ad esempio, se l'autorizzazione è necessaria per una funzionalità specifica, l'app può disattivare la funzionalità. Se l'autorizzazione è essenziale per consentire all'app funzione, l'app può disattivare tutte le sue funzionalità e informare l'utente che deve concedere l'autorizzazione.
Il seguente esempio di codice verifica l'autorizzazione utilizzando la libreria AndroidX
prima di attivare il livello La mia posizione. Gestisce quindi il risultato della richiesta di
autorizzazione implementando il metodo
ActivityCompat.OnRequestPermissionsResultCallback
della libreria di assistenza:
Kotlin
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.kotlindemos import android.Manifest import android.annotation.SuppressLint import android.content.pm.PackageManager import android.location.Location import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback import androidx.core.content.ContextCompat import com.example.kotlindemos.PermissionUtils.PermissionDeniedDialog.Companion.newInstance import com.example.kotlindemos.PermissionUtils.isPermissionGranted import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment /** * This demo shows how GMS Location can be used to check for changes to the users location. The * "My Location" button uses GMS Location to set the blue dot representing the users location. * Permission for [Manifest.permission.ACCESS_FINE_LOCATION] and [Manifest.permission.ACCESS_COARSE_LOCATION] * are requested at run time. If either permission is not granted, the Activity is finished with an error message. */ class MyLocationDemoActivity : AppCompatActivity(), OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, OnRequestPermissionsResultCallback { /** * Flag indicating whether a requested permission has been denied after returning in * [.onRequestPermissionsResult]. */ private var permissionDenied = false private lateinit var map: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.my_location_demo) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(this) } override fun onMapReady(googleMap: GoogleMap) { map = googleMap googleMap.setOnMyLocationButtonClickListener(this) googleMap.setOnMyLocationClickListener(this) enableMyLocation() } /** * Enables the My Location layer if the fine location permission has been granted. */ @SuppressLint("MissingPermission") private fun enableMyLocation() { // 1. Check if permissions are granted, if so, enable the my location layer if (ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { map.isMyLocationEnabled = true return } // 2. If if a permission rationale dialog should be shown if (ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_FINE_LOCATION ) || ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_COARSE_LOCATION ) ) { PermissionUtils.RationaleDialog.newInstance( LOCATION_PERMISSION_REQUEST_CODE, true ).show(supportFragmentManager, "dialog") return } // 3. Otherwise, request permission ActivityCompat.requestPermissions( this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ), LOCATION_PERMISSION_REQUEST_CODE ) } override fun onMyLocationButtonClick(): Boolean { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false } override fun onMyLocationClick(location: Location) { Toast.makeText(this, "Current location:\n$location", Toast.LENGTH_LONG) .show() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { super.onRequestPermissionsResult( requestCode, permissions, grantResults ) return } if (isPermissionGranted( permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION ) || isPermissionGranted( permissions, grantResults, Manifest.permission.ACCESS_COARSE_LOCATION ) ) { // Enable the my location layer if the permission has been granted. enableMyLocation() } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true } } override fun onResumeFragments() { super.onResumeFragments() if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError() permissionDenied = false } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private fun showMissingPermissionError() { newInstance(true).show(supportFragmentManager, "dialog") } companion object { /** * Request code for location permission request. * * @see .onRequestPermissionsResult */ private const val LOCATION_PERMISSION_REQUEST_CODE = 1 } }
Java
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.mapdemo; import android.Manifest.permission; import android.annotation.SuppressLint; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener; import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.widget.Toast; /** * This demo shows how GMS Location can be used to check for changes to the users location. The "My * Location" button uses GMS Location to set the blue dot representing the users location. * Permission for {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and {@link * android.Manifest.permission#ACCESS_COARSE_LOCATION} are requested at run time. If either * permission is not granted, the Activity is finished with an error message. */ public class MyLocationDemoActivity extends AppCompatActivity implements OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, ActivityCompat.OnRequestPermissionsResultCallback { /** * Request code for location permission request. * * @see #onRequestPermissionsResult(int, String[], int[]) */ private static final int LOCATION_PERMISSION_REQUEST_CODE = 1; /** * Flag indicating whether a requested permission has been denied after returning in {@link * #onRequestPermissionsResult(int, String[], int[])}. */ private boolean permissionDenied = false; private GoogleMap map; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_location_demo); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(@NonNull GoogleMap googleMap) { map = googleMap; map.setOnMyLocationButtonClickListener(this); map.setOnMyLocationClickListener(this); enableMyLocation(); } /** * Enables the My Location layer if the fine location permission has been granted. */ @SuppressLint("MissingPermission") private void enableMyLocation() { // 1. Check if permissions are granted, if so, enable the my location layer if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { map.setMyLocationEnabled(true); return; } // 2. Otherwise, request location permissions from the user. PermissionUtils.requestLocationPermissions(this, LOCATION_PERMISSION_REQUEST_CODE, true); } @Override public boolean onMyLocationButtonClick() { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG).show(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); return; } if (PermissionUtils.isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION) || PermissionUtils .isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_COARSE_LOCATION)) { // Enable the my location layer if the permission has been granted. enableMyLocation(); } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true; } } @Override protected void onResumeFragments() { super.onResumeFragments(); if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError(); permissionDenied = false; } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private void showMissingPermissionError() { PermissionUtils.PermissionDeniedDialog .newInstance(true).show(getSupportFragmentManager(), "dialog"); } }
Il livello La mia posizione
Puoi utilizzare il livello La mia posizione e il pulsante La mia posizione per mostrare all'utente la sua posizione attuale sulla mappa. Chiama mMap.setMyLocationEnabled()
per attivare il livello La mia posizione sulla mappa.
L'esempio seguente mostra un semplice utilizzo del livello La mia posizione:
Kotlin
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.maps.example.kotlin import android.annotation.SuppressLint import android.location.Location import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.maps.example.R internal class MyLocationLayerActivity : AppCompatActivity(), OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_my_location) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } @SuppressLint("MissingPermission") override fun onMapReady(map: GoogleMap) { // TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.isMyLocationEnabled = true map.setOnMyLocationButtonClickListener(this) map.setOnMyLocationClickListener(this) } override fun onMyLocationClick(location: Location) { Toast.makeText(this, "Current location:\n$location", Toast.LENGTH_LONG) .show() } override fun onMyLocationButtonClick(): Boolean { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false } }
Java
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.maps.example; import android.annotation.SuppressLint; import android.location.Location; import android.os.Bundle; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; class MyLocationLayerActivity extends AppCompatActivity implements GoogleMap.OnMyLocationButtonClickListener, GoogleMap.OnMyLocationClickListener, OnMapReadyCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_location); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @SuppressLint("MissingPermission") @Override public void onMapReady(GoogleMap map) { // TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.setMyLocationEnabled(true); map.setOnMyLocationButtonClickListener(this); map.setOnMyLocationClickListener(this); } @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG) .show(); } @Override public boolean onMyLocationButtonClick() { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } }
Quando il livello La mia posizione è attivo, il pulsante La mia posizione viene visualizzato nell'angolo in alto a destra della mappa. Quando un utente fa clic sul pulsante, la fotocamera centra la mappa sulla posizione attuale del dispositivo, se nota. Il luogo è indicato sulla mappa da un puntino blu se il dispositivo è fermo, o come gallone, se il dispositivo è in movimento.
Il seguente screenshot mostra il pulsante La mia posizione in alto a destra e l'icona Punto blu di La mia posizione al centro della mappa:
Puoi impedire la visualizzazione del pulsante La mia posizione chiamando
UiSettings.setMyLocationButtonEnabled(false)
.
La tua app può rispondere ai seguenti eventi:
- Se l'utente fa clic sul pulsante La mia posizione, la tua app riceve un callback
onMyLocationButtonClick()
daGoogleMap.OnMyLocationButtonClickListener
. - Se l'utente fa clic sul punto blu di La mia posizione, la tua app riceve
Chiamata di
onMyLocationClick()
dalGoogleMap.OnMyLocationClickListener
API Google Play Services Location
L'API Location di Google Play Services è il metodo preferito per aggiungere la consapevolezza della posizione alla tua applicazione Android. Include funzionalità che ti consentono di:
- Determinare la posizione del dispositivo.
- Monitora i cambiamenti di località.
- Determina il mezzo di trasporto, se il dispositivo è in movimento.
- Crea e monitora regioni geografiche predefinite, note come recinti virtuali.
Le API di localizzazione ti consentono di creare facilmente campagne a efficienza energetica, che utilizzano la localizzazione. Come Maps SDK for Android, il campo L'API è distribuita come parte dell'SDK Google Play Services. Per maggiori informazioni informazioni sull'API Location, fai riferimento al corso di formazione su Android Rendere l'app Location Aware o API Location Riferimento. Gli esempi di codice sono inclusi nel modulo SDK Play Services.