Статьи

Android SDK: работа с Google Maps — интеграция с Google Places

Карты Google предоставляют разработчикам Android инструменты локализации, которые могут быть включены в ваши собственные интерфейсы приложений. В этой серии мы создаем базовое приложение для Android с интеграцией Google Maps и Google Places. В этой части мы получим доступ к API Google Адресов, чтобы получить информацию о достопримечательностях рядом с текущим местоположением пользователя. Мы будем использовать возвращенные данные для представления маркеров для каждого места на карте в заключительной части этой серии уроков. Мы также настроим приложение на обновление маркеров карты при изменении местоположения пользователя.

Это третья из четырех частей серии руководств по использованию карт Google и Google Places в приложениях для Android :

Приложение, к которому мы работаем
Это снимок финального приложения.

В первой части этой серии мы использовали консоль API Google, чтобы получить ключ API для инструментов отображения. Теперь нам нужно сделать то же самое для API Google Адресов. Войдите в свою учетную запись Google и снова перейдите к консоли . Выберите Сервисы из опций в левом столбце и прокрутите вниз до записи для API Адресов . Нажмите, чтобы включить места для своей учетной записи.

API мест

Помните, что вам нужно выполнить этот шаг для любой службы API Google, к которой вы хотите получить доступ, поскольку ваши ключи не будут работать в противном случае.

Теперь нам нужно получить ключ для доступа к API Places. Выберите API Access в левом столбце в консоли API Google. Вы увидите страницу, которую мы использовали в первой части серии, чтобы получить ключ API для пакета сопоставления. Хотя мы собираемся использовать API Адресов в приложении для Android, тип доступа на самом деле такой же, как и для браузерных приложений. Когда мы получаем данные Places, мы запрашиваем их с помощью URL-адреса и получаем результаты в формате JSON, как в веб-приложении. Скопируйте ключ, указанный в разделе « Ключ для приложений браузера », и сохраните его.

Ключ API мест

Мы закончили с консолью API Google, поэтому не стесняйтесь выйти из своей учетной записи.


Google Places API предоставляет различную информацию о местах. Для нашего приложения мы собираемся использовать запрос Поиск места, чтобы вернуть список мест рядом с текущим местоположением пользователя. Нам нужно встроить необходимые элементы в строку запроса URL, чтобы выполнить поиск по месту. Это основной формат URL:

1
https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters

Вывод может быть JSON или XML; мы будем использовать JSON для этого приложения. К URL-адресу должны быть добавлены различные обязательные параметры, включая ваш ключ API, местоположение пользователя в виде значений долготы и широты, радиус для поиска в нем и логический флаг, указывающий, было ли получено местоположение из датчика местоположения, такого как GPS. Существуют различные необязательные параметры, которые вы можете добавить в свой запрос; см. документацию Поиск места для обзора. Для целей этого приложения мы добавим необязательный параметр types для поиска мест определенных типов.

Это показатель того, как будет выглядеть окончательный запрос:

1
2
3
4
5
6
https://maps.googleapis.com/maps/api/place/nearbysearch/json?
    location=55.864237,-4.251805999999988
    &radius=1000
    &sensor=true
    &types=food|bar|store|museum|art_gallery
    &key=your_api_key

Мы будем строить значения долготы и широты динамически (приведенные выше примерные значения просто для демонстрации). Значение радиуса указано в метрах, поэтому не стесняйтесь изменять его в соответствии с целями своего приложения. Вы также можете изменить типы мест, если хотите; см. обзор поддерживаемых типов мест для доступных опций. Убедитесь, что вы разделяете типы мест, используя трубу «|» персонаж. Конечно, вы должны изменить значение параметра ключа, чтобы оно отражало ваш собственный ключ API.

В вашем вспомогательном методе класса Activity updatePlaces после существующего кода, в котором мы получили местоположение пользователя и анимировали на него камеру карты, создайте строку для URL поиска по месту:

1
2
3
4
5
String placesSearchStr = «https://maps.googleapis.com/maps/api/place/nearbysearch/» +
    «json?location=»+lat+»,»+lng+
    «&radius=1000&sensor=true» +
    «&types=food|bar|store|museum|art_gallery»+
    «&key=your_key_here»;

Включите ключ API, который вы скопировали из консоли API Google для приложений браузера. Обратите внимание, что мы передаем значения широты и долготы, которые мы ранее извлекли из местоположения пользователя.


Вам нужно будет добавить следующие операторы импорта в ваш класс Activity для кода, который мы будем использовать далее:

01
02
03
04
05
06
07
08
09
10
11
12
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
 
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
 
import android.os.AsyncTask;

