Місцезнаходження користувача на Android
Отримати місцезнаходження користувача на Android трохи простіше, ніж на iOS. Щоб почати плутанину, є два абсолютно різні способи зробити це. Перший - це використання API Android від android.location.LocationListener
, а другий - API API Google Play Services com.google.android.gms.location.LocationListener
. Переглянемо їх обох.
API розташування Android
API розташування Android використовують три різних постачальника, щоб отримати місцезнаходження -
LocationManager.GPS_PROVIDER
- Цей провайдер визначає місцезнаходження за допомогою супутників. Залежно від умов, цей постачальник може зайняти деякий час, щоб повернути виправлення місцеположення.
LocationManager.NETWORK_PROVIDER
- Цей провайдер визначає місцеположення залежно від наявності стільникових башт та точок доступу Wi-Fi. Результати отримують за допомогою мережевого пошуку.
LocationManager.PASSIVE_PROVIDER
- Цей постачальник поверне місця, створені іншими постачальниками. Ви пасивно отримуєте оновлення місцеположення, коли інші додатки чи служби їх вимагають, не фактично запитуючи їх про місцезнаходження.
Суть його полягає в тому, що ви отримуєте об'єкт LocationManager
від системи, реалізуєте LocationListener
і викликаєте requestLocationUpdates
на LocationManager
.
Ось фрагмент коду:
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
Посібник з API Google щодо стратегій розташуванняпояснює код досить добре. Але вони також зазначають, що в більшості випадків ви отримаєте кращі показники роботи акумулятора, а також більш відповідну точність, використовуючи натомість API локальних служб Google . Тепер плутанина починається!
- API служби локації Google
API локальних служб Google є частиною APK служб Google Play ( ось як його налаштувати ). Вони побудовані на основі API Android. Ці API надають "Постачальника плавного розташування" замість згаданих вище постачальників. Цей постачальник автоматично вибирає, який саме постачальник використовуватиметься, виходячи з точності, використання акумулятора тощо. Це швидко, оскільки ви отримуєте місцезнаходження від загальносистемної служби, яка постійно його оновлює. І ви можете використовувати більш вдосконалені функції, такі як географічне огородження.
Щоб використовувати служби локації Google, ваш додаток повинен підключитися до GooglePlayServicesClient
. Для підключення до клієнта ваша діяльність (або фрагмент тощо) потребує впровадження GooglePlayServicesClient.ConnectionCallbacks
та GooglePlayServicesClient.OnConnectionFailedListener
інтерфейсів. Ось зразок коду:
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
LocationClient locationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
locationClient = new LocationClient(this, this, this);
}
@Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation() ;
Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisconnected() {
Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// code to handle failed connection
// this code can be found here — http://developer.android.com/training/location/retrieve-current.html
}
- Чому дорівнює
locationClient.getLastLocation()
нулю?
locationClient.getLastLocation()
Отримує останнє відоме місце розташування від клієнта. Однак Провайдер злитого розташування підтримуватиме фонове розташування лише в тому випадку, якщо до нього підключений хоча б один клієнт. Після підключення першого клієнта він негайно спробує отримати місцезнаходження. Якщо ваша діяльність є першим клієнтом для підключення і ви дзвоните getLastLocation()
відразу в onConnected()
, що не може бути достатньо часу для першого місця , щоб увійти. Це призведе до location
бути null
.
Щоб вирішити цю проблему, вам доведеться почекати (невизначено), поки постачальник не отримає місцезнаходження, а потім зателефонувати getLastLocation()
, що неможливо дізнатися. Інший (кращий) варіант - це реалізувати com.google.android.gms.location.LocationListener
інтерфейс для отримання періодичних оновлень місцеположення (і вимкнути його, як тільки ви отримаєте перше оновлення).
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
// . . . . . . . . more stuff here
LocationRequest locationRequest;
LocationClient locationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
// . . . . other initialization code
locationClient = new LocationClient(this, this, this);
locationRequest = new LocationRequest();
// Use high accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
locationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
locationRequest.setFastestInterval(FASTEST_INTERVAL);
}
// . . . . . . . . other methods
@Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation();
if (location == null)
locationClient.requestLocationUpdates(locationRequest, this);
else
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
// . . . . . . . . other methods
@Override
public void onLocationChanged(Location location) {
locationClient.removeLocationUpdates(this);
// Use the location here!!!
}
У цьому коді ви перевіряєте, чи клієнт уже має останнє місцезнаходження (в onConnected
). Якщо ні, ви запитуєте оновлення місцеположення та вимикаєте запити (у onLocationChanged()
зворотному дзвінку), як тільки отримуєте оновлення.
Зауважте, що locationClient.requestLocationUpdates(locationRequest, this);
повинно бути всередині onConnected
зворотного дзвінка, інакше у вас з’явиться запит, IllegalStateException
оскільки ви намагаєтеся подати запит на розташування без підключення до клієнта Служб Google Play.
- Користувач відключив Служби локації
У багатьох випадках користувач відключав послуги локації (для економії акумулятора чи причин конфіденційності). У такому випадку наведений вище код все одно запитуватиме оновлення місцеположення, але onLocationChanged
ніколи не буде викликаний. Ви можете зупинити запити, перевіривши, чи користувач відключив послуги локації.
Якщо ваш додаток вимагає, щоб вони ввімкнули послуги локації, ви хочете показати повідомлення чи тост. На жаль, немає можливості перевірити, чи користувач вимкнув служби локації в API локальних служб Google. Для цього вам доведеться вдатися до API Android.
У вашому onCreate
методі:
LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationEnabled = false;
Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;
І використовуйте locationEnabled
прапор у своєму onConnected
методі так:
if (location != null) {
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
locationClient.requestLocationUpdates(locationRequest, this);
}
ОНОВЛЕННЯ
Документ оновлюється, LocationClient видаляється, а api підтримує включення GPS одним натисканням кнопки з діалогового вікна:
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
}
});
task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
Посилання https://developer.android.com/training/location/change-location-settings#prompt
Новий клієнт локації: FusedLocationProviderClient
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
Рекомендується пройти https://developer.android.com/training/location, перш ніж виконувати будь-які завдання щодо локації.