{"id":311591,"date":"2020-10-16T15:01:20","date_gmt":"2020-10-16T15:01:20","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=311591"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=311591","title":{"rendered":"\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0440\u0442\u044b \u043e\u0442 Huawei \u0432 Android \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/521810\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ip\/vt\/ua\/ipvtuas0ifxicmrkpximu9tjqb4.png\" alt=\"image\"><\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b <a href=\"https:\/\/habr.com\/ru\/post\/520226\/\">\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/a> \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Huawei Mobile Services \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u043a \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e. \u041f\u043e\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/post\/521804\/\">\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443 \u043e\u0442 Huawei<\/a> \u0432\u043c\u0435\u0441\u0442\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0430 \u043e\u0442 Google. \u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438 \u0438 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c <a href=\"https:\/\/habr.com\/ru\/post\/521806\/\">\u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u0438<\/a>. \u0412 \u044d\u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u044b \u043e\u0442 Huawei \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u0430\u0440\u0442 \u043e\u0442 Google.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u0434 \u043a \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044e. <a href=\"https:\/\/habr.com\/ru\/post\/520226\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Huawei Analytics. <a href=\"https:\/\/habr.com\/ru\/post\/521804\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u044e \u043e\u0442 Huawei. <a href=\"https:\/\/habr.com\/ru\/post\/521806\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>Huawei maps. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043c\u0435\u0441\u0442\u043e Google maps \u0434\u043b\u044f AppGallery. \u2190 \u0432\u044b \u0442\u0443\u0442<\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"v-chyom-slozhnost\">\u0412 \u0447\u0451\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c<\/h3>\n<p>  <\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u0441 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u0439 \u0438 \u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u0435\u0439. \u0427\u0442\u043e \u0438 \u043d\u0435\u0443\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0442.\u043a. \u044d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u0430\u043c\u0430 \u043f\u043e \u0441\u0435\u0431\u0435. \u0418 \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043a\u0430\u0440\u0442\u044b \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043d\u0438\u043c\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442 \u043c\u0430\u0440\u043a\u0435\u0440\u044b, \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0443\u044e\u0442 \u0438\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e, \u0442.\u043a. \u043d\u0430\u0434\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u0430\u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u043c\u0435\u044f \u0432 \u0432\u0438\u0434\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0432 API \u043a\u0430\u0440\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h3 id=\"sozdayom-abstrakciyu-nad-kartoy\">\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e \u043d\u0430\u0434 \u043a\u0430\u0440\u0442\u043e\u0439<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u0434\u043e \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b. <code>com.google.android.libraries.maps.MapView<\/code> \u0434\u043b\u044f \u0433\u0443\u0433\u043b\u043e-\u043a\u0430\u0440\u0442 \u0438 <code>com.huawei.hms.maps.MapView<\/code> \u0434\u043b\u044f Huawei. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a: \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0443\u044e \u0432\u044c\u044e\u0445\u0443, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u043e\u0442 <code>FrameLayout<\/code> \u0438 \u0432 \u043d\u0435\u0451 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>MapView<\/code> \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 <code>flavors<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043d\u0430\u0448\u0435\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0439 \u0432\u044c\u044e\u0445\u0435 \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u0445. \u0418 \u0435\u0449\u0451 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441\u0430\u043c\u043e\u0439 \u043a\u0430\u0440\u0442\u044b. \u0418 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 MapView \u043e\u0442 \u0433\u0443\u0433\u043b\u0430 \u0438 Huawei \u0438 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0440\u0442 \u0438\u0437 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438. \u0412\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">abstract class MapView : FrameLayout {      enum class MapType(val value: Int) {         NONE(0), NORMAL(1), SATELLITE(2), TERRAIN(3), HYBRID(4)     }      protected var mapType = MapType.NORMAL      protected var liteModeEnabled = false      constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {         initView(context, attrs)     }      constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(         context,         attrs,         defStyleAttr     ) {         initView(context, attrs)     }      private fun initView(context: Context, attrs: AttributeSet) {         initAttributes(context, attrs)          inflateMapViewImpl()     }      private fun initAttributes(context: Context, attrs: AttributeSet) {          val attributeInfo = context.obtainStyledAttributes(             attrs,             R.styleable.MapView         )          mapType = MapType.values()[attributeInfo.getInt(             R.styleable.MapView_someMapType,             MapType.NORMAL.value         )]          liteModeEnabled = attributeInfo.getBoolean(R.styleable.MapView_liteModeEnabled, false)          attributeInfo.recycle()     }      abstract fun inflateMapViewImpl()      abstract fun onCreate(mapViewBundle: Bundle?)     abstract fun onStart()     abstract fun onResume()     abstract fun onPause()     abstract fun onStop()     abstract fun onLowMemory()     abstract fun onDestroy()     abstract fun onSaveInstanceState(mapViewBundle: Bundle?)     abstract fun getMapAsync(function: (SomeMap) -&gt; Unit) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u043d\u0430\u043c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0430\u0434\u043e \u0438\u0445 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 <code>res\/values\/attrs.xml<\/code> \u0432\u043e\u0442 \u044d\u0442\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">&lt;declare-styleable name=&quot;MapView&quot;&gt;     &lt;attr name=&quot;someMapType&quot;&gt;         &lt;enum name=&quot;none&quot; value=&quot;0&quot;\/&gt;         &lt;enum name=&quot;normal&quot; value=&quot;1&quot;\/&gt;         &lt;enum name=&quot;satellite&quot; value=&quot;2&quot;\/&gt;         &lt;enum name=&quot;terrain&quot; value=&quot;3&quot;\/&gt;         &lt;enum name=&quot;hybrid&quot; value=&quot;4&quot;\/&gt;     &lt;\/attr&gt;     &lt;attr format=&quot;boolean&quot; name=&quot;liteModeEnabled&quot;\/&gt; &lt;\/declare-styleable&gt;<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0440\u044f\u043c\u043e \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0430\u0448\u0443 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0443\u044e \u043a\u0430\u0440\u0442\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0438\u043f \u043a\u0430\u0440\u0442\u044b \u0438 \u043d\u0443\u0436\u0435\u043d \u043b\u0438 \u043d\u0430\u043c \u043e\u0431\u043b\u0435\u0433\u0447\u0451\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0451. \u0412\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a (\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>MapViewImpl<\/code> \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0434\u0430\u043b\u0435\u0435):<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">&lt;com.example.ui.base.widget.map.MapViewImpl     android:layout_width=&quot;match_parent&quot;     android:layout_height=&quot;150dp&quot;     app:liteModeEnabled=&quot;true&quot;     app:someMapType=&quot;normal&quot;\/&gt;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u0434\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>MapView<\/code>, \u0442\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u0438\u0439 <code>SomeMap<\/code> \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>getMapAsync<\/code>. \u0422\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0430\u0436\u0435\u043c \u043a\u0430\u043a\u0438\u0435 \u0435\u0449\u0451 \u043e\u0431\u0449\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u043a\u0430\u0440\u0442.<\/p>\n<p>  <\/p>\n<p><code>SomeMap<\/code> \u2014 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438. \u0412 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u043e\u043f\u0446\u0438\u0439 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u043f\u043e \u043a\u0430\u0440\u0442\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">abstract class SomeMap {      abstract fun setUiSettings(         isMapToolbarEnabled: Boolean? = null,         isCompassEnabled: Boolean? = null,         isRotateGesturesEnabled: Boolean? = null,         isMyLocationButtonEnabled: Boolean? = null,         isZoomControlsEnabled: Boolean? = null     )      abstract fun setPadding(left: Int, top: Int, right: Int, bottom: Int)      abstract fun animateCamera(someCameraUpdate: SomeCameraUpdate)     abstract fun moveCamera(someCameraUpdate: SomeCameraUpdate)     abstract fun setOnCameraIdleListener(function: () -&gt; Unit)     abstract fun setOnCameraMoveStartedListener(onCameraMoveStartedListener: (Int) -&gt; Unit)     abstract fun setOnCameraMoveListener(function: () -&gt; Unit)      abstract fun setOnMarkerClickListener(function: (SomeMarker) -&gt; Boolean)     abstract fun setOnMapClickListener(function: () -&gt; Unit)      abstract fun addMarker(markerOptions: SomeMarkerOptions): SomeMarker      abstract fun &lt;Item : SomeClusterItem&gt; addMarkers(         context: Context,         markers: List&lt;Item&gt;,         clusterItemClickListener: (Item) -&gt; Boolean,         clusterClickListener: (SomeCluster&lt;Item&gt;) -&gt; Boolean,         generateClusterItemIconFun: ((Item, Boolean) -&gt; Bitmap)? = null     ): (Item?) -&gt; Unit      companion object {         const val REASON_GESTURE = 1         const val REASON_API_ANIMATION = 2         const val REASON_DEVELOPER_ANIMATION = 3     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b\/\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b:<\/p>\n<p>  <\/p>\n<p><code>SomeCameraUpdate<\/code> \u2014 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u043d\u0430 \u043a\u0430\u0440\u0442\u0435 \u043a \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0442\u043e\u0447\u043a\u0435 \u0438\u043b\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class SomeCameraUpdate private constructor(     val location: Location? = null,     val zoom: Float? = null,     val bounds: SomeLatLngBounds? = null,     val width: Int? = null,     val height: Int? = null,     val padding: Int? = null ) {     constructor(         location: Location? = null,         zoom: Float? = null     ) : this(location, zoom, null, null, null, null)      constructor(         bounds: SomeLatLngBounds? = null,         width: Int? = null,         height: Int? = null,         padding: Int? = null     ) : this(null, null, bounds, width, height, padding) }<\/code><\/pre>\n<p>  <\/p>\n<p><code>SomeLatLngBounds<\/code> \u2014 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435, \u043a\u0443\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">abstract class SomeLatLngBounds(val southwest: Location? = null, val northeast: Location? = null) {        abstract fun forLocations(locations: List&lt;Location&gt;): SomeLatLngBounds }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432.<\/p>\n<p>  <\/p>\n<p><code>SomeMarker<\/code> \u2014 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0430\u0440\u043a\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">abstract class SomeMarker {     abstract fun remove() }<\/code><\/pre>\n<p>  <\/p>\n<p><code>SomeMarkerOptions<\/code> \u2014 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u0438 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">data class SomeMarkerOptions(     val icon: Bitmap,     val position: Location )<\/code><\/pre>\n<p>  <\/p>\n<p><code>SomeClusterItem<\/code> \u2014 \u0434\u043b\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u0430 \u043f\u0440\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">interface SomeClusterItem {     fun getLocation(): Location      fun getTitle(): String?      fun getSnippet(): String?      fun getDrawableResourceId(): Int }<\/code><\/pre>\n<p>  <\/p>\n<p><code>SomeCluster<\/code> \u2014 \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">data class SomeCluster&lt;T : SomeClusterItem&gt;(     val location: Location,     val items: List&lt;T&gt; )<\/code><\/pre>\n<p>  <\/p>\n<p><code>SelectableMarkerRenderer<\/code> \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438, \u043c\u0435\u043d\u044f\u044f \u0438\u043c \u0438\u043a\u043e\u043d\u043a\u0443 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0440\u043a\u0435\u0440.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">interface SelectableMarkerRenderer&lt;Item : SomeClusterItem&gt; {     val pinBitmapDescriptorsCache: Map&lt;Int, Bitmap&gt;      var selectedItem: Item?      fun selectItem(item: Item?)      fun getVectorResourceAsBitmap(@DrawableRes vectorResourceId: Int): Bitmap }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0432\u0438\u0434\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044f \u0438\u043a\u043e\u043d\u043a\u0443 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0438\u0437 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0438\u0437 \u0433\u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u2014 <code>IconGenerator<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">\/**  * Not full copy of com.google.maps.android.ui.IconGenerator  *\/ class IconGenerator(private val context: Context) {     private val mContainer = LayoutInflater.from(context)         .inflate(R.layout.map_marker_view, null as ViewGroup?) as ViewGroup     private var mTextView: TextView?     private var mContentView: View?      init {         mTextView = mContainer.findViewById(R.id.amu_text) as TextView         mContentView = mTextView     }      fun makeIcon(text: CharSequence?): Bitmap {         if (mTextView != null) {             mTextView!!.text = text         }         return this.makeIcon()     }      fun makeIcon(): Bitmap {         val measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)         mContainer.measure(measureSpec, measureSpec)         val measuredWidth = mContainer.measuredWidth         val measuredHeight = mContainer.measuredHeight         mContainer.layout(0, 0, measuredWidth, measuredHeight)         val r = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)         r.eraseColor(0)         val canvas = Canvas(r)         mContainer.draw(canvas)         return r     }      fun setContentView(contentView: View?) {         mContainer.removeAllViews()         mContainer.addView(contentView)         mContentView = contentView         val view = mContainer.findViewById&lt;View&gt;(R.id.amu_text)         mTextView = if (view is TextView) view else null     }      fun setBackground(background: Drawable?) {         mContainer.setBackgroundDrawable(background)         if (background != null) {             val rect = Rect()             background.getPadding(rect)             mContainer.setPadding(rect.left, rect.top, rect.right, rect.bottom)         } else {             mContainer.setPadding(0, 0, 0, 0)         }     }      fun setContentPadding(left: Int, top: Int, right: Int, bottom: Int) {         mContentView!!.setPadding(left, top, right, bottom)     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"sozdayom-realizacii-nashey-abstraktnoy-karty\">\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u044b<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">\/\/google maps googleImplementation 'com.google.android.gms:play-services-location:17.0.0' googleImplementation 'com.google.maps.android:android-maps-utils-sdk-v3-compat:0.1' \/\/clasterization \/\/huawei maps huaweiImplementation 'com.huawei.hms:maps:4.0.1.302'<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043a\u0430\u0440\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 (<code>AndroidManifest.xml<\/code>) \u0432 \u043f\u0430\u043f\u043a\u0435 <code>src\/huawei\/<\/code> \u0441 \u0442\u0430\u043a\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">&lt;manifest xmlns:android=&quot;http:\/\/schemas.android.com\/apk\/res\/android&quot;     package=&quot;com.example&quot;&gt;      &lt;!-- used for MapKit --&gt;     &lt;uses-permission android:name=&quot;com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA&quot;\/&gt; &lt;\/manifest&gt;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u0440\u0442 \u0434\u043b\u044f \u0433\u0443\u0433\u043b. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 <code>src\/google\/kotlin\/com\/example<\/code> \u043a\u043b\u0430\u0441\u0441 <code>MapViewImpl<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class MapViewImpl : MapView {      private lateinit var mapView: com.google.android.libraries.maps.MapView      constructor(context: Context, attrs: AttributeSet) : super(context, attrs)      constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(         context,         attrs,         defStyleAttr     )      override fun inflateMapViewImpl() {         mapView = com.google.android.libraries.maps.MapView(             context,             GoogleMapOptions().liteMode(liteModeEnabled).mapType(mapType.value)         )          addView(mapView)     }      override fun getMapAsync(function: (SomeMap) -&gt; Unit) {         mapView.getMapAsync { function(SomeMapImpl(it)) }     }      override fun onCreate(mapViewBundle: Bundle?) {         mapView.onCreate(mapViewBundle)     }      override fun onStart() {         mapView.onStart()     }      override fun onResume() {         mapView.onResume()     }      override fun onPause() {         mapView.onPause()     }      override fun onStop() {         mapView.onStop()     }      override fun onLowMemory() {         mapView.onLowMemory()     }      override fun onDestroy() {         mapView.onDestroy()     }      override fun onSaveInstanceState(mapViewBundle: Bundle?) {         mapView.onSaveInstanceState(mapViewBundle)     }      \/**      * We need to manually pass touch events to MapView      *\/     override fun onTouchEvent(event: MotionEvent?): Boolean {         mapView.onTouchEvent(event)         return true     }      \/**      * We need to manually pass touch events to MapView      *\/     override fun dispatchTouchEvent(event: MotionEvent?): Boolean {         mapView.dispatchTouchEvent(event)         return true     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410 \u0432 \u043f\u0430\u043f\u043a\u0443 <code>src\/huawei\/kotlin\/com\/example<\/code> \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>MapViewImpl<\/code> \u043d\u043e \u0443\u0436\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442 \u043e\u0442 Huawei:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class MapViewImpl : MapView {      private lateinit var mapView: com.huawei.hms.maps.MapView      constructor(context: Context, attrs: AttributeSet) : super(context, attrs)      constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(         context,         attrs,         defStyleAttr     )      override fun inflateMapViewImpl() {         mapView = com.huawei.hms.maps.MapView(             context,             HuaweiMapOptions().liteMode(liteModeEnabled).mapType(mapType.value)         )         addView(mapView)     }      override fun getMapAsync(function: (SomeMap) -&gt; Unit) {         mapView.getMapAsync { function(SomeMapImpl(it)) }     }      override fun onCreate(mapViewBundle: Bundle?) {         mapView.onCreate(mapViewBundle)     }      override fun onStart() {         mapView.onStart()     }      override fun onResume() {         mapView.onResume()     }      override fun onPause() {         try {             mapView.onPause()         } catch (e: Exception) {             \/\/ there can be ClassCastException: com.exmaple.App cannot be cast to android.app.Activity             \/\/ at com.huawei.hms.maps.MapView$MapViewLifecycleDelegate.onPause(MapView.java:348)             Log.wtf(&quot;MapView&quot;, &quot;Error while pausing MapView&quot;, e)         }     }      override fun onStop() {         mapView.onStop()     }      override fun onLowMemory() {         mapView.onLowMemory()     }      override fun onDestroy() {         mapView.onDestroy()     }      override fun onSaveInstanceState(mapViewBundle: Bundle?) {         mapView.onSaveInstanceState(mapViewBundle)     }      \/**      * We need to manually pass touch events to MapView      *\/     override fun onTouchEvent(event: MotionEvent?): Boolean {         mapView.onTouchEvent(event)         return true     }      \/**      * We need to manually pass touch events to MapView      *\/     override fun dispatchTouchEvent(event: MotionEvent?): Boolean {         mapView.dispatchTouchEvent(event)         return true     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u043d\u0430\u0434\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 3 \u043c\u043e\u043c\u0435\u043d\u0442\u0430:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0412\u044c\u044e\u0445\u0443 \u043a\u0430\u0440\u0442\u044b \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e, \u0430 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0438\u0437 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438, \u0442.\u043a. \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043d\u0435\u0451 \u043e\u043f\u0446\u0438\u0438 (\u043b\u0451\u0433\u043a\u0438\u0439 \u0440\u0435\u0436\u0438\u043c, \u0442\u0438\u043f \u043a\u0430\u0440\u0442\u044b etc).<\/li>\n<li>\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b <code>onTouchEvent<\/code> \u0438 <code>dispatchTouchEvent<\/code>, \u0441 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0432 <code>mapView<\/code> \u2014 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043a\u0430\u0440\u0442\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u0441\u0430\u043d\u0438\u044f.<\/li>\n<li>\u0412 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f Huawei \u0431\u044b\u043b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d \u043a\u0440\u044d\u0448 \u043f\u0440\u0438 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>onPause<\/code>, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0432 try-catch \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c. \u041d\u0430\u0434\u0435\u044e\u0441\u044c \u044d\u0442\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u044f\u0442 \u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438)<\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"realizuem-dopolnitelnye-abstrakcii\">\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438<\/h3>\n<p>  <\/p>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0430\u043c\u043e\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435. \u0423 \u043d\u0430\u0441 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0431\u044b\u043b\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u044b \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432. \u041a\u043e\u0433\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0438 \u044d\u0442\u043e \u0432\u0441\u0451 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u2014 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438. \u041f\u043e\u0447\u0442\u0438 \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u044f\u0441\u043d\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0445\u043e\u0442\u044f \u0432 \u043a\u0430\u0440\u0442\u0430\u0445 \u043e\u0442 Huawei \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043e\u043d\u0430 \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0430 \u043f\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0443 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442 \u0433\u0443\u0433\u043b\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0435\u043b\u044c\u0437\u044f \u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043d\u0435\u0433\u043e. \u0422\u0430\u043a\u0436\u0435 \u0432 Huawei \u043a\u0430\u0440\u0442\u0430\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432 (\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439) \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0438 \u043c\u0430\u0440\u043a\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0410 \u0432\u043e\u0442 \u0432 \u0433\u0443\u0433\u043b\u043e-\u043a\u0430\u0440\u0442\u0430\u0445 \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0443\u044e\u0449\u0438\u0445\u0441\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432 \u0432\u0441\u0451 \u0438\u043d\u0430\u0447\u0435 \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0432\u0438\u0434\u0430 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0451 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u0443\u043c\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0433\u0443\u0433\u043b\u043e-\u043a\u0430\u0440\u0442 \u0438 \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0440\u0442\u044b \u043e\u0442 Huawei \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u043f\u0440\u0438\u0448\u043b\u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043a \u0442\u0430\u043a\u043e\u043c\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443: \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0432 \u043d\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043b\u044f\u043c\u0431\u0434\u0443, \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u0430. \u0412\u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>SomeMap<\/code> \u0434\u043b\u044f \u0433\u0443\u0433\u043b\u043e-\u043a\u0430\u0440\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class SomeMapImpl(val map: GoogleMap) : SomeMap() {      override fun setUiSettings(         isMapToolbarEnabled: Boolean?,         isCompassEnabled: Boolean?,         isRotateGesturesEnabled: Boolean?,         isMyLocationButtonEnabled: Boolean?,         isZoomControlsEnabled: Boolean?     ) {         map.uiSettings.apply {             isMapToolbarEnabled?.let {                 this.isMapToolbarEnabled = isMapToolbarEnabled             }             isCompassEnabled?.let {                 this.isCompassEnabled = isCompassEnabled             }             isRotateGesturesEnabled?.let {                 this.isRotateGesturesEnabled = isRotateGesturesEnabled             }             isMyLocationButtonEnabled?.let {                 this.isMyLocationButtonEnabled = isMyLocationButtonEnabled             }             isZoomControlsEnabled?.let {                 this.isZoomControlsEnabled = isZoomControlsEnabled             }              setAllGesturesEnabled(true)         }     }      override fun animateCamera(someCameraUpdate: SomeCameraUpdate) {         someCameraUpdate.toCameraUpdate()?.let { map.animateCamera(it) }     }      override fun moveCamera(someCameraUpdate: SomeCameraUpdate) {         someCameraUpdate.toCameraUpdate()?.let { map.moveCamera(it) }     }      override fun setOnCameraIdleListener(function: () -&gt; Unit) {         map.setOnCameraIdleListener { function() }     }      override fun setOnMarkerClickListener(function: (SomeMarker) -&gt; Boolean) {         map.setOnMarkerClickListener { function(MarkerImpl(it)) }     }      override fun setOnMapClickListener(function: () -&gt; Unit) {         map.setOnMapClickListener { function() }     }      override fun setOnCameraMoveStartedListener(onCameraMoveStartedListener: (Int) -&gt; Unit) {         map.setOnCameraMoveStartedListener { onCameraMoveStartedListener(it) }     }      override fun addMarker(markerOptions: SomeMarkerOptions): SomeMarker {         return MarkerImpl(             map.addMarker(                 MarkerOptions()                     .position(markerOptions.position.toLatLng())                     .icon(BitmapDescriptorFactory.fromBitmap(markerOptions.icon))             )         )     }      override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {         map.setPadding(left, top, right, bottom)     }      override fun setOnCameraMoveListener(function: () -&gt; Unit) {         map.setOnCameraMoveListener { function() }     }      override fun &lt;Item : SomeClusterItem&gt; addMarkers(         context: Context,         markers: List&lt;Item&gt;,         clusterItemClickListener: (Item) -&gt; Boolean,         clusterClickListener: (SomeCluster&lt;Item&gt;) -&gt; Boolean,         generateClusterItemIconFun: ((Item, Boolean) -&gt; Bitmap)?     ): (Item?) -&gt; Unit {         val clusterManager = ClusterManager&lt;SomeClusterItemImpl&lt;Item&gt;&gt;(context, map)             .apply {                 setOnClusterItemClickListener {                     clusterItemClickListener(it.someClusterItem)                 }                  setOnClusterClickListener { cluster -&gt;                     val position = Location(cluster.position.latitude, cluster.position.longitude)                     val items: List&lt;Item&gt; = cluster.items.map { it.someClusterItem }                     val someCluster: SomeCluster&lt;Item&gt; = SomeCluster(position, items)                     clusterClickListener(someCluster)                 }             }          map.setOnCameraIdleListener(clusterManager)         map.setOnMarkerClickListener(clusterManager)          val renderer =             object :                 DefaultClusterRenderer&lt;SomeClusterItemImpl&lt;Item&gt;&gt;(context, map, clusterManager),                 SelectableMarkerRenderer&lt;SomeClusterItemImpl&lt;Item&gt;&gt; {                 override val pinBitmapDescriptorsCache = mutableMapOf&lt;Int, Bitmap&gt;()                  override var selectedItem: SomeClusterItemImpl&lt;Item&gt;? = null                  override fun onBeforeClusterItemRendered(                     item: SomeClusterItemImpl&lt;Item&gt;,                     markerOptions: MarkerOptions                 ) {                     val icon = generateClusterItemIconFun                         ?.invoke(item.someClusterItem, item == selectedItem)                         ?: getVectorResourceAsBitmap(                             item.someClusterItem.getDrawableResourceId(item == selectedItem)                         )                     markerOptions                         .icon(BitmapDescriptorFactory.fromBitmap(icon))                         .zIndex(1.0f) \/\/ to hide cluster pin under the office pin                 }                  override fun getColor(clusterSize: Int): Int {                     return context.resources.color(R.color.primary)                 }                  override fun selectItem(item: SomeClusterItemImpl&lt;Item&gt;?) {                     selectedItem?.let {                         val icon = generateClusterItemIconFun                             ?.invoke(it.someClusterItem, false)                             ?: getVectorResourceAsBitmap(                                 it.someClusterItem.getDrawableResourceId(false)                             )                         getMarker(it)?.setIcon(BitmapDescriptorFactory.fromBitmap(icon))                     }                      selectedItem = item                      item?.let {                         val icon = generateClusterItemIconFun                             ?.invoke(it.someClusterItem, true)                             ?: getVectorResourceAsBitmap(                                 it.someClusterItem.getDrawableResourceId(true)                             )                         getMarker(it)?.setIcon(BitmapDescriptorFactory.fromBitmap(icon))                     }                 }                  override fun getVectorResourceAsBitmap(@DrawableRes vectorResourceId: Int): Bitmap {                     return pinBitmapDescriptorsCache[vectorResourceId]                         ?: context.resources.generateBitmapFromVectorResource(vectorResourceId)                             .also { pinBitmapDescriptorsCache[vectorResourceId] = it }                 }             }          clusterManager.renderer = renderer          clusterManager.clearItems()         clusterManager.addItems(markers.map { SomeClusterItemImpl(it) })         clusterManager.cluster()          @Suppress(&quot;UnnecessaryVariable&quot;)         val pinItemSelectedCallback = fun(item: Item?) {             renderer.selectItem(item?.let { SomeClusterItemImpl(it) })         }         return pinItemSelectedCallback     } }  fun Location.toLatLng() = LatLng(latitude, longitude)  fun SomeLatLngBounds.toLatLngBounds() = LatLngBounds(southwest?.toLatLng(), northeast?.toLatLng())  fun SomeCameraUpdate.toCameraUpdate(): CameraUpdate? {     return if (zoom != null) {         CameraUpdateFactory.newCameraPosition(             CameraPosition.fromLatLngZoom(                 location?.toLatLng()                     ?: Location.DEFAULT_LOCATION.toLatLng(),                 zoom             )         )     } else if (bounds != null &amp;&amp; width != null &amp;&amp; height != null &amp;&amp; padding != null) {         CameraUpdateFactory.newLatLngBounds(             bounds.toLatLngBounds(),             width,             height,             padding         )     } else {         null     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u043e\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u043a\u0430\u043a \u0443\u0436\u0435 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u2014 \u0432 <code>addMarkers<\/code> \u043c\u0435\u0442\u043e\u0434\u0435. \u0412 \u043d\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f <code>ClusterManager<\/code> \u0438 <code>ClusterRenderer<\/code>, \u0430\u043d\u0430\u043b\u043e\u0433\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u0442 \u0432 Huawei \u043a\u0430\u0440\u0442\u0430\u0445. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u044d\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0430\u0440\u043a\u0435\u0442\u044b \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>ClusterItem<\/code>, \u0430\u043d\u0430\u043b\u043e\u0433\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0442 \u0443 Huawei. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0435\u0439. Data \u043a\u043b\u0430\u0441\u0441\u044b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>SomeClusterItem<\/code>, \u0430 \u0433\u0443\u0433\u043b\u043e\u0432\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>ClusterItem<\/code> \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0430\u0440\u043a\u0435\u0440\u0430. \u0412\u043e\u0442 \u0442\u0430\u043a\u0430\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">data class SomeClusterItemImpl&lt;T : SomeClusterItem&gt;(     val someClusterItem: T ) : ClusterItem, SomeClusterItem {      override fun getSnippet(): String {         return someClusterItem.getSnippet() ?: &quot;&quot;     }      override fun getTitle(): String {         return someClusterItem.getTitle() ?: &quot;&quot;     }      override fun getPosition(): LatLng {         return someClusterItem.getLocation().toLatLng()     }      override fun getLocation(): Location {         return someClusterItem.getLocation()     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435, \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e-\u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u0440\u0442 \u0434\u043b\u044f \u0433\u0443\u0433\u043b\u0430 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0432 \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 <code>ClusterItem<\/code> \u0438\u0437 \u0433\u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u2014 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>addMarkers<\/code> \u0432\u044b\u0448\u0435.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0451 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u044d\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class SomeLatLngBoundsImpl(bounds: LatLngBounds? = null) :     SomeLatLngBounds(bounds?.southwest?.toLocation(), bounds?.northeast?.toLocation()) {      override fun forLocations(locations: List&lt;Location&gt;): SomeLatLngBounds {         val bounds = LatLngBounds.builder()             .apply { locations.map { it.toLatLng() }.forEach { include(it) } }             .build()          return SomeLatLngBoundsImpl(bounds)     } }  fun LatLng.toLocation(): Location {     return Location(latitude, longitude) }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class MarkerImpl(private val marker: Marker?) : SomeMarker() {     override fun remove() {         marker?.remove()     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0434\u043b\u044f Huawei \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0449\u0435 \u2014 \u043d\u0435 \u043d\u0430\u0434\u043e \u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435\u043c <code>SomeClusterItem<\/code>. \u0412\u043e\u0442 \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0434\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 <code>src\/huawei\/kotlin\/com\/example<\/code>:<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>SomeMap<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class SomeMapImpl(val map: HuaweiMap) : SomeMap() {      override fun setUiSettings(         isMapToolbarEnabled: Boolean?,         isCompassEnabled: Boolean?,         isRotateGesturesEnabled: Boolean?,         isMyLocationButtonEnabled: Boolean?,         isZoomControlsEnabled: Boolean?     ) {         map.uiSettings.apply {             isMapToolbarEnabled?.let {                 this.isMapToolbarEnabled = isMapToolbarEnabled             }             isCompassEnabled?.let {                 this.isCompassEnabled = isCompassEnabled             }             isRotateGesturesEnabled?.let {                 this.isRotateGesturesEnabled = isRotateGesturesEnabled             }             isMyLocationButtonEnabled?.let {                 this.isMyLocationButtonEnabled = isMyLocationButtonEnabled             }             isZoomControlsEnabled?.let {                 this.isZoomControlsEnabled = isZoomControlsEnabled             }              setAllGesturesEnabled(true)         }     }      override fun animateCamera(someCameraUpdate: SomeCameraUpdate) {         someCameraUpdate.toCameraUpdate()?.let { map.animateCamera(it) }     }      override fun moveCamera(someCameraUpdate: SomeCameraUpdate) {         someCameraUpdate.toCameraUpdate()?.let { map.moveCamera(it) }     }      override fun setOnCameraIdleListener(function: () -&gt; Unit) {         map.setOnCameraIdleListener { function() }     }      override fun setOnMarkerClickListener(function: (SomeMarker) -&gt; Boolean) {         map.setOnMarkerClickListener { function(MarkerImpl(it)) }     }      override fun setOnMapClickListener(function: () -&gt; Unit) {         map.setOnMapClickListener { function() }     }      override fun setOnCameraMoveStartedListener(onCameraMoveStartedListener: (Int) -&gt; Unit) {         map.setOnCameraMoveStartedListener { onCameraMoveStartedListener(it) }     }      override fun addMarker(markerOptions: SomeMarkerOptions): SomeMarker {         return MarkerImpl(             map.addMarker(                 MarkerOptions()                     .position(markerOptions.position.toLatLng())                     .icon(BitmapDescriptorFactory.fromBitmap(markerOptions.icon))             )         )     }      override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {         map.setPadding(left, top, right, bottom)     }      override fun setOnCameraMoveListener(function: () -&gt; Unit) {         map.setOnCameraMoveListener { function() }     }      override fun &lt;Item : SomeClusterItem&gt; addMarkers(         context: Context,         markers: List&lt;Item&gt;,         clusterItemClickListener: (Item) -&gt; Boolean,         clusterClickListener: (SomeCluster&lt;Item&gt;) -&gt; Boolean,         generateClusterItemIconFun: ((Item, Boolean) -&gt; Bitmap)?     ): (Item?) -&gt; Unit {         val addedMarkers = mutableListOf&lt;Pair&lt;Item, Marker&gt;&gt;()          val selectableMarkerRenderer = object : SelectableMarkerRenderer&lt;Item&gt; {             override val pinBitmapDescriptorsCache = mutableMapOf&lt;Int, Bitmap&gt;()              override var selectedItem: Item? = null              override fun selectItem(item: Item?) {                 selectedItem?.let {                     val icon = generateClusterItemIconFun                         ?.invoke(it, false)                         ?: getVectorResourceAsBitmap(it.getDrawableResourceId(false))                     getMarker(it)?.setIcon(BitmapDescriptorFactory.fromBitmap(icon))                 }                  selectedItem = item                  item?.let {                     val icon = generateClusterItemIconFun                         ?.invoke(it, true)                         ?: getVectorResourceAsBitmap(                             it.getDrawableResourceId(true)                         )                     getMarker(it)?.setIcon(BitmapDescriptorFactory.fromBitmap(icon))                 }             }              private fun getMarker(item: Item): Marker? {                 return addedMarkers.firstOrNull { it.first == item }?.second             }              override fun getVectorResourceAsBitmap(@DrawableRes vectorResourceId: Int): Bitmap {                 return pinBitmapDescriptorsCache[vectorResourceId]                     ?: context.resources.generateBitmapFromVectorResource(vectorResourceId)                         .also { pinBitmapDescriptorsCache[vectorResourceId] = it }             }         }          addedMarkers += markers.map {             val selected = selectableMarkerRenderer.selectedItem == it             val icon = generateClusterItemIconFun                 ?.invoke(it, selected)                 ?: selectableMarkerRenderer.getVectorResourceAsBitmap(it.getDrawableResourceId(selected))              val markerOptions = MarkerOptions()                 .position(it.getLocation().toLatLng())                 .icon(BitmapDescriptorFactory.fromBitmap(icon))                 .clusterable(true)             val marker = map.addMarker(markerOptions)              it to marker         }         map.setMarkersClustering(true)          map.setOnMarkerClickListener { clickedMarker -&gt;             val clickedItem = addedMarkers.firstOrNull { it.second == clickedMarker }?.first             clickedItem?.let { clusterItemClickListener(it) } ?: false         }          return selectableMarkerRenderer::selectItem     } }  fun Location.toLatLng() = LatLng(latitude, longitude)  fun SomeLatLngBounds.toLatLngBounds() = LatLngBounds(southwest?.toLatLng(), northeast?.toLatLng())  fun SomeCameraUpdate.toCameraUpdate(): CameraUpdate? {     return if (zoom != null) {         CameraUpdateFactory.newCameraPosition(             CameraPosition.fromLatLngZoom(                 location?.toLatLng()                     ?: Location.DEFAULT_LOCATION.toLatLng(),                 zoom             )         )     } else if (bounds != null &amp;&amp; width != null &amp;&amp; height != null &amp;&amp; padding != null) {         CameraUpdateFactory.newLatLngBounds(             bounds.toLatLngBounds(),             width,             height,             padding         )     } else {         null     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class SomeLatLngBoundsImpl(bounds: LatLngBounds? = null) :     SomeLatLngBounds(bounds?.southwest?.toLocation(), bounds?.northeast?.toLocation()) {      override fun forLocations(locations: List&lt;Location&gt;): SomeLatLngBounds {         val bounds = LatLngBounds.builder()             .apply { locations.map { it.toLatLng() }.forEach { include(it) } }             .build()          return SomeLatLngBoundsImpl(bounds)     } }  fun LatLng.toLocation(): Location {     return Location(latitude, longitude) }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\">class MarkerImpl(private val marker: Marker?) : SomeMarker() {     override fun remove() {         marker?.remove()     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0438\u0445 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439 \u043c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0412\u0430\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432 \u0432\u0438\u0434\u0443, \u0447\u0442\u043e \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0438 \u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0434\u0435\u0432\u0430\u0439\u0441\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b Huawei Mobile Services, \u043a\u0430\u0440\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u043e\u0442 Huawei.<\/p>\n<p>  <\/p>\n<h3 id=\"ispolzuem-nashu-abstraktnuyu-kartu\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0430\u0448\u0443 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0443\u044e \u043a\u0430\u0440\u0442\u0443<\/h3>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c <code>MapViewImpl<\/code>, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435 \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043a\u043e\u0434\u0443. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 <code>MapView<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u0440\u0442\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">mapView.getMapAsync { onMapReady(it) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u2014 \u0431\u0443\u0434\u0435\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0435\u0439 \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0448\u0435\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438. \u0410 \u0442\u0430\u043a\u0436\u0435, \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438, \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u0438\u0445 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. \u0418 \u0435\u0449\u0451 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b, \u043a\u0430\u043a \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c \u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">private fun onMapReady(map: SomeMap) {     map.setUiSettings(isMapToolbarEnabled = false, isCompassEnabled = false)      var pinItemSelected: ((MarkerItem?) -&gt; Unit)? = null      fun onMarkerSelected(selectedMarkerItem: MarkerItem?) {         pinItemSelected?.invoke(selectedMarkerItem)         selectedMarkerItem?.let {             map.animateCamera(SomeCameraUpdate(it.getLocation(), DEFAULT_ZOOM))             Snackbar.make(root, &quot;Marker selected: ${it.markerTitle}&quot;, Snackbar.LENGTH_SHORT).show()         }     }      with(map) {         setOnMapClickListener {             onMarkerSelected(null)         }          setOnCameraMoveStartedListener { reason -&gt;             if (reason == SomeMap.REASON_GESTURE) {                 onMarkerSelected(null)             }         }     }      locationGateway.requestLastLocation()         .flatMap { mapMarkersGateway.getMapMarkers(it) }         .subscribeBy { itemList -&gt;             pinItemSelected = map.addMarkers(                 requireContext(),                 itemList.map { it },                 {                     onMarkerSelected(it)                     true                 },                 { someCluster -&gt;                     mapView?.let { mapViewRef -&gt;                         val bounds = SomeLatLngBoundsImpl()                             .forLocations(someCluster.items.map { it.getLocation() })                          val someCameraUpdate = SomeCameraUpdate(                             bounds = bounds,                             width = mapViewRef.width,                             height = mapViewRef.height,                             padding = 32.dp()                         )                          map.animateCamera(someCameraUpdate)                     }                      onMarkerSelected(null)                      true                 }             )         } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043e\u043f\u0443\u0449\u0435\u043d\u0430 \u0434\u043b\u044f \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438. \u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"https:\/\/github.com\/MobileUpLLC\/huawei_and_google_services\" rel=\"nofollow\">GitHub<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0410 \u0432\u043e\u0442 \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043a\u0430\u0440\u0442\u044b \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 (\u0441\u043d\u0430\u0447\u0430\u043b\u0430 Huawei, \u043f\u043e\u0442\u043e\u043c Google):<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/vz\/eo\/eu\/vzeoeuyxzyarbccgedhnygcftdc.png\" alt=\"Huawei maps\"><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ec\/gu\/wu\/ecguwus8dvmufxsngo1safe7w-4.png\" alt=\"Google maps\"><\/p>\n<p>  <\/p>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u2014 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u0441 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u0439. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f. \u0425\u043e\u0442\u044f \u043c\u043e\u0433\u043b\u043e \u0431\u044b\u0442\u044c \u0438 \u0445\u0443\u0436\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0435\u0441\u043b\u0438 \u0431\u044b API \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u043b\u043e\u0441\u044c \u0441\u0438\u043b\u044c\u043d\u0435\u0435. \u0422\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 Huawei \u0437\u0430 \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043a\u0430\u0440\u0442 \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<h3 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>  <\/p>\n<p>\u0420\u044b\u043d\u043e\u043a \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u0415\u0449\u0451 \u0432\u0447\u0435\u0440\u0430 \u043a\u0430\u0437\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u043d\u0435\u0437\u044b\u0431\u043b\u0435\u043c\u044b\u043c\u0438 \u043c\u043e\u043d\u043e\u043f\u043e\u043b\u0438\u0438 Google \u0438 Apple \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u044b \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u0442\u0440\u0430\u0434\u0430\u0432\u0448\u0438\u043c\u0438 \u043e\u0442 \u043d\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 (\u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u2014 <a href=\"http:\/\/dont-play-with-google.com\/#\/article\/137\" rel=\"nofollow\">Telegram<\/a>, <a href=\"http:\/\/dont-play-with-google.com\/en\/#\/article\/140\" rel=\"nofollow\">Microsoft<\/a>, <a href=\"http:\/\/dont-play-with-google.com\/#\/article\/148\" rel=\"nofollow\">Epic Games<\/a>) \u043d\u043e \u0438 \u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438 \u0443\u0440\u043e\u0432\u043d\u044f <a href=\"http:\/\/dont-play-with-google.com\/#\/article\/122\" rel=\"nofollow\">EC<\/a> \u0438 <a href=\"http:\/\/dont-play-with-google.com\/en\/#\/article\/133\" rel=\"nofollow\">\u0421\u0428\u0410<\/a>. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043d\u0430 \u044d\u0442\u043e\u043c \u0444\u043e\u043d\u0435 \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0437\u0434\u043e\u0440\u043e\u0432\u0430\u044f \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u0430\u044f \u0441\u0440\u0435\u0434\u0430 \u0445\u043e\u0442\u044f \u0431\u044b \u043d\u0430 Android. \u0420\u0430\u0431\u043e\u0442\u0430 Huawei \u0432 \u044d\u0442\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0440\u0430\u0434\u0443\u0435\u0442 \u2014 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043b\u044e\u0434\u0438 \u0441\u0442\u0430\u0440\u0430\u044e\u0442\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c. \u041f\u043e\u0441\u043b\u0435 \u043e\u043f\u044b\u0442\u0430 \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u0442\u0435\u0445. \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 GooglePlay, \u0433\u0434\u0435 \u0442\u0435\u0431\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0440\u043e\u0431\u043e\u0442\u044b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c (\u0438 \u043e\u043d\u0438 \u0436\u0435 \u0438 \u0431\u0430\u043d\u044f\u0442) \u0432 Huawei \u0442\u0435\u0431\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043b\u044e\u0434\u0438. \u041c\u0430\u043b\u043e \u0442\u043e\u0433\u043e \u2014 \u043a\u043e\u0433\u0434\u0430 \u0443 \u043c\u0435\u043d\u044f \u0432\u043e\u0437\u043d\u0438\u043a \u0432\u043e\u043f\u0440\u043e\u0441 \u043f\u043e \u0438\u0445 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u2014 \u0443 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c \u0438 \u043f\u043e\u0437\u0432\u043e\u043d\u0438\u0442\u044c \u0436\u0438\u0432\u043e\u043c\u0443 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0443 \u0438\u0437 \u041c\u043e\u0441\u043a\u0432\u044b \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u044e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0442\u0435\u0445.\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u2014 \u0438\u0434\u0438\u0442\u0435 \u0432 Huawei. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0442\u0435\u043c \u0432\u044b\u0448\u0435 \u0448\u0430\u043d\u0441, \u0447\u0442\u043e \u0438 \u0432 GooglePlay \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043b\u0443\u0447\u0448\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443. \u0418 \u0432\u044b\u0438\u0433\u0440\u0430\u044e\u0442 \u0432\u0441\u0435.<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0441\u0442\u044c \u0432 \u044d\u0442\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 GitHub. \u0412\u043e\u0442 <a href=\"https:\/\/github.com\/MobileUpLLC\/huawei_and_google_services\" rel=\"nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430<\/a>.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/521810\/\"> https:\/\/habr.com\/ru\/post\/521810\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/521810\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ip\/vt\/ua\/ipvtuas0ifxicmrkpximu9tjqb4.png\" alt=\"image\"><\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b <a href=\"https:\/\/habr.com\/ru\/post\/520226\/\">\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/a> \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Huawei Mobile Services \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u043a \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e. \u041f\u043e\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/post\/521804\/\">\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443 \u043e\u0442 Huawei<\/a> \u0432\u043c\u0435\u0441\u0442\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0430 \u043e\u0442 Google. \u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438 \u0438 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c <a href=\"https:\/\/habr.com\/ru\/post\/521806\/\">\u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u0438<\/a>. \u0412 \u044d\u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u044b \u043e\u0442 Huawei \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u0430\u0440\u0442 \u043e\u0442 Google.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u0434 \u043a \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044e. <a href=\"https:\/\/habr.com\/ru\/post\/520226\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Huawei Analytics. <a href=\"https:\/\/habr.com\/ru\/post\/521804\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u044e \u043e\u0442 Huawei. <a href=\"https:\/\/habr.com\/ru\/post\/521806\/\">\u0442\u044b\u043a<\/a><\/li>\n<li>Huawei maps. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043c\u0435\u0441\u0442\u043e Google maps \u0434\u043b\u044f AppGallery. \u2190 \u0432\u044b \u0442\u0443\u0442<\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"v-chyom-slozhnost\">\u0412 \u0447\u0451\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c<\/h3>\n<p>  <\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u0441 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u0439 \u0438 \u0433\u0435\u043e\u043b\u043e\u043a\u0430\u0446\u0438\u0435\u0439. \u0427\u0442\u043e \u0438 \u043d\u0435\u0443\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0442.\u043a. \u044d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u0430\u043c\u0430 \u043f\u043e \u0441\u0435\u0431\u0435. \u0418 \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043a\u0430\u0440\u0442\u044b \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043d\u0438\u043c\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442 \u043c\u0430\u0440\u043a\u0435\u0440\u044b, \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0443\u044e\u0442 \u0438\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e, \u0442.\u043a. \u043d\u0430\u0434\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u0430\u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u043c\u0435\u044f \u0432 \u0432\u0438\u0434\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0432 API \u043a\u0430\u0440\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-311591","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/311591","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=311591"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/311591\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=311591"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=311591"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=311591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}