Добрый день, Друзья!
Вопрос определения местоположения пользователя на максимальном количестве девайсов мучил меня примерно пол года. Дело доходило даже до велосипедов, описанных тут и тут. Дело было в том, что находились устройства, на которых местоположение не определялось, по неизвестной причине, однако другие приложения работали вполне хорошо. Очередной раз, копаясь в коде и рыская в просторах гула в поисках того, что я упускаю, и реализации, которой я еще не опробовал, наткнулся на свеженькую статью-мануал от google и, о боги(!), это заработало.
В данной статье я хочу рассказать, как я использовал это в своих целях и привести простой пример.
В официальном примере показывается как все это сделать в одном activity, так как им важно показать только возможности, а мне нужно было удобство, поэтому я все вынес в отдельный класс.
Для начала работы, необходимо инициализировать экземпляры классов LocationClient и LocationRequest. Первый отвечает за доступ к основным методам API определения местоположения и Geofence, второй обслуживает LocationClient и отвечает за обновления, т.е через него осуществляются колбэки(callbacks). С помощью LocationRequest, как в примере ниже, можно задавать интервалы обновления, приоритет для точности позиционирования и интервалы обновления.
private LocationRequest mLocationRequest;
private LocationClient mLocationClient;
private LocationListenerGPServices(final Context context)
{
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setFastestInterval(FAST_INTERVAL_CEILING_IN_MILLISECONDS);
mLocationClient = new LocationClient(context, this, this);
}
Далее есть два варианта развития событий: мы можем взять последнее известное местоположение или запросить поиск нового.
В моем случае, я комбинирую эти два варианта, т.е в начале я получаю последнее известное местоположение и, если оно меня устраивает, использую его, иначе я запрашиваю обновления. В коде ниже, после вызова метода mLocationClient.connect() должен сработать метод onConnected(final Bundle bundle) у интерфейса GooglePlayServicesClient.ConnectionCallbacks, который означает, что нам удалось подключиться к Сервисам Google Play, т.е. теперь мы можем подписаться на обновление местоположения.
public void enableMyLocation()
{
log("enableMyLocation");
mLocation = null;
mLocationClient.connect();
}
private boolean useCurrentLocation()
{
final Location location = mLocationClient.getLastLocation();
if (System.currentTimeMillis() - location.getTime() < HALF_MINUTE)
{
log("useCurrentLocation");
disableMyLocation();
if (locationRunnable != null)
locationRunnable.locationUpdate(location);
return true;
}
return false;
}
Когда мы запросили определение местоположения, чтобы скоротать как то время и не грузить UI — поток, я использую AsynkTask в качестве таймаута, который работает какое-то заданное время, и по завершению возвращает приложению найденное местоположение и отписывается от обновлений местоположения.
@Override
public void onConnected(final Bundle bundle)
{
if (!useCurrentLocation())
{
mLocationClient.requestLocationUpdates(mLocationRequest, this);
if (findLocation != null && !findLocation.isCancelled())
findLocation.cancel(true);
findLocation = new FindLocation();
findLocation.execute();
}
}
private Location endFind()
{
long sec = System.currentTimeMillis();
while (this.mLocation == null && System.currentTimeMillis() - sec < TIME_OUT)
{}
return this.mLocation;
}
private class FindLocation extends AsyncTask<Void, Void, Location>
{
@Override
protected Location doInBackground(final Void... params)
{return endFind();}
@Override
protected void onPostExecute(final Location location)
{
if (locationRunnable != null)
locationRunnable.locationUpdate(location);
disableMyLocation();
}
}
@Override
public void disableMyLocation()
{
if (mLocationClient.isConnected())
mLocationClient.removeLocationUpdates(this);
mLocationClient.disconnect();
}
public interface LocationRunnable
{ public void locationUpdate(Location location);}
Собственно как это использовать пример с github:
Для начала нужно получить экземпляр класса, для себя я реализовал singletone, так как он более подходит, для моего случая
locationListener = LocationListenerGPServices.getInstance(this);
Затем подписаться на получение местоположения и делать все, что вздумается с ним.
locationListener.setLocationRunnable(new ILocationListener.LocationRunnable() {
@Override
public void locationUpdate(final Location location)
{}});
Собственно вот и все, что я хотел рассказать по данной теме. Тут я постарался рассказать в кратце, и привел минимум кода по тексту, в исходниках на github я показал на примере, как найти местоположение пользователя и отсортировать список станций метро по расстоянию до пользователя.
Спасибо за внимание, надеюсь кому-то это поможет и избавит от мучений.
Автор: andreich
у меня украли телефон,как я его могу найти