Поскольку мы будем извлекать данные через Интернет, мы будем использовать AsyncTask для выполнения этого процесса вне потока пользовательского интерфейса. Это позволит нам обрабатывать результаты в потоке пользовательского интерфейса, добавляя маркеры на видимую карту, когда приложение получает данные поиска места.

В своем классе Activity создайте схему класса AsyncTask следующим образом:

1
private class GetPlaces extends AsyncTask<String, Void, String> { //fetch and parse place data }

Указанные три типа представляют типы параметров, единицы измерения и результат фоновой операции. Мы передадим URL поиска по месту в виде строки, так что это параметр. Мы не будем указывать прогресс для этого приложения, поэтому второй тип является недействительным. Результатом фоновой операции в этом случае будет строка JSON, представляющая места, поэтому третий тип — текстовая строка.

Когда вы используете AsyncTask , вы указываете обработку, которую вы хотите выполнить в фоновом режиме в методе doInBackground . Как только он выполнил и получил результат, будет выполнен метод onPostExecute . Для этого приложения мы получим результаты поиска по месту в doInBackground , а затем проанализируем результаты в onPostExecute , создавая маркеры, которые будут отображаться на карте одновременно.

Внутри вашего класса AsyncTask добавьте метод doInBackground :

1
2
3
4
@Override
protected String doInBackground(String… placesURL) {
    //fetch places
}

Тип параметра — строка, как указано в схеме класса выше. Давайте используем String Builder для построения возвращаемой текстовой строки JSON внутри этого нового метода:

1
StringBuilder placesBuilder = new StringBuilder();

Хотя мы передадим только одну строку URL-адреса запроса поиска по месту, метод doInBackground предполагает получение массива параметров, поэтому добавим цикл для его обработки:

1
2
3
4
//process search parameter string(s)
for (String placeSearchURL : placesURL) {
//execute search
}

Внутри цикла создайте объект HTTP-клиента для выполнения URL-адреса запроса:

1
HttpClient placesClient = new DefaultHttpClient();

Как и в случае любого процесса ввода / вывода, нам нужно позаботиться о возможных ошибках, поэтому добавьте блоки try и catch далее, все еще внутри цикла:

1
2
3
4
5
6
try {
    //try to fetch the data
}
catch(Exception e){
    e.printStackTrace();
}

Внутри блока try создайте объект HTTP Get, передав строку URL:

1
HttpGet placesGet = new HttpGet(placeSearchURL);

Используйте HTTP-клиент для выполнения этого, получив HTTP-ответ:

1
HttpResponse placesResponse = placesClient.execute(placesGet);

Давайте проверим, что у нас есть положительный ответ, прежде чем мы предпримем дальнейшую обработку. Получить строку состояния:

1
StatusLine placeSearchStatus = placesResponse.getStatusLine();

Мы можем продолжить, только если у нас есть код состояния «ОК» 200, указывающий на успешность запроса, поэтому добавьте условный оператор:

1
2
3
if (placeSearchStatus.getStatusCode() == 200) {
//we have an OK response
}

Внутри блока if извлеките сущность HTTP из объекта ответа:

1
HttpEntity placesEntity = placesResponse.getEntity();

Теперь мы можем начать получать фактическое содержимое ответа, которое должно быть строкой JSON. Начните с создания входного потока:

1
InputStream placesContent = placesEntity.getContent();

Теперь создайте читателя для этого потока:

1
InputStreamReader placesInput = new InputStreamReader(placesContent);

Давайте выполним обработку нашего входного потока с помощью Buffered Reader:

1
BufferedReader placesReader = new BufferedReader(placesInput);

Теперь мы можем использовать цикл для чтения входных данных по одной строке за раз, добавляя каждую из них в String Builder по мере продвижения:

1
2
3
4
String lineIn;
while ((lineIn = placesReader.readLine()) != null) {
    placesBuilder.append(lineIn);
}

Этот цикл будет продолжаться до тех пор, пока есть данные для чтения.

Наконец, мы можем вернуть строку, которая обрабатывается String Builder. В конце метода doInBackground после цикла for верните данные JSON:

1
return placesBuilder.toString();

Третья часть этого урока завершена. Мы настроили приложение на использование API Google Places и создали внутренний класс для извлечения данных о местах в фоновом режиме из основного потока пользовательского интерфейса приложения. Мы выполнили запрос Place Search и получили полученный JSON. Когда вы запускаете свое приложение, оно не будет вести себя иначе, чем после предыдущей части этой серии. Это потому, что мы еще не завершили или не создали экземпляр класса AsyncTask . Мы сделаем это в заключительной части, после того как добавим метод onPostExecute, чтобы проанализировать результат поиска JSON Place и преобразовать его в маркеры карты. Мы также расширим приложение, чтобы обновлять отображаемые маркеры при изменении местоположения пользователя.