diff --git a/MapboxSearch/gradle/versions.gradle b/MapboxSearch/gradle/versions.gradle index 91579aaa6..7f6ac1a55 100644 --- a/MapboxSearch/gradle/versions.gradle +++ b/MapboxSearch/gradle/versions.gradle @@ -46,7 +46,7 @@ ext { common_sdk_version = '24.7.0-beta.1' mapbox_base_version = '0.8.0' - search_native_version = '2.5.0-beta.1' + search_native_version = '2.4.0-feat_offline_user_record_searching-SNAPSHOT' detekt_version = '1.19.0' diff --git a/MapboxSearch/offline/build.gradle b/MapboxSearch/offline/build.gradle index 36a5c2de4..5d730ee43 100644 --- a/MapboxSearch/offline/build.gradle +++ b/MapboxSearch/offline/build.gradle @@ -76,6 +76,7 @@ android { dependencies { implementation project(path: ':base') api project(path: ':sdk-common') + api project(path: ':sdk') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" diff --git a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngine.kt b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngine.kt index fb3204ade..b1a15677b 100644 --- a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngine.kt +++ b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngine.kt @@ -7,6 +7,8 @@ import com.mapbox.common.TileStoreOptions import com.mapbox.common.TilesetDescriptor import com.mapbox.geojson.Feature import com.mapbox.geojson.Point +import com.mapbox.search.IndexableDataProviderManager +import com.mapbox.search.MapboxSearchSdk import com.mapbox.search.base.BaseSearchSdkInitializerImpl import com.mapbox.search.base.SearchRequestContextProvider import com.mapbox.search.base.core.CoreApiType @@ -15,8 +17,6 @@ import com.mapbox.search.base.core.CoreSearchEngine import com.mapbox.search.base.core.getUserActivityReporter import com.mapbox.search.base.location.LocationEngineAdapter import com.mapbox.search.base.location.WrapperLocationProvider -import com.mapbox.search.base.record.IndexableRecordResolver -import com.mapbox.search.base.result.SearchResultFactory import com.mapbox.search.base.utils.AndroidKeyboardLocaleProvider import com.mapbox.search.base.utils.UserAgentProvider import com.mapbox.search.base.utils.orientation.AndroidScreenOrientationProvider @@ -31,7 +31,7 @@ import java.util.concurrent.Executor * The API of this class is temporary and subject to change. * Tiles loading functionality is available to selected customers only. Contact our team, to get early preview. */ -public interface OfflineSearchEngine { +public interface OfflineSearchEngine : IndexableDataProviderManager { /** * Interface definition for a callback to be invoked when the [OfflineSearchEngine] is ready for use. @@ -383,7 +383,7 @@ public interface OfflineSearchEngine { AndroidScreenOrientationProvider(app) ) - val searchResultFactory = SearchResultFactory(IndexableRecordResolver.EMPTY) + val searchResultFactory = MapboxSearchSdk.searchResultFactory return OfflineSearchEngineImpl( settings = settings, @@ -391,6 +391,7 @@ public interface OfflineSearchEngine { activityReporter = getUserActivityReporter(), requestContextProvider = requestContextProvider, searchResultFactory = searchResultFactory, + indexableDataProvidersRegistry = MapboxSearchSdk.indexableDataProvidersRegistry ) } diff --git a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngineImpl.kt b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngineImpl.kt index ac7947374..5a1600786 100644 --- a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngineImpl.kt +++ b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/OfflineSearchEngineImpl.kt @@ -5,6 +5,7 @@ import com.mapbox.geojson.BoundingBox import com.mapbox.geojson.Feature import com.mapbox.geojson.LineString import com.mapbox.geojson.Point +import com.mapbox.search.IndexableDataProvidersRegistry import com.mapbox.search.base.BaseSearchSdkInitializerImpl import com.mapbox.search.base.SearchRequestContextProvider import com.mapbox.search.base.core.CoreApiType @@ -16,11 +17,14 @@ import com.mapbox.search.base.logger.logd import com.mapbox.search.base.result.SearchResultFactory import com.mapbox.search.base.task.AsyncOperationTaskImpl import com.mapbox.search.common.AsyncOperationTask +import com.mapbox.search.common.CompletionCallback import com.mapbox.search.internal.bindgen.OfflineIndexChangeEvent import com.mapbox.search.internal.bindgen.OfflineIndexError import com.mapbox.search.internal.bindgen.UserActivityReporterInterface import com.mapbox.search.offline.OfflineSearchEngine.EngineReadyCallback import com.mapbox.search.offline.OfflineSearchEngine.OnIndexChangeListener +import com.mapbox.search.record.IndexableDataProvider +import com.mapbox.search.record.IndexableRecord import com.mapbox.turf.TurfMeasurement import com.mapbox.turf.TurfMisc import java.util.concurrent.Executor @@ -34,6 +38,7 @@ internal class OfflineSearchEngineImpl( private val requestContextProvider: SearchRequestContextProvider, private val searchResultFactory: SearchResultFactory, private val engineExecutorService: ExecutorService = DEFAULT_EXECUTOR, + private val indexableDataProvidersRegistry: IndexableDataProvidersRegistry, ) : BaseSearchEngine(), OfflineSearchEngine { private val initializationLock = Any() @@ -256,6 +261,32 @@ internal class OfflineSearchEngineImpl( } } + override fun registerDataProvider( + dataProvider: IndexableDataProvider, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + return indexableDataProvidersRegistry.register( + dataProvider = dataProvider, + searchEngine = coreEngine, + executor = executor, + callback = callback, + ) + } + + override fun unregisterDataProvider( + dataProvider: IndexableDataProvider, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + return indexableDataProvidersRegistry.unregister( + dataProvider = dataProvider, + searchEngine = coreEngine, + executor = executor, + callback = callback, + ) + } + private fun bufferBoundingBox(coords: DoubleArray, percentage: Double = 5.0): DoubleArray { var minLon = coords[0] var minLat = coords[1] diff --git a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/offlineSearchResultType.kt b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/offlineSearchResultType.kt index 0a91eec77..d47611a5d 100644 --- a/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/offlineSearchResultType.kt +++ b/MapboxSearch/offline/src/main/java/com/mapbox/search/offline/offlineSearchResultType.kt @@ -23,6 +23,8 @@ public enum class OfflineSearchResultType { * Individual residential or business addresses. */ ADDRESS, + + USER_RECORD, } @JvmSynthetic @@ -31,6 +33,7 @@ internal fun BaseRawResultType.tryMapToOfflineSdkType(): OfflineSearchResultType BaseRawResultType.PLACE -> OfflineSearchResultType.PLACE BaseRawResultType.STREET -> OfflineSearchResultType.STREET BaseRawResultType.ADDRESS -> OfflineSearchResultType.ADDRESS + BaseRawResultType.USER_RECORD -> OfflineSearchResultType.USER_RECORD else -> null } } diff --git a/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/MainActivity.kt b/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/MainActivity.kt index 09de78b83..5348b802b 100644 --- a/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/MainActivity.kt +++ b/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/MainActivity.kt @@ -7,6 +7,8 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.net.Uri import android.os.Bundle +import android.os.Parcel +import android.os.Parcelable import android.util.Log import android.view.Menu import android.view.MenuItem @@ -32,7 +34,9 @@ import com.mapbox.maps.RenderedQueryOptions import com.mapbox.maps.Style import com.mapbox.maps.plugin.annotation.annotations import com.mapbox.maps.plugin.annotation.generated.CircleAnnotationOptions +import com.mapbox.maps.plugin.annotation.generated.PolylineAnnotationOptions import com.mapbox.maps.plugin.annotation.generated.createCircleAnnotationManager +import com.mapbox.maps.plugin.annotation.generated.createPolylineAnnotationManager import com.mapbox.maps.plugin.gestures.addOnMapClickListener import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener import com.mapbox.maps.plugin.locationcomponent.location @@ -40,16 +44,24 @@ import com.mapbox.search.ApiType import com.mapbox.search.ResponseInfo import com.mapbox.search.SearchEngine import com.mapbox.search.SearchEngineSettings +import com.mapbox.search.SearchResultMetadata import com.mapbox.search.base.location.defaultLocationProvider import com.mapbox.search.base.utils.extension.toPoint +import com.mapbox.search.common.AsyncOperationTask +import com.mapbox.search.common.CompletionCallback import com.mapbox.search.common.DistanceCalculator +import com.mapbox.search.common.RoutablePoint import com.mapbox.search.offline.OfflineResponseInfo import com.mapbox.search.offline.OfflineSearchEngine import com.mapbox.search.offline.OfflineSearchEngineSettings import com.mapbox.search.offline.OfflineSearchResult import com.mapbox.search.record.HistoryRecord +import com.mapbox.search.record.IndexableDataProvider +import com.mapbox.search.record.IndexableDataProviderEngine +import com.mapbox.search.record.IndexableRecord import com.mapbox.search.result.SearchAddress import com.mapbox.search.result.SearchResult +import com.mapbox.search.result.SearchResultType import com.mapbox.search.result.SearchSuggestion import com.mapbox.search.sample.api.AddressAutofillKotlinExampleActivity import com.mapbox.search.sample.api.CategorySearchJavaExampleActivity @@ -86,6 +98,8 @@ import com.mapbox.search.ui.view.place.SearchPlace import com.mapbox.search.ui.view.place.SearchPlaceBottomSheetView import com.mapbox.turf.TurfConstants import com.mapbox.turf.TurfTransformation +import java.util.UUID +import java.util.concurrent.Executor class MainActivity : AppCompatActivity() { @@ -108,6 +122,27 @@ class MainActivity : AppCompatActivity() { private val tileRegionId = "Washington DC" private var tilesLoadingTask: Cancelable? = null + private val customDataProvider = InMemoryDataProvider( + records = listOf( + createRecord("Custom User Record #1", Point.fromLngLat( + -77.01345075849513, + 38.889966341103104), + listOf( + Point.fromLngLat(-77.04730852417978, 38.90441882114379), + Point.fromLngLat(-77.02453747528648, 38.91910826019327), + Point.fromLngLat(-76.99483554515201, 38.91046894203774), + Point.fromLngLat(-77.04730852417978, 38.90441882114379))), + createRecord("Custom User Record #2", Point.fromLngLat( + -77.11345075849513, + 38.989966341103106 + )), + createRecord("Custom User Record #3", Point.fromLngLat( + -76.01345075849513, + 38.7899663411031 + )), + ) + ) + private val onBackPressedCallback = object : OnBackPressedCallback(false) { override fun handleOnBackPressed() { when { @@ -209,6 +244,32 @@ class MainActivity : AppCompatActivity() { ) ) + searchEngine.registerDataProvider( + dataProvider = customDataProvider, + callback = object : CompletionCallback { + override fun onComplete(result: Unit) { + Log.i("SearchApiExample", "CustomDataProvider is registered") + } + + override fun onError(e: Exception) { + Log.e("SearchApiExample", "Error during registering", e) + } + } + ) + + offlineSearchEngine.registerDataProvider( + dataProvider = customDataProvider, + callback = object : CompletionCallback { + override fun onComplete(result: Unit) { + Log.i("SearchApiExample", "CustomDataProvider is registered") + } + + override fun onError(e: Exception) { + Log.e("SearchApiExample", "Error during registering", e) + } + } + ) + val descriptors = listOf(OfflineSearchEngine.createTilesetDescriptor()) val dcLocation = Point.fromLngLat(-77.0339911055176, 38.899920004207516) val tileGeometry = TurfTransformation.circle(dcLocation, 20.0, 32, TurfConstants.UNIT_KILOMETERS) @@ -267,7 +328,15 @@ class MainActivity : AppCompatActivity() { override fun onSearchResultSelected(searchResult: SearchResult, responseInfo: ResponseInfo) { closeSearchView() searchPlaceView.open(SearchPlace.createFromSearchResult(searchResult, responseInfo)) - mapMarkersManager.showMarker(searchResult.coordinate) + + searchResult.indexableRecord?.let { + val customUserRecord = it as CustomUserRecord + if (customUserRecord.trail?.isEmpty() == false) { + mapMarkersManager.showTrail(customUserRecord.trail) + } else { + mapMarkersManager.showMarker(searchResult.coordinate) + } + } ?: mapMarkersManager.showMarker(searchResult.coordinate) } override fun onOfflineSearchResultSelected(searchResult: OfflineSearchResult, responseInfo: OfflineResponseInfo) { @@ -551,14 +620,21 @@ class MainActivity : AppCompatActivity() { private val mapboxMap = mapView.mapboxMap private val circleAnnotationManager = mapView.annotations.createCircleAnnotationManager(null) + private val polylineAnnotationManager = mapView.annotations.createPolylineAnnotationManager() private val markers = mutableMapOf() + var trail: List? = null + private set + var onMarkersChangeListener: (() -> Unit)? = null val hasMarkers: Boolean get() = markers.isNotEmpty() fun clearMarkers() { + polylineAnnotationManager.deleteAll() + trail = null + markers.clear() circleAnnotationManager.deleteAll() } @@ -601,6 +677,44 @@ class MainActivity : AppCompatActivity() { } onMarkersChangeListener?.invoke() } + + fun showTrail(trail: List) { + if (trail.isEmpty()) { + return + } + + clearMarkers() + + this.trail = trail + + val polylineAnnotationOptions: PolylineAnnotationOptions = PolylineAnnotationOptions() + .withPoints(trail) + .withLineColor("#007bff") + .withLineBorderColor("#0056b3") + .withLineWidth(5.0) + + polylineAnnotationManager.create(polylineAnnotationOptions) + + val cameraOptions = mapboxMap.cameraForCoordinates( + trail, MARKERS_INSETS, bearing = null, pitch = null + ) + mapboxMap.setCamera(cameraOptions) + } + } + + private fun createRecord(name: String, coordinate: Point, trail: List? = null): IndexableRecord { + return CustomUserRecord( + id = UUID.randomUUID().toString(), + name = name, + descriptionText = "A randomly generated place", + categories = emptyList(), + coordinate = coordinate, + address = null, + makiIcon = null, + metadata = null, + routablePoints = null, + trail = trail + ) } private companion object { @@ -618,4 +732,148 @@ class MainActivity : AppCompatActivity() { const val PERMISSIONS_REQUEST_LOCATION = 0 } + + private class InMemoryDataProvider(records: List) : + IndexableDataProvider { + + private val dataProviderEngines: MutableList = mutableListOf() + private val records: MutableMap = mutableMapOf() + + override val dataProviderName: String = "SAMPLE_APP_CUSTOM_DATA_PROVIDER" + override val priority: Int = 200 + + init { + this.records.putAll(records.map { it.id to it }) + } + + override fun registerIndexableDataProviderEngine( + dataProviderEngine: IndexableDataProviderEngine, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + dataProviderEngine.upsertAll(records.values.toList()) + dataProviderEngines.add(dataProviderEngine) + executor.execute { + callback.onComplete(Unit) + } + return AsyncOperationTask.COMPLETED + } + + override fun unregisterIndexableDataProviderEngine( + dataProviderEngine: IndexableDataProviderEngine, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + val isRemoved = dataProviderEngines.remove(dataProviderEngine) + if (isRemoved) { + dataProviderEngine.clear() + } + executor.execute { + callback.onComplete(isRemoved) + } + return AsyncOperationTask.COMPLETED + } + + override operator fun get( + id: String, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + executor.execute { + callback.onComplete(records[id]) + } + return AsyncOperationTask.COMPLETED + } + + override fun getAll(executor: Executor, callback: CompletionCallback>): AsyncOperationTask { + executor.execute { + callback.onComplete(ArrayList(records.values)) + } + return AsyncOperationTask.COMPLETED + } + + override fun contains( + id: String, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + executor.execute { + callback.onComplete(records[id] != null) + } + return AsyncOperationTask.COMPLETED + } + + override fun upsert(record: R, executor: Executor, callback: CompletionCallback): AsyncOperationTask { + dataProviderEngines.forEach { + it.upsert(record) + } + records[record.id] = record + executor.execute { + callback.onComplete(Unit) + } + return AsyncOperationTask.COMPLETED + } + + override fun upsertAll( + records: List, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask { + dataProviderEngines.forEach { + it.upsertAll(records) + } + for (record in records) { + this.records[record.id] = record + } + executor.execute { + callback.onComplete(Unit) + } + return AsyncOperationTask.COMPLETED + } + + override fun remove(id: String, executor: Executor, callback: CompletionCallback): AsyncOperationTask { + dataProviderEngines.forEach { + it.remove(id) + } + val isRemoved = records.remove(id) != null + executor.execute { + callback.onComplete(isRemoved) + } + return AsyncOperationTask.COMPLETED + } + + override fun clear(executor: Executor, callback: CompletionCallback): AsyncOperationTask { + dataProviderEngines.forEach { + it.clear() + } + records.clear() + executor.execute { + callback.onComplete(Unit) + } + return AsyncOperationTask.COMPLETED + } + } + + class CustomUserRecord( + override val id: String, + override val name: String, + override val descriptionText: String, + override val categories: List, + override val coordinate: Point, + override val address: SearchAddress?, + override val makiIcon: String?, + override val metadata: SearchResultMetadata?, + override val routablePoints: List?, + override val indexTokens: List = emptyList(), + override val type: SearchResultType = SearchResultType.POI, + val trail: List? = null + ) : IndexableRecord, Parcelable { + override fun describeContents(): Int { + TODO("Not yet implemented") + } + + override fun writeToParcel(p0: Parcel, p1: Int) { + TODO("Not yet implemented") + } + } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProviderManager.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProviderManager.kt new file mode 100644 index 000000000..244c2c147 --- /dev/null +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProviderManager.kt @@ -0,0 +1,70 @@ +package com.mapbox.search + +import com.mapbox.search.common.AsyncOperationTask +import com.mapbox.search.common.CompletionCallback +import com.mapbox.search.common.concurrent.SearchSdkMainThreadWorker +import com.mapbox.search.record.IndexableDataProvider +import com.mapbox.search.record.IndexableRecord +import java.util.concurrent.Executor + +public interface IndexableDataProviderManager { + /** + * Registers [dataProvider] in this [SearchEngine]. + * + * @param dataProvider [IndexableDataProvider] to register. + * @param executor Executor used for events dispatching. By default events are dispatched on the main thread. + * @param callback Callback to handle result. + * @return an object representing pending completion of the task. + */ + public fun registerDataProvider( + dataProvider: IndexableDataProvider, + executor: Executor, + callback: CompletionCallback + ): AsyncOperationTask + + /** + * Registers [dataProvider] in this [SearchEngine]. + * + * @param dataProvider [IndexableDataProvider] to register. + * @param callback Callback to handle result. Events are dispatched on the main thread. + * @return an object representing pending completion of the task. + */ + public fun registerDataProvider( + dataProvider: IndexableDataProvider, + callback: CompletionCallback + ): AsyncOperationTask = registerDataProvider( + dataProvider = dataProvider, + executor = SearchSdkMainThreadWorker.mainExecutor, + callback = callback, + ) + + /** + * Unregisters previously registered [IndexableDataProvider]. + * + * @param dataProvider [IndexableDataProvider] to unregister. + * @param executor Executor used for events dispatching. By default events are dispatched on the main thread. + * @param callback Callback to handle result. + * @return an object representing pending completion of the task. + */ + public fun unregisterDataProvider( + dataProvider: IndexableDataProvider, + executor: Executor, + callback: CompletionCallback, + ): AsyncOperationTask + + /** + * Unregisters previously registered [IndexableDataProvider]. + * + * @param dataProvider [IndexableDataProvider] to unregister. + * @param callback Callback to handle result. Events are dispatched on the main thread. + * @return an object representing pending completion of the task. + */ + public fun unregisterDataProvider( + dataProvider: IndexableDataProvider, + callback: CompletionCallback, + ): AsyncOperationTask = unregisterDataProvider( + dataProvider = dataProvider, + executor = SearchSdkMainThreadWorker.mainExecutor, + callback = callback, + ) +} diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProvidersRegistry.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProvidersRegistry.kt index 4dc28aecd..2c8d18263 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProvidersRegistry.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/IndexableDataProvidersRegistry.kt @@ -7,22 +7,21 @@ import com.mapbox.search.record.IndexableDataProvider import com.mapbox.search.record.IndexableRecord import java.util.concurrent.Executor -internal interface IndexableDataProvidersRegistry { - - fun preregister( +public interface IndexableDataProvidersRegistry { + public fun preregister( dataProvider: IndexableDataProvider, executor: Executor, callback: CompletionCallback ): AsyncOperationTask - fun register( + public fun register( dataProvider: IndexableDataProvider, searchEngine: CoreSearchEngineInterface, executor: Executor, callback: CompletionCallback ): AsyncOperationTask - fun unregister( + public fun unregister( dataProvider: IndexableDataProvider, searchEngine: CoreSearchEngineInterface, executor: Executor, diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt index 8cb123b17..ec722c91f 100755 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt @@ -5,6 +5,7 @@ import com.mapbox.common.EventsServerOptions import com.mapbox.common.EventsService import com.mapbox.common.location.LocationProvider import com.mapbox.search.analytics.AnalyticsEventJsonParser +import com.mapbox.search.analytics.AnalyticsService import com.mapbox.search.analytics.AnalyticsServiceImpl import com.mapbox.search.analytics.SearchFeedbackEventsFactory import com.mapbox.search.base.SearchRequestContextProvider @@ -33,19 +34,19 @@ import com.mapbox.search.utils.file.InternalFileSystem import com.mapbox.search.utils.loader.DataLoader import com.mapbox.search.utils.loader.InternalDataLoader -internal object MapboxSearchSdk { +public object MapboxSearchSdk { - lateinit var searchRequestContextProvider: SearchRequestContextProvider - lateinit var searchResultFactory: SearchResultFactory + public lateinit var searchRequestContextProvider: SearchRequestContextProvider + public lateinit var searchResultFactory: SearchResultFactory private lateinit var timeProvider: TimeProvider private lateinit var formattedTimeProvider: FormattedTimeProvider private lateinit var uuidProvider: UUIDProvider - lateinit var indexableDataProvidersRegistry: IndexableDataProvidersRegistryImpl + public lateinit var indexableDataProvidersRegistry: IndexableDataProvidersRegistry private lateinit var application: Application - fun initialize( + public fun initialize( application: Application, timeProvider: TimeProvider = LocalTimeProvider(), formattedTimeProvider: FormattedTimeProvider = FormattedTimeProviderImpl(timeProvider), @@ -82,7 +83,7 @@ internal object MapboxSearchSdk { favoritesDataProvider = favoritesDataProvider, ) - searchResultFactory = SearchResultFactory(indexableDataProvidersRegistry) + searchResultFactory = SearchResultFactory(indexableDataProvidersRegistry as IndexableDataProvidersRegistryImpl) preregisterDefaultDataProviders( historyDataProvider, favoritesDataProvider @@ -105,10 +106,10 @@ internal object MapboxSearchSdk { ) } - fun createAnalyticsService( + public fun createAnalyticsService( settings: SearchEngineSettings, coreSearchEngine: CoreSearchEngineInterface, - ) = createAnalyticsService( + ): AnalyticsService = createAnalyticsService( coreSearchEngine = coreSearchEngine, locationProvider = settings.locationProvider, viewportProvider = settings.viewportProvider diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/SearchEngine.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/SearchEngine.kt index d4ce8419a..1ce0065a6 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/SearchEngine.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/SearchEngine.kt @@ -6,7 +6,6 @@ import com.mapbox.search.common.AsyncOperationTask import com.mapbox.search.common.CompletionCallback import com.mapbox.search.common.concurrent.SearchSdkMainThreadWorker import com.mapbox.search.record.IndexableDataProvider -import com.mapbox.search.record.IndexableRecord import com.mapbox.search.result.SearchResult import com.mapbox.search.result.SearchSuggestion import java.util.concurrent.Executor @@ -57,7 +56,7 @@ import java.util.concurrent.Executor * * @see SearchEngine.createSearchEngine */ -public interface SearchEngine { +public interface SearchEngine : IndexableDataProviderManager { /** * The type of the API used by the Search Engine. @@ -306,66 +305,6 @@ public interface SearchEngine { callback = callback, ) - /** - * Registers [dataProvider] in this [SearchEngine]. - * - * @param dataProvider [IndexableDataProvider] to register. - * @param executor Executor used for events dispatching. By default events are dispatched on the main thread. - * @param callback Callback to handle result. - * @return an object representing pending completion of the task. - */ - public fun registerDataProvider( - dataProvider: IndexableDataProvider, - executor: Executor, - callback: CompletionCallback - ): AsyncOperationTask - - /** - * Registers [dataProvider] in this [SearchEngine]. - * - * @param dataProvider [IndexableDataProvider] to register. - * @param callback Callback to handle result. Events are dispatched on the main thread. - * @return an object representing pending completion of the task. - */ - public fun registerDataProvider( - dataProvider: IndexableDataProvider, - callback: CompletionCallback - ): AsyncOperationTask = registerDataProvider( - dataProvider = dataProvider, - executor = SearchSdkMainThreadWorker.mainExecutor, - callback = callback, - ) - - /** - * Unregisters previously registered [IndexableDataProvider]. - * - * @param dataProvider [IndexableDataProvider] to unregister. - * @param executor Executor used for events dispatching. By default events are dispatched on the main thread. - * @param callback Callback to handle result. - * @return an object representing pending completion of the task. - */ - public fun unregisterDataProvider( - dataProvider: IndexableDataProvider, - executor: Executor, - callback: CompletionCallback, - ): AsyncOperationTask - - /** - * Unregisters previously registered [IndexableDataProvider]. - * - * @param dataProvider [IndexableDataProvider] to unregister. - * @param callback Callback to handle result. Events are dispatched on the main thread. - * @return an object representing pending completion of the task. - */ - public fun unregisterDataProvider( - dataProvider: IndexableDataProvider, - callback: CompletionCallback, - ): AsyncOperationTask = unregisterDataProvider( - dataProvider = dataProvider, - executor = SearchSdkMainThreadWorker.mainExecutor, - callback = callback, - ) - /** * Companion object. */ diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsEventJsonParser.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsEventJsonParser.kt index d6906ebdf..6083fddb0 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsEventJsonParser.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsEventJsonParser.kt @@ -4,7 +4,7 @@ import com.google.gson.Gson import com.mapbox.search.analytics.events.SearchFeedbackEvent import org.json.JSONObject -internal class AnalyticsEventJsonParser { +public class AnalyticsEventJsonParser { private val gson: Gson = Gson() @@ -13,7 +13,7 @@ internal class AnalyticsEventJsonParser { * @throws com.google.gson.JsonSyntaxException if [jsonEvent] is not a valid representation for an object of subtype of BaseSearchEvent * @throws IllegalArgumentException if [jsonEvent] has unknown "event" type */ - fun parse(jsonEvent: String): SearchFeedbackEvent { + public fun parse(jsonEvent: String): SearchFeedbackEvent { val jsonObject = JSONObject(jsonEvent) return when (val event = jsonObject.getString("event")) { SearchFeedbackEvent.EVENT_NAME -> gson.fromJson(jsonEvent, SearchFeedbackEvent::class.java) @@ -21,14 +21,14 @@ internal class AnalyticsEventJsonParser { } } - fun serialize(event: SearchFeedbackEvent): String { + public fun serialize(event: SearchFeedbackEvent): String { require(event.event == SearchFeedbackEvent.EVENT_NAME) { "$event is not valid" } return gson.toJson(event) } - fun serializeAny(obj: Any): String { + public fun serializeAny(obj: Any): String { return gson.toJson(obj) } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt index bab5f9326..e04690844 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt @@ -19,14 +19,14 @@ import com.mapbox.search.result.SearchSuggestion import com.mapbox.search.result.isIndexableRecordSuggestion import java.util.concurrent.Executor -internal class AnalyticsServiceImpl( +public class AnalyticsServiceImpl( private val eventsService: EventsServiceInterface, private val eventsJsonParser: AnalyticsEventJsonParser, private val feedbackEventsFactory: SearchFeedbackEventsFactory, private val locationProvider: LocationProvider? ) : AnalyticsService { - fun createRawFeedbackEvent( + public fun createRawFeedbackEvent( searchResult: SearchResult, responseInfo: ResponseInfo, executor: Executor, @@ -55,7 +55,7 @@ internal class AnalyticsServiceImpl( ) } - fun createRawFeedbackEvent( + public fun createRawFeedbackEvent( searchSuggestion: SearchSuggestion, responseInfo: ResponseInfo, executor: Executor, diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/SearchFeedbackEventsFactory.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/SearchFeedbackEventsFactory.kt index 5bbc4b51a..cb7c70a9a 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/SearchFeedbackEventsFactory.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/SearchFeedbackEventsFactory.kt @@ -27,7 +27,7 @@ import com.mapbox.search.utils.bitmap.BitmapEncodeOptions import com.mapbox.search.utils.bitmap.encodeBase64 import java.util.TreeMap -internal class SearchFeedbackEventsFactory( +public class SearchFeedbackEventsFactory( private val providedUserAgent: String, private val viewportProvider: ViewportProvider?, private val uuidProvider: UUIDProvider, @@ -38,7 +38,7 @@ internal class SearchFeedbackEventsFactory( ) { @SuppressLint("WrongConstant") - fun createSearchFeedbackEvent( + public fun createSearchFeedbackEvent( event: MissingResultFeedbackEvent, currentLocation: Point?, callback: CompletionCallback @@ -61,7 +61,7 @@ internal class SearchFeedbackEventsFactory( ) } - fun createSearchFeedbackEvent( + public fun createSearchFeedbackEvent( record: IndexableRecord, event: FeedbackEvent, currentLocation: Point?, @@ -92,7 +92,7 @@ internal class SearchFeedbackEventsFactory( } } - fun createSearchFeedbackEvent( + public fun createSearchFeedbackEvent( baseRawSearchResult: BaseRawSearchResult?, requestOptions: RequestOptions, searchResponse: BaseSearchResponse?, diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/AppMetadata.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/AppMetadata.kt index ee0821803..fa49396bd 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/AppMetadata.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/AppMetadata.kt @@ -5,7 +5,7 @@ import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize @Parcelize -internal data class AppMetadata( +public data class AppMetadata( @SerializedName("name") var name: String? = null, @SerializedName("version") var version: String? = null, @SerializedName("userId") var userId: String? = null, diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/SearchFeedbackEvent.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/SearchFeedbackEvent.kt index b9278266a..ec09b3017 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/SearchFeedbackEvent.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/events/SearchFeedbackEvent.kt @@ -3,7 +3,7 @@ package com.mapbox.search.analytics.events import com.google.gson.annotations.SerializedName // https://github.com/mapbox/event-schema/blob/master/lib/base-schemas/search.feedback.js -internal data class SearchFeedbackEvent( +public data class SearchFeedbackEvent( @SerializedName("event") var event: String? = null, @@ -121,7 +121,7 @@ internal data class SearchFeedbackEvent( resultIndex != null && selectedItemName != null && event == EVENT_NAME && appMetadata?.isValid != false && queryString != null - companion object { - const val EVENT_NAME = "search.feedback" + public companion object { + public const val EVENT_NAME: String = "search.feedback" } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/utils/loader/DataLoader.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/utils/loader/DataLoader.kt index 23ea0af32..ed34675db 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/utils/loader/DataLoader.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/utils/loader/DataLoader.kt @@ -3,9 +3,9 @@ package com.mapbox.search.utils.loader import androidx.annotation.WorkerThread @WorkerThread -internal interface DataLoader { +public interface DataLoader { - fun load(relativeDir: String, fileName: String): T + public fun load(relativeDir: String, fileName: String): T - fun save(relativeDir: String, fileName: String, data: T) + public fun save(relativeDir: String, fileName: String, data: T) } diff --git a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/utils/offline/OfflineSearchResultType.kt b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/utils/offline/OfflineSearchResultType.kt index 48f6cf540..fe46554de 100644 --- a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/utils/offline/OfflineSearchResultType.kt +++ b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/utils/offline/OfflineSearchResultType.kt @@ -9,5 +9,6 @@ internal fun OfflineSearchResultType.mapToSdkSearchResultType(): SearchResultTyp OfflineSearchResultType.PLACE -> SearchResultType.PLACE OfflineSearchResultType.STREET -> SearchResultType.STREET OfflineSearchResultType.ADDRESS -> SearchResultType.ADDRESS + OfflineSearchResultType.USER_RECORD -> SearchResultType.PLACE } }