Начало работы
Для работы с SDK нужно вызвать метод initialize()
объекта DGis, указав контекст приложения и набор ключей доступа (объект ApiKeys).
В SDK используется два ключа: map
(основной ключ SDK) и directory
(ключ доступа к дополнительным API: справочнику объектов и маршрутизатору).
class Application : Application() {
lateinit var sdkContext: Context
override fun onCreate() {
super.onCreate()
sdkContext = DGis.initialize(
this, ApiKeys(
directory = "Directory API key",
map = "SDK key"
)
)
}
}
Обратите внимание, что нельзя создавать более одного экземпляра Context.
Дополнительно можно указать настройки журналирования (LogOptions) и настройки HTTP-клиента (HttpOptions), такие как кеширование.
// Ключи доступа
val apiKeys = ApiKeys(
directory = "Directory API key",
map = "SDK key"
)
// Настройки журналирования
val logOptions = LogOptions(
LogLevel.VERBOSE
)
// Настройки HTTP-клиента
val httpOptions = HttpOptions(
useCache = false
)
// Согласие на сбор и отправку персональных данных
val dataCollectConsent = PersonalDataCollectionConsent.GRANTED
sdkContext = DGis.initialize(
appContext = this,
apiKeys = apiKeys,
dataCollectConsent = dataCollectConsent,
logOptions = logOptions,
httpOptions = httpOptions
)
Начало работы с версии 4.x
Сначала нужно обратиться в техническую поддержку 2ГИС для получения нового ключа. Обязательно нужно указать appId
приложения, для которого будет создан ключ. Полученный файл ключа dgissdk.key
нужно добавить assets
.
Для работы с SDK нужно вызвать метод initialize()
объекта DGis, указав контекст приложения.
class Application : Application() {
lateinit var sdkContext: Context
override fun onCreate() {
super.onCreate()
sdkContext = DGis.initialize(
this
)
}
}
Обратите внимание, что нельзя создавать более одного экземпляра Context.
Дополнительно можно указать настройки журналирования (LogOptions) и настройки HTTP-клиента (HttpOptions), такие как кеширование.
// Настройки журналирования
val logOptions = LogOptions(
LogLevel.VERBOSE
)
// Настройки HTTP-клиента
val httpOptions = HttpOptions(
useCache = false
)
// Согласие на сбор и отправку персональных данных
val dataCollectConsent = PersonalDataCollectionConsent.GRANTED
sdkContext = DGis.initialize(
appContext = this,
dataCollectConsent = dataCollectConsent,
logOptions = logOptions,
httpOptions = httpOptions
)
Создание карты
Чтобы создать карту, добавьте MapView в ваш activity:
<ru.dgis.sdk.map.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:dgis_cameraTargetLat="55.740444"
app:dgis_cameraTargetLng="37.619524"
app:dgis_cameraZoom="16.0"
/>
Для карты можно указать начальные координаты (cameraTargetLat
- широта; cameraTargetLng
- долгота) и масштаб (cameraZoom
).
MapView также можно создать программно. В таком случае настройки можно указать в виде объекта MapOptions.
Объект карты (Map) можно получить, вызвав метод getMapAsync()
:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val sdkContext = DGis.initialize(applicationContext, apiKeys)
setContentView(R.layout.activity_main)
val mapView = findViewById<MapView>(R.id.mapView)
lifecycle.addObserver(mapView)
mapView.getMapAsync { map ->
// Действия с картой
val camera = map.camera
}
}
Общие принципы работы
Отложенные результаты
Некоторые методы SDK (например те, которые обращаются к удалённому серверу) возвращают отложенные результаты (Future). Для работы с ними нужно создать обработчик получения данных и обработчик ошибок.
Пример получения объекта из справочника:
// Создание объекта для поиска по справочнику
val searchManager = SearchManager.createOnlineManager(sdkContext)
// Получение объекта из справочника по идентификатору
val future = searchManager.searchByDirectoryObjectId(objectId)
// Обработка результата
future.onResult { directoryObject ->
Log.d("APP", "Название объекта: ${directoryObject.title}")
}
// Обработка ошибки
future.onError { error ->
Log.d("APP", "Ошибка получения информации об объекте.")
}
По умолчанию обработка результатов происходит в UI-потоке. Чтобы это изменить, для onResult
и onError
можно указать Executor.
Подробнее про работу со справочником можно посмотреть в разделе Справочник объектов.
Потоки значений
Некоторые объекты SDK предоставляют потоки значений, которые можно обработать, используя механизм каналов: на поток можно подписаться, указав функцию-обработчик данных, и отписаться, когда обработка данных больше не требуется. Для работы с потоками значений используется интерфейс Channel.
Пример подписки на изменение видимой области карты (поток новых прямоугольных областей):
// Выбираем канал (прямоугольники видимой области карты)
val visibleRectChannel = map.camera.visibleRectChannel
// Подписываемся и обрабатываем результаты в главной очереди. Значения будут присылаться при любом изменении видимой области до момента отписки.
// Важно сохранить соединение с каналом, иначе подписка будет уничтожена.
val connection = visibleRectChannel.connect { geoRect ->
Log.d("APP", "${geoRect.southWestPoint.latitude.value}")
}
После окончания работы с каналом важно отменить подписку, чтобы избежать утечки памяти. Для этого нужно вызвать метод close()
:
connection.close()
Источники данных для карты
В некоторых случаях для добавления объектов на карту нужно создать специальный объект - источник данных. Источники данных выступают в роли менеджеров объектов: вместо добавления объектов на карту напрямую, на карту добавляется источник данных и вся последующая работа с объектами происходит через него.
Источники данных бывают разных типов: движущиеся маркеры, маршруты с отображением текущей загруженности дорог, произвольные геометрические фигуры и т.д. Для каждого типа данных существует свой класс.
В общем случае работа с источниками данных выглядит следующим образом:
// Создание источника данных
val source = MyMapObjectSource(
sdkContext,
...
)
// Добавление источника данных на карту
map.addSource(source)
// Добавление и удаление объектов в источнике данных
source.addObject(...)
source.removeObject(...)
Чтобы удалить созданный источник данных и все связанные с ним объекты, нужно вызвать метод карты removeSource()
:
map.removeSource(source)
Список активных источников данных можно получить, используя свойство map.sources
.
Добавление объектов
Для добавления динамических объектов на карту (маркеров, линий, кругов, многоугольников) нужно создать менеджер объектов (MapObjectManager), указав объект карты. При удалении менеджера объектов удаляются все связанные с ним объекты на карте, поэтому его нужно сохранить в activity.
mapObjectManager = MapObjectManager(map)
Для добавления объектов используются методы addObject() и addObjects(). Для каждого динамического объекта можно указать поле userData
, которое будет хранить произвольные данные, связанные с объектом. Настройки объектов можно менять после их создания.
Для удаления объектов используются методы removeObject() и removeObjects(). Чтобы удалить все объекты, можно использовать метод removeAll().
Маркер
Чтобы добавить маркер на карту, нужно создать объект Marker, указав нужные настройки, и передать его в вызов addObject()
менеджера объектов.
В настройках нужно указать координаты маркера (параметр position
).
val marker = Marker(
MarkerOptions(
position = GeoPointWithElevation(
latitude = 55.752425,
longitude = 37.613983
)
)
)
mapObjectManager.addObject(marker)
Чтобы изменить иконку маркера, нужно указать объект Image в качестве параметра icon
. Создать Image можно с помощью следующих функций:
val icon = imageFromResource(sdkContext, R.drawable.ic_marker)
val marker = Marker(
MarkerOptions(
position = GeoPointWithElevation(
latitude = 55.752425,
longitude = 37.613983
),
icon = icon
)
)
Чтобы изменить точку привязки иконки (выравнивание иконки относительно координат на карте), нужно указать параметр anchor.
Дополнительно можно указать текст для маркера и другие настройки (см. MarkerOptions).
Линия
Чтобы нарисовать на карте линию, нужно создать объект Polyline, указав нужные настройки, и передать его в вызов addObject()
менеджера объектов.
Кроме списка координат для точек линии, в настройках можно указать ширину линии, цвет, пунктир, обводку и другие параметры (см. PolylineOptions).
// Координаты вершин ломаной линии
val points = listOf(
GeoPoint(latitude = 55.7513, longitude = 37.6236),
GeoPoint(latitude = 55.7405, longitude = 37.6235),
GeoPoint(latitude = 55.7439, longitude = 37.6506)
)
// Создание линии
val polyline = Polyline(
PolylineOptions(
points = points,
width = 2.lpx
)
)
// Добавление линии на карту
mapObjectManager.addObject(polyline)
Свойство-расширение .lpx
преобразует целое число в объект LogicalPixel.
Многоугольник
Чтобы нарисовать на карте многоугольник, нужно создать объект Polygon, указав нужные настройки, и передать его в вызов addObject()
менеджера объектов.
Координаты для многоугольника указываются в виде двумерного списка. Первый вложенный список должен содержать координаты основных вершин многоугольника. Остальные вложенные списки не обязательны и могут быть заданы для того, чтобы создать вырез внутри многоугольника (один дополнительный список - один вырез в виде многоугольника).
Дополнительно можно указать цвет полигона и параметры обводки (см. PolygonOptions).
val polygon = Polygon(
PolygonOptions(
contours = listOf(
// Вершины многоугольника
listOf(
GeoPoint(latitude = 55.72014932919687, longitude = 37.562599182128906),
GeoPoint(latitude = 55.72014932919687, longitude = 37.67555236816406),
GeoPoint(latitude = 55.78004852149085, longitude = 37.67555236816406),
GeoPoint(latitude = 55.78004852149085, longitude = 37.562599182128906),
GeoPoint(latitude = 55.72014932919687, longitude = 37.562599182128906)
),
// Координаты для выреза внутри многоугольника
listOf(
GeoPoint(latitude = 55.754167897761, longitude = 37.62422561645508),
GeoPoint(latitude = 55.74450654680055, longitude = 37.61238098144531),
GeoPoint(latitude = 55.74460317215391, longitude = 37.63435363769531),
GeoPoint(latitude = 55.754167897761, longitude = 37.62422561645508)
)
),
borderWidth = 1.lpx
)
)
mapObjectManager.addObject(polygon)
Кластеризация
Для добавления маркеров на карту в режиме кластеризации нужно создать менеджер объектов (MapObjectManager) через MapObjectManager.withClustering(), указав инстанс карты, расстояние между кластерами в логических пикселях, максимальный zoom-уровень формирования кластеров и пользовательскую имплементацию протокола SimpleClusterRenderer. SimpleClusterRenderer используется для кастомизации кластеров в MapObjectManager.
val clusterRenderer = object : SimpleClusterRenderer {
override fun renderCluster(cluster: SimpleClusterObject): SimpleClusterOptions {
val textStyle = TextStyle(
fontSize = LogicalPixel(15.0f),
textPlacement = TextPlacement.RIGHT_TOP
)
val objectCount = cluster.objectCount
val iconMapDirection = if (objectCount < 5) MapDirection(45.0) else null
return SimpleClusterOptions(
icon,
iconWidth = LogicalPixel(30.0f),
text = objectCount.toString(),
textStyle = textStyle,
iconMapDirection = iconMapDirection,
userData = objectCount.toString()
)
}
}
mapObjectManager = MapObjectManager.withClustering(map, LogicalPixel(80.0f), Zoom(18.0f), clusterRenderer)
Управление камерой
Для работы с камерой используется объект Camera, доступный через свойство map.camera
.
Перелёт
Чтобы запустить анимацию перелёта камеры, нужно вызвать метод move() и указать параметры перелёта:
position
- конечная позиция камеры (координаты и уровень приближения). Дополнительно можно указать наклон и поворот камеры (см. CameraPosition).time
- продолжительность перелёта в секундах (Duration).animationType
- тип анимации (CameraAnimationType).
Функция move()
возвращает объект Future, который можно использовать, чтобы обработать событие завершения перелёта.
val mapView = findViewById<MapView>(R.id.mapView)
mapView.getMapAsync { map ->
val cameraPosition = CameraPosition(
point = GeoPoint(latitude = 55.752425, longitude = 37.613983),
zoom = Zoom(16.0),
tilt = Tilt(25.0),
bearing = Arcdegree(85.0)
)
map.camera.move(cameraPosition, Duration.ofSeconds(2), CameraAnimationType.LINEAR).onResult {
Log.d("APP", "Перелёт камеры завершён.")
}
}
Для указания продолжительности перелёта можно использовать расширение .seconds
:
map.camera.move(cameraPosition, 2.seconds, CameraAnimationType.LINEAR)
Для более точного контроля над анимацией перелёта можно использовать контроллер перелёта, который будет определять позицию камеры в каждый конкретный момент времени. Для этого нужно реализовать интерфейс CameraMoveController и передать созданный объект в метод move()
вместо параметров перелёта.
Получение состояния камеры
Текущее состояние камеры (находится ли камера в полёте) можно получить, используя свойство state
. См. CameraState для списка возможных состояний камеры.
val currentState = map.camera.state
Подписаться на изменения состояния камеры можно с помощью свойства stateChannel
.
// Подписка
val connection = map.camera.stateChannel.connect { state ->
Log.d("APP", "Состояние камеры изменилось на ${state}")
}
// Отписка
connection.close()
Получение позиции камеры
Текущую позицию камеры можно получить, используя свойство position
(см. объект CameraPosition).
val currentPosition = map.camera.position
Log.d("APP", "Координаты: ${currentPosition.point}")
Log.d("APP", "Приближение: ${currentPosition.zoom}")
Log.d("APP", "Наклон: ${currentPosition.tilt}")
Log.d("APP", "Поворот: ${currentPosition.bearing}")
Подписаться на изменения позиции камеры (и угла наклона/поворота) можно с помощью свойства positionChannel
.
// Подписка
val connection = map.camera.positionChannel.connect { position ->
Log.d("APP", "Изменилась позиция камеры или угол наклона/поворота.")
}
// Отписка
connection.close()
Моё местоположение
На карту можно добавить специальный маркер, который будет отражать текущее местоположение устройства. Для этого нужно добавить на карту источник данных MyLocationMapObjectSource.
// Создание источника данных
val source = MyLocationMapObjectSource(
sdkContext,
MyLocationDirectionBehaviour.FOLLOW_SATELLITE_HEADING
)
// Добавление источника данных на карту
map.addSource(source)
Получение объектов по экранным координатам
Информацию об объектах на карте можно получить, используя пиксельные координаты. Для этого нужно вызвать метод карты getRenderedObjects(), указав координаты в пикселях и радиус в экранных миллиметрах. Метод вернет отложенный результат, содержащий информацию обо всех найденных объектах в указанном радиусе на видимой области карты (список RenderedObjectInfo).
Пример функции, которая принимает координаты нажатия на экран и передаёт их в метод getRenderedObjects()
:
override fun onTap(point: ScreenPoint) {
map.getRenderedObjects(point, ScreenDistance(5f)).onResult { renderedObjectInfos ->
// Первый объект в списке - самый близкий к координатам
for (renderedObjectInfo in renderedObjectInfos) {
Log.d("APP", "Произвольные данные объекта: ${renderedObjectInfo.item.item.userData}")
}
}
}
Справочник объектов
Для поиска объектов в справочнике нужно создать объект SearchManager, вызвав один из следующих методов:
- SearchManager.createOnlineManager() - создаёт онлайн-справочник.
- SearchManager.createOfflineManager() - создаёт офлайн-справочник, работающий только с предзагруженными данными.
- SearchManager.createSmartManager() - создаёт комбинированный справочник, работающий с онлайн-данными при наличии сети и с предзагруженными данными при отсутствии сети.
val searchManager = SearchManager.createSmartManager(sdkContext)
Если идентификатор (ID) объекта известен, то для получения информации о нём нужно вызвать метод searchById(). Метод вернёт отложенный результат DirectoryObject.
searchManager.searchById(id).onResult { directoryObject ->
Log.d("APP", "Название объекта: ${directoryObject.title}")
}
Если ID объекта не известен, то можно создать поисковый запрос (объект SearchQuery) с помощью SearchQueryBuilder и передать его в метод search(). Вызов вернёт отложенный результат SearchResult, содержащий список найденных объектов (DirectoryObject), разделенный на страницы.
val query = SearchQueryBuilder.fromQueryText("пицца").setPageSize(10).build()
searchManager.search(query).onResult { searchResult ->
// Получаем первый объект с первой страницы
val directoryObject = searchResult.firstPage?.items?.getOrNull(0) ?: return
Log.d("APP", "Название объекта: ${directoryObject.title}")
}
Чтобы получить следующую страницу результатов поиска, нужно вызвать метод страницы fetchNextPage(), который вернёт отложенный результат Page.
firstPage.fetchNextPage().onResult { nextPage
val directoryObject = nextPage?.items?.getOrNull(0) ?: return
}
Также с помощью справочника можно получать подсказки при текстовом поиске объектов (см. Suggest API для демонстрации). Для этого нужно создать объект SuggestQuery с помощью SuggestQueryBuilder и передать его в метод suggest(). Вызов вернёт отложенный результат SuggestResult, содержащий список подсказок (Suggest).
val query = SuggestQueryBuilder.fromQueryText("пицц").setLimit(10).build()
searchManager.suggest(query).onResult { suggestResult ->
// Получаем первую подсказку из списка
val firstSuggest = suggestResult.suggests?.getOrNull(0) ?: return
Log.d("APP", "Заголовок подсказки: ${firstSuggest.title}")
}
Построение маршрута
Для того, чтобы проложить маршрут на карте, нужно создать два объекта: TrafficRouter для поиска оптимального маршрута и источник данных RouteMapObjectSource для отображения маршрута на карте.
Чтобы найти маршрут между двумя точками, нужно вызвать метод findRoute(), передав координаты точек в виде объектов RouteSearchPoint. Дополнительно можно указать параметры маршрута (RouteOptions), а также список промежуточных точек маршрута (список RouteSearchPoint).
val startSearchPoint = RouteSearchPoint(
coordinates = GeoPoint(latitude = 55.759909, longitude = 37.618806)
)
val finishSearchPoint = RouteSearchPoint(
coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983)
)
val trafficRouter = TrafficRouter(sdkContext)
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)
Вызов вернёт отложенный результат со списком объектов TrafficRoute. Чтобы отобразить найденный маршрут на карте, нужно на основе этих объектов создать объекты RouteMapObject и добавить их в источник данных RouteMapObjectSource.
// Создаём источник данных
val routeMapObjectSource = RouteMapObjectSource(sdkContext, RouteVisualizationType.NORMAL)
map.addSource(routeMapObjectSource)
// Ищем маршрут
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)
val trafficRouter = TrafficRouter(sdkContext)
// После получения маршрута добавляем его на карту
routesFuture.onResult { routes: List<TrafficRoute> ->
var isActive = true
var routeIndex = 0
for (route in routes) {
routeMapObjectSource.addObject(
RouteMapObject(route, isActive, routeIndex)
)
isActive = false
routeIndex++
}
}
Вместо пары TrafficRouter и RouteMapObjectSource для построения маршрута можно использовать RouteEditor и RouteEditorSource. В таком случае не нужно обрабатывать список TrafficRoute, достаточно передать координаты маршрута в виде объекта RouteParams в метод setRouteParams() и маршрут отобразится автоматически.
val routeEditor = RouteEditor(sdkContext)
val routeEditorSource = RouteEditorSource(sdkContext, routeEditor)
map.addSource(routeEditorSource)
routeEditor.setRouteParams(
RouteParams(
startPoint = RouteSearchPoint(
coordinates = GeoPoint(latitude = 55.759909, longitude = 37.618806)
),
finishPoint = RouteSearchPoint(
coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983)
)
)
)
Навигатор
Чтобы создать навигатор, можно использовать готовые элементы интерфейса и класс NavigationManager.
Для этого нужно добавить в MapView элементы NavigationView и DefaultNavigationControls.
<ru.dgis.sdk.map.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ru.dgis.sdk.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ru.dgis.sdk.navigation.DefaultNavigationControls
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</ru.dgis.sdk.navigation.NavigationView>
</ru.dgis.sdk.map.MapView>
После этого нужно добавить на карту маркер с текущим местоположением и создать объект NavigationManager.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sdkContext = DGis.initialize(applicationContext, apiKeys)
// Регистрируем источник геопозиции
locationProvider = ManagerLocationSource(applicationContext)
registerPlatformLocationSource(sdkContext, locationProvider)
setContentView(R.layout.activity_navigation)
findViewById<MapView>(R.id.mapView).apply { mapView ->
lifecycle.addObserver(mapView)
mapView.getMapAsync { map ->
// Добавляем маркер с текущим местоположением
map.addSource(
MyLocationMapObjectSource(
sdkContext,
MyLocationDirectionBehaviour.FOLLOW_SATELLITE_HEADING,
createSmoothMyLocationController()
)
)
}
}
// Создаём объект NavigationManager
navigationManager = NavigationManager(sdkContext)
findViewById<NavigationView>(R.id.navigationView).apply {
// Привязываем созданный объект NavigationManager к элементу интерфейса NavigationView
navigationManager = this@NavigationActivity.navigationManager
}
// Запускаем навигатор в режиме свободной навигации
navigationManager.start()
}
Навигатор может работать в трёх режимах: свободная навигация, ведение по маршруту и симуляция ведения.
Настройки навигатора можно изменить через свойства NavigationManager.
Свободная навигация
В этом режиме маршрут следования отсутствует, но навигатор будет информировать о превышениях скорости, дорожных камерах, авариях и ремонтных работах.
Чтобы запустить навигатор в этом режиме, нужно вызвать метод start()
без параметров.
navigationManager.start()
Ведение по маршруту
В этом режиме на карте будет построен маршрут от текущего местоположения до указанной точки назначения, и пользователь будет получать инструкции по мере движения.
Чтобы запустить навигатор в этом режиме, нужно вызвать метод start()
и указать объект RouteBuildOptions - координаты точки назначения и настройки маршрута.
val routeBuildOptions = RouteBuildOptions(
finishPoint = RouteSearchPoint(
coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983)
),
routeSearchOptions = CarRouteSearchOptions(
avoidTollRoads = true,
avoidUnpavedRoads = false,
avoidFerry = false,
routeSearchType = RouteSearchType.JAM
)
)
navigationManager.start(routeBuildOptions)
Дополнительно при вызове метода start()
можно указать объект TrafficRoute - готовый маршрут для навигации (см. раздел Построение маршрута). В таком случае навигатор не будет пытаться построить маршрут от текущего местоположения, а начнёт ведение по указанному маршруту.
navigationManager.start(routeBuildOptions, trafficRoute)
Симуляция ведения по маршруту
В этом режиме навигатор не будет отслеживать реальное местоположение устройства, а запустит симулированное движение по указанному маршруту. Режим удобно использовать для отладки.
Чтобы запустить навигатор в режиме симуляции, нужно вызвать метод startSimulation()
, указав готовый маршрут (TrafficRoute) и его настройки (RouteBuildOptions).
Скорость движения можно изменить с помощью свойства SimulationSettings.speed (метры в секунду).
navigationManager.simulationSettings.speed = 30 / 3.6
navigationManager.startSimulation(routeBuildOptions, trafficRoute)
Остановить симуляцию можно с помощью метода stop()
.
navigationManager.stop()
Отображение пробок на карте
Чтобы включить показ дорожного трафика, нужно добавить на карту источник данных TrafficSource.
val trafficSource = TrafficSource(sdkContext)
map.addSource(trafficSource)
Собственный источник геопозиции
В рамках SDK можно использовать произвольный источник геопозиции. Для этого нужно реализовать интерфейс LocationSource.
public class CustomLocationSource: LocationSource {
override fun activate(listener: LocationChangeListener?) {
// Включение источника геопозиции
}
override fun deactivate() {
// Выключение источника геопозиции
}
override fun setDesiredAccuracy(accuracy: DesiredAccuracy?) {
// Изменение требуемого уровня точности
}
}
Чтобы зарегистрировать созданный источник в SDK, нужно вызвать функцию registerPlatformLocationSource().
val customSource = CustomLocationSource()
registerPlatformLocationSource(sdkContext, customSource)
Основная точка входа в интерфейс - функция activate()
. Когда SDK потребуется геопозиция, в эту функцию будет передан объект LocationChangeListener. После этого, чтобы сообщить текущую геопозицию, нужно передать в него массив объектов Location (от более старой позиции к более новой), используя метод onLocationChanged().
val location = Location(...)
val newLocations = arrayOf(location)
listener.onLocationChanged(newLocations)
Чтобы сообщить изменение доступности источника, можно вызвать метод onAvailabilityChanged().
Дополнительно можно менять логику определения геопозиции в зависимости от требуемой точности. Требуемая точность передаётся в функцию setDesiredAccuracy()
в виде объекта DesiredAccuracy.
Когда источник геопозиции больше не требуется, будет вызвана функция deactivate()
.