diff --git a/google-map/.gitignore b/google-map/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/google-map/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/google-map/build.gradle b/google-map/build.gradle
new file mode 100644
index 0000000..7673daa
--- /dev/null
+++ b/google-map/build.gradle
@@ -0,0 +1,18 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ compileSdkVersion versions.compileSdk
+
+ defaultConfig {
+ minSdkVersion 17
+ }
+}
+
+dependencies {
+ api project(":base-map")
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+
+ implementation "com.google.android.gms:play-services-maps:$versions.google_maps"
+}
diff --git a/google-map/src/main/AndroidManifest.xml b/google-map/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..38758e2
--- /dev/null
+++ b/google-map/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/google-map/src/main/java/ru/touchin/googlemap/GoogleMapManager.kt b/google-map/src/main/java/ru/touchin/googlemap/GoogleMapManager.kt
new file mode 100644
index 0000000..1745afa
--- /dev/null
+++ b/google-map/src/main/java/ru/touchin/googlemap/GoogleMapManager.kt
@@ -0,0 +1,110 @@
+package ru.touchin.googlemap
+
+import android.os.Bundle
+import androidx.annotation.RequiresPermission
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.MapView
+import com.google.android.gms.maps.model.CameraPosition
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.LatLngBounds
+import ru.touchin.basemap.AbstractMapManager
+
+class GoogleMapManager(mapView: MapView) : AbstractMapManager(mapView) {
+
+ override fun initialize(mapListener: AbstractMapListener?) {
+ super.initialize(mapListener)
+ mapView.getMapAsync(::initMap)
+ }
+
+ override fun initMap(map: GoogleMap) {
+ super.initMap(map)
+ with(map) {
+ setOnMapLoadedCallback { mapListener?.onMapLoaded() }
+ setOnCameraMoveStartedListener { mapListener?.onCameraMoved(true) }
+ setOnCameraMoveListener { mapListener?.onCameraMoved(true) }
+ setOnMapClickListener { location -> mapListener?.onMapTap(location) }
+ setOnMapLongClickListener { location -> mapListener?.onMapLongTap(location) }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle) {
+ super.onCreate(savedInstanceState)
+ mapView.onCreate(savedInstanceState)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mapView.onDestroy()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mapView.onStop()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ mapView.onPause()
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ mapView.onSaveInstanceState(outState)
+ }
+
+ override fun getCameraTarget(): LatLng = map.cameraPosition.target
+
+ override fun getCameraZoom(): Float = map.cameraPosition.zoom
+
+ override fun moveCamera(target: LatLng, zoom: Float) {
+ map.moveCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.Builder().target(target).zoom(zoom).build()))
+ }
+
+ override fun smoothMoveCamera(target: LatLng, zoom: Float) {
+ map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.Builder().target(target).zoom(zoom).build()))
+ }
+
+ override fun smoothMoveCamera(targets: List, padding: Int) {
+ val boundingBox = getBoundingBox(targets)
+ map.animateCamera(CameraUpdateFactory.newLatLngBounds(boundingBox, padding))
+ }
+
+ override fun smoothMoveCamera(targets: List, width: Int, height: Int, padding: Int) {
+ val boundingBox = getBoundingBox(targets)
+ map.animateCamera(CameraUpdateFactory.newLatLngBounds(boundingBox, width, height, padding))
+ }
+
+ override fun setMapAllGesturesEnabled(enabled: Boolean) = map.uiSettings.setAllGesturesEnabled(enabled)
+
+ @RequiresPermission(anyOf = ["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"])
+ override fun setMyLocationEnabled(enabled: Boolean) {
+ map.isMyLocationEnabled = enabled
+ }
+
+ override fun isLocationInVisibleRegion(location: LatLng): Boolean = map.projection.visibleRegion.latLngBounds.contains(location)
+
+ private fun getBoundingBox(targets: List) = LatLngBounds.builder()
+ .also { builder ->
+ targets.forEach { target -> builder.include(target) }
+ }
+ .build()
+
+ interface MapListener : AbstractMapListener
+
+}