Статьи

Android геозон с Google Maps

Геозона — это интересный виртуальный периметр, который может быть настроен на срабатывание уведомлений при входе или выходе из них, либо в обоих случаях. Например, приложение геозоны может предупредить нас о том, что наш ребенок покинул ранее указанную область, или отправить нам купон (например, тип предложения «Подарите это SMS и получите скидку 20%»), когда нам случается гулять или ездить поблизости. кинотеатра. Теперь, с новыми API определения местоположения, алгоритм местоположения Google был переписан, чтобы быть более точным и использовать значительно меньше времени автономной работы. Достаточно документации, примеров кода и загружаемого примера приложения ( GeofenceDetection ), чтобы помочь нам начать создавать приложения геозон. Необходимые условия:

  1. Загрузите Google Play Services (через Android SDK Manager) и настройте его как библиотеку
  2. Получите ключ API Карт Google v2 и, возможно, запустите пример приложения. Это краткое руководство может помочь
  3. Загрузите (снова через SDK Manager) библиотеку поддержки для обслуживания более старых версий Android.

В практических целях давайте просто начнем с того, где останавливается пример приложения геозон (GeofenceDetection), и представим несколько улучшений, которые сделают приложение полуоприличным и продемонстрируют пример возможностей с новым API местоположения.

1. Масштаб и положение камеры

Сначала немного о Google Maps API v2. Давайте выберем уровень масштабирования и угол наклона камеры:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
//...
// inside class, for a given lat/lon
CameraPosition INIT =
new CameraPosition.Builder()
.target(new LatLng(lat, lon))
.zoom( 17.5F )
.bearing( 300F) // orientation
.tilt( 50F) // viewing angle
.build();
 // use GooggleMap mMap to move camera into position
 mMap.animateCamera( CameraUpdateFactory.newCameraPosition(INIT) );

Код выше имеет уровень масштабирования, позволяющий просматривать здания в 3D. Google Maps v2 использует OpenGL для встраиваемых систем ( OpenGL ES v2) для визуализации 2D и 3D компьютерной графики.

2. Меню настроек

Даже если мы не большие поклонники меню «Опции», в этом случае оно может быть адекватным, поскольку мы не хотели бы загромождать карту слишком большим «сенсорным» функционалом (у нас скоро будет много этого).

Мы можем переключаться между «нормальным» и спутниковым обзором:

1
2
3
4
5
6
7
8
9
/**
 * Toggle View Satellite-Normal
 */
 public static void toggleView(){
 mMap.setMapType( mMap.getMapType() ==
              GoogleMap.MAP_TYPE_NORMAL ?
              GoogleMap.MAP_TYPE_SATELLITE :
              GoogleMap.MAP_TYPE_NORMAL);
 }

Мы также можем предоставить «Режим полета», где мы позволяем камере прокручиваться. Не очень полезно, но все же круто:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
//...
private static CancelableCallback callback = new CancelableCallback() {
@Override
 public void onFinish() {
   scroll();
 }
 @Override
 public void onCancel() {}
};
 
public static void scroll() {
   // we don't want to scroll too fast since
  // loading new areas in map takes time
   mMap.animateCamera( CameraUpdateFactory.scrollBy(10, -10),
                       callback ); // 10 pix
}

3. Геокодирование / обратное геокодирование

Пример здесь для демонстрации особенностей и интенсивного использования координат широты / долготы. Но нам нужно предоставить более удобный способ взаимодействия с местами на карте, например адрес улицы. Мы можем использовать геокодирование / обратное геокодирование для преобразования адреса улицы в координаты и наоборот, используя геокодер Android .

4. Добавление геозон

Хорошо, теперь на геозоны. Благодаря геокодированию мы можем запросить у пользователя фактический физический адрес, а не координаты. Мы просто изменим этот адрес на пару широта / долгота внутри, чтобы обработать пользовательский ввод. Обратите внимание, как мы максимально используем прозрачные пользовательские интерфейсы, чтобы улучшить то, что некоторые могут назвать пользовательским интерфейсом. Также обратите внимание, что мы предоставляем спиннер, чтобы пользователь мог выбирать между предопределенными значениями. Это избавляет пользователя от набора текста и избавляет нас от проверки значений координат каждый раз.

Тем не менее, если мы хотим быть еще более удобными для пользователей, мы можем дать нашим пользователям возможность предварительно заполнить поле адреса, нажав и удерживая нажатой точку на карте. Затем мы будем использовать обратное геокодирование для перевода координат в физический адрес для отображения (экран внизу справа):

Обработка длинных прессов довольно проста:

01
02
03
04
05
06
07
08
09
10
11
12
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
//...
public class MainActivity extends FragmentActivity
                          implements OnMapLongClickListener  {
  //...
  mMap.setOnMapLongClickListener(this);
  //...
  @Override
  public void onMapLongClick(LatLng point) {
     // reverse geocode point
  }
}

Добавление / удаление геозон в значительной степени описано в примере приложения (классы GeofenceRequester и GeofenceRemover ). Следует помнить, что процесс добавления / удаления заборов выглядит следующим образом:

  1. Наше приложение запрашивает подключение к службам определения местоположения Google.
  2. Как только / если соединение доступно, запрос на добавление / удаление ограждения выполняется с использованием PendingIntent .
  3. Если аналогичный запрос, сделанный нашим приложением, все еще выполняется, операция завершается ошибкой.
  4. Несмотря на то, что метод, который мы вызываем (например, addGeofences () ), возвращается сразу, мы не будем знать, был ли запрос успешным, пока Службы определения местоположения не перезвонят в наше приложение (например, onAddGeofencesResult () OnAddGeofencesResultListener с кодом состояния успеха.
  5. Наконец, предыдущий метод будет использовать Broadcast Intent, чтобы уведомить другие компоненты нашего приложения об успехе / неудаче.

Излишне говорить, что нам нужно защищаться практически на каждом этапе пути. Теперь, когда геозона добавлена, мы можем добавить маркер (по умолчанию или индивидуальный) и выбирать различные формы (круг, многоугольник и т. Д.), Чтобы разграничить геозону. Например, мы можем написать этот код, чтобы добавить маркер по умолчанию и обвести забор в пределах указанного радиуса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.MarkerOptions;
//...
public static void addMarkerForFence(SimpleGeofence fence){
if(fence == null){
    // display en error message and return
   return;
}
mMap.addMarker( new MarkerOptions()
  .position( new LatLng(fence.getLatitude(), fence.getLongitude()) )
  .title("Fence " + fence.getId())
  .snippet("Radius: " + fence.getRadius()) ).showInfoWindow();
 
//Instantiates a new CircleOptions object +  center/radius
CircleOptions circleOptions = new CircleOptions()
  .center( new LatLng(fence.getLatitude(), fence.getLongitude()) )
  .radius( fence.getRadius() )
  .fillColor(0x40ff0000)
  .strokeColor(Color.TRANSPARENT)
  .strokeWidth(2);
 
// Get back the mutable Circle
Circle circle = mMap.addCircle(circleOptions);
// more operations on the circle...
 
}

Вот итоговые экраны, в том числе тот, который мы получаем, как только «коснемся для редактирования» информационного окна:

В примере приложения есть все, что нам нужно для запуска уведомлений после входа или выхода из обведенной выше области. Обратите внимание, как мы настроили информационное окно маркера, чтобы разрешить редактирование радиуса геозоны или удаление геозоны в целом. Для реализации интерактивного настраиваемого информационного окна все, что нам нужно, — это создать собственные InfoWindowAdapter и OnInfoWindowClickListener .

Что касается самих уведомлений, то вот как они выглядят в примере приложения:

Конечно, мы можем изменить внешний вид и функциональность уведомления, и … это будет предметом другой статьи. Надеемся, что это дало представление о том, что возможно с новым Location API. Веселитесь с Android геозон.

Ссылка: Android Geofencing с Google Maps от нашего партнера JCG Тони Сицилиана в блоге Tony’s Blog .