Coder Social home page Coder Social logo

googlemaps / android-maps-ktx Goto Github PK

View Code? Open in Web Editor NEW
314.0 15.0 45.0 10.86 MB

Kotlin extensions (KTX) for the Maps SDK and Utility Library for Android

Home Page: https://developers.google.com/maps/documentation/android-sdk/ktx

License: Apache License 2.0

Kotlin 100.00%
kotlin ktx-library android-maps-utils android maps google-maps language-extension

android-maps-ktx's People

Contributors

arriolac avatar barbeau avatar danielgomezrico avatar dependabot-preview[bot] avatar dependabot[bot] avatar googlemaps-bot avatar jpoehnelt avatar kikoso avatar louiscad avatar marcauberer avatar semantic-release-bot avatar simonmarquis avatar tperraut avatar wangela avatar ychescale9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-maps-ktx's Issues

Kotlin Flow: cameraMoveStartedEvents missing reason

Environment details

OS type and version: any
Library version and other environment information: v3.2.0

Steps to reproduce

googleMap.cameraMoveStartedEvents().collect { ... }

Code example

cameraMoveStartedEvents does not pass reason code:

https://github.com/googlemaps/android-maps-ktx/blob/main/maps-ktx/src/main/java/com/google/maps/android/ktx/GoogleMap.kt#L240

Should be:

public fun GoogleMap.cameraMoveStartedEvents(): Flow<Int> =
    callbackFlow {
        setOnCameraMoveStartedListener {
            trySend(it)
        }
        awaitClose {
            setOnCameraMoveStartedListener(null)
        }
    }

Provide Kotlin Extensions for Maps SDK

Is your feature request related to a problem? Please describe.
This library should have Kotlin friendly extensions so that modern language features offered by Kotlin (e.g. extensions, lambdas, coroutines, etc.) can be used while interacting with this library.

Describe the solution you'd like
This feature should allow me to write idiomatic Kotlin while using the Maps SDK.

Additional context
Similar to googlemaps/android-maps-utils#618

MapFragment should not use deprecated android.app.Fragment in SDK v3

The implementation of SupportMapFragment should replace the implementation of MapFragment, and SupportMapFragment should become a deprecated class extending the new MapFragment.

Support libraries are long gone, and the naming of the v3 of the SDK should reflect that instead of being stuck in the past and keep confusing developers.

Add support for Flow when receiving Camera events

Is your feature request related to a problem? Please describe.
Kotlin's flow construct can be used to receive various camera change events (i.e. move started, move, move cancelled. and idle). Using flow for this use case seems to be a really concise way of receiving camera events vs. having to set 4 separate listeners to the GoogleMap object. Additionally, enumerating camera event types also encourages developers to think about all the different states and not necessarily just one event (e.g. just listening to the move event)

Describe the solution you'd like
Create an extension function on GoogleMap that returns a Flow emitting camera events.

e.g.

googleMap.cameraEvents().collect { cameraEvent ->
    when (cameraEvent) {
        is CameraEvent.MoveStarted -> TODO()
        is CameraEvent.Move -> TODO()
        is CameraEvent.Cancelled -> TODO()
        is CameraEvent.Idle -> TODO()
    }
}

Describe alternatives you've considered
N/A

Additional context
N/A

Readme is using deprecated method

The readme is showing the following:

    lifecycle.coroutineScope.launchWhenCreated {
        val googleMap = mapFragment?.awaitMap()
    }

as the example of how to use this, but that code has been deprecated.
Can you update the readme to have a more current example?

Is:

     lifecycleScope.lifecycleScope.launch {
         lifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) {
             val googleMap = mapFragment?.awaitMap()
         }
     }

the correct way to use this now?

Map flickering on some devices

Hi,
I want to report a possible bug. The map is flickering on some devices (see video below).

Device:

Model: Lenovo Tab M10 Plus 10'' Tablet
Android version: Android 9

But I observed the bug on other devices as well. On other devices (e.g.: Pixel 3a) it works like a charm.

Video

device-2020-06-19-192530

Layout config

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <androidx.appcompat.widget.AppCompatSpinner
        android:id="@+id/mapType"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:background="@drawable/map_control_background"
        android:clickable="true"
        android:focusable="true"
        android:layout_margin="6dp"
        android:padding="2dp"
        android:elevation="10dp"/>

    <androidx.appcompat.widget.AppCompatSpinner
        android:id="@+id/mapTraffic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@+id/mapType"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@drawable/map_control_background"
        android:clickable="true"
        android:focusable="true"
        android:layout_marginStart="6dp"
        android:layout_marginTop="6dp"
        android:padding="2dp"
        android:elevation="10dp"/>

    <TextView
        android:id="@+id/mapSensorCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@+id/mapTraffic"
        app:layout_constraintTop_toTopOf="parent"
        android:paddingStart="6dp"
        android:paddingEnd="6dp"
        android:paddingTop="3dp"
        android:paddingBottom="3dp"
        android:text="@string/loading"
        android:textColor="@color/colorTextMapControls"
        android:background="@drawable/map_control_background"
        android:clickable="true"
        android:focusable="true"
        android:layout_margin="6dp"
        android:elevation="10dp"/>

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/mapRefresh"
        android:layout_width="35dp"
        android:layout_height="35dp"
        app:srcCompat="@drawable/refresh_white"
        android:tint="@color/colorTextMapControls"
        android:background="@drawable/map_control_background"
        android:clickable="true"
        android:focusable="true"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="3dp"
        android:elevation="10dp"/>

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/mapRanking"
        android:layout_width="35dp"
        android:layout_height="35dp"
        app:srcCompat="@drawable/format_list_numbered_white"
        android:tint="@color/colorTextMapControls"
        android:background="@drawable/map_control_background"
        android:clickable="true"
        android:focusable="true"
        app:layout_constraintTop_toBottomOf="@+id/mapRefresh"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="3dp"
        android:elevation="10dp"/>

    <include
        android:id="@+id/markerWindow1"
        layout="@layout/info_window_marker"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:visibility="invisible"/>

    <include
        android:id="@+id/markerWindow2"
        layout="@layout/info_window_marker"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:visibility="invisible"/>

    <include
        android:id="@+id/clusterWindow1"
        layout="@layout/info_window_cluster"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:visibility="invisible"/>

    <include
        android:id="@+id/clusterWindow2"
        layout="@layout/info_window_cluster"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:visibility="invisible"/>
</androidx.constraintlayout.widget.ConstraintLayout>

This is a fragment, which gets displayed within a ViewPager2.

Would appreciate a fix. Thank you ;)

android-maps-ktx: Listeners aren't removed in awaitClose block in cameraEvents(): Flow implementation

👋 I was looking at the new cameraEvents(): Flow<CameraEvent> implementation. It looks like the listeners aren't cleared when the channel is closed / cancelled. I'd expect something like this:

callbackFlow {
  val idleListener = GoogleMap.OnCameraIdleListener {
    offer(CameraIdleEvent)
  }
  ...
  setOnCameraIdleListener(idleListener)
  awaitClose {
    setOnCameraIdleListener(null)
    ...
  }
}

Happy to send a PR 😃 .

Tests failing due to demo app for ClusterItem

Tests are encountering this error:

file:///home/runner/work/android-maps-ktx/android-maps-ktx/app/src/main/java/com/google/maps/android/ktx/demo/model/MyItem.kt:29:6 Class 'MyItem' is not abstract and does not implement abstract member public abstract fun getZIndex(): Float? defined in com.google.maps.android.clustering.ClusterItem

See logs for PR #214 at https://github.com/googlemaps/android-maps-ktx/actions/runs/6385143972
and https://github.com/googlemaps/android-maps-ktx/actions/runs/6385134681

Duplicate package name build warning

Building my app with the 2 dependencies below (using the current releases) causes build warnings. Please find a way to eliminate the warnings. Thanks.

Environment details

com.google.maps.android:maps-utils-ktx:3.0.0, com.google.maps.android:android-maps-utils:2.2.2

Task :app:processFastDebugMainManifest
[com.google.maps.android:maps-utils-ktx:3.0.0] /Users/me/.gradle/caches/transforms-3/ff18f3a8e16af67bd303501ad035d84c/transformed/jetified-maps-utils-ktx-3.0.0/AndroidManifest.xml Warning:
Package name 'com.google.maps.android' used in: com.google.maps.android:maps-utils-ktx:3.0.0, com.google.maps.android:android-maps-utils:2.2.2.

Add Kotlin KSerializer for LatLng

Is your feature request related to a problem? Please describe.
In my fairly pure Kotlin app I need to persist various types of data to disk, including List<LatLng>. I am switching to Kotlin serialization to do this, as it provides a straightforward framework that has recently seen a stable release. For now I intend to use stable Json-based Kotlin serialization, but may switch to a more compact format such as CBOR or protobuf as the respective library artifacts stabilize. LatLng from google-maps is a Java class and needs an external KSerializer to enable this.

Describe the solution you'd like
Add performant KSerializer implementation for LatLng that supports different Kotlin serialization formats, perhaps using the approach from https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#hand-written-composite-serializer

Describe alternatives you've considered
I am writing my own KSerializer based on https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#composite-serializer-via-surrogate. It is not as performant as the suggested hand-written composite serializer approach. It seems unnecessary for app developers to reinvent the wheel - LatLng is essentially a POJO that lends itself to serialization.

Unresolved reference: ClusterManager when using the Kotlin library for maps utilities

Hello

I'm trying to use the Google Maps Utilities Library for Kotlin to use marker clustering.

I added these two lines to my build.gradle file:

implementation 'com.google.maps.android:maps-utils-ktx:3.1.0'
implementation 'com.google.maps.android:android-maps-utils:2.2.6'

Then I'm trying to create a ClusterManager in MainActivity:

private lateinit var clusterManager: ClusterManager

I am getting the error :

Unresolved reference: ClusterManager

If I downgrade the utilities library to version 2.2.5 the error disappears and everything works but I get another error, something to do with marker collection setOnInfoWindowAdapter.

Please help.

Add support for StreetViewUtil

Recently StreetViewUtil was added to android-maps-utils (googlemaps/android-maps-utils#1200 published as v3.5.0). It was implemented with Kotlin coroutines, so I'm not sure if we need any extensions for it to be used with Kotlin, but as people are loading maps-utils-ktx for idiomatic Kotlin support of the utilities, I'm opening this issue in case anything needs to be added to this library to pull in the utility.

Support KTX for V3 Beta

Is your feature request related to a problem? Please describe.
The KTX library at the moment is only for the Google Play Services SDK and not the standalone V3 beta. The standalone V3 library should also be supported.

Describe the solution you'd like
Add an additional module called maps-v3-ktx that uses Maps V3 beta instead of Maps on Play Services.

Describe alternatives you've considered
N/A

Additional context
N/A

Allow customization of return type when using markerClickEvents() and myLocationButtonClickEvents()

Is your feature request related to a problem? Please describe.
Currently, using the markerClickEvents() and myLocationButtonClickEvents() APIs cannot customize the behavior when a marker or when the blue dot is tapped. That is, the default behavior of centering the map on the marker/blue dot (and additionally displaying an info window for a marker) will always occur.

Describe the solution you'd like
Customization of this behavior should be achievable by passing in an optional lambda to one of those methods.

For example:

googleMap.markerClickEvents { marker ->
    // Override default behavior
    return false
}.collect {
    // ...
}

Describe alternatives you've considered
Do nothing.

Additional context
See #162 (comment)

Add Kotlin Flow extensions to maps-ktx and maps-v3-ktx

Overview

This is a tracking bug for adding Kotlin Flow support to methods within the maps-ktx and maps-v3-ktx packages where applicable.

Background

Version 2.1.0 of the KTX library added support for Kotlin flow through the introduction of the method cameraEvents(). As a continuation to this work, this issue is for adding extension methods returning Kotlin flows for methods that can be modeled as such. For example, set listener methods (e.g. setOnCameraIdleListener(), setOnMapClickListener(), and so on) are good candidates.

Design

While cameraEvents() added support for Kotlin flow, this method wrapped several set listener methods and should be improved upon to aid in predictability for the Kotlin flow extension APIs. Specifically, wrapped methods should have a unique Kotlin flow API. In other words, the relationship between the extended method and the extension methods should be one-to-one, and not one-to-many. Since cameraEvents() does not comply to this design, it should be removed or marked as deprecated in favor of the API convention described here.

Method Naming

  • The setOn prefix should be dropped as well as the Listener suffix. Additionally, Events should be added as a suffix
    • Examples:
      • setOnCameraIdleListener()cameraIdleEvents()
      • setOnMapClickListener()mapClickEvents()

Developing

  • Pull requests should be done against the feature branch kotlin-flow
  • Pull requests should be kept small (one or few extension methods only), as well as an update to the sample app (a nice-to-have)
  • Refer to #113 as an example

Classes to Extend

  • GoogleMap
  • StreetViewPanorama

Contributing

Thinking of contributing? Awesome! Leave a comment below on what you'd like to add/work on so it's accounted for or any feedback on the design if you have any.

Add coroutine version of MapsInitializer.initialize()

Is your feature request related to a problem? Please describe.
Need to control Map renderer from coroutines-based environment

Describe the solution you'd like
Would like to use MapsInitializer.initialize(preferredRenderer) from a coroutine. Akin to MapView.awaitMap() to retrieve GoogleMap object. Needs to return the chosen Renderer or throw exception

Describe alternatives you've considered
Roll my own

Marker click listener doesn't work

####Issue:
Google Maps Marker click listener callback doesn't return

Environment details

Android version: 10
Android SDK: 29
Kernel Version: 4.14.117-perf+
Battery: 57%
Locale: en_US
Uptime: 24:19:36 h
Model: GM1900
Internal Model: 2007240000
Architecture: aarch64
Number of Cores: 8
Free disk space: 144.20 GB
Free RAM: 148.61 MB
Total memory: 7.30 GB
Available memory: 1.90 GB
Threshold memory: 216.00 MB
Low memory: false

Steps to reproduce

  1. Start map and load markers
  2. Click on any map marker visible

Expose API that uses Kotlin Flow to listen to marker events.

Is your feature request related to a problem? Please describe.
N/A

Describe the solution you'd like
This API would emulate the cameraEvents() API but emit marker related events.

Event types:

sealed class MarkerEvent
data class MarkerClickEvent(val marker: Marker) : MarkerEvent()
enum class MarkerDragType {
  START, DRAG, END
}
data class MarkerDragEvent(val marker: Marker, val type: MarkerDragType) : MarkerEvent()

Usage:

map.markerEvents().collect { event: MarkerEvent ->
  // do something
}

Describe alternatives you've considered
N/A

Additional context
See the cameraEvents() API

SDK v3 is not properly using AndroidX as it still depends on support library dependencies

The following appears when running ./gradlew :some-module:dependencies on a module that depends on the Google Maps SDK for Android v3 (3.1.0-beta):

EhB1Bs3VgAAZygJ

That means many apps pay a high build time price because they need to keep jetifier because of Google Maps still not being properly migrated as it depends on support libraries instead of AndroidX.

Please, make fixing this a top priority, it affects developers in the wild, not even counting the quiet ones: https://twitter.com/chris_h_codes/status/1300985936377868289?s=20

Cluster manager clicks listeners not working

When we use ClusterManager with KmlLayer, then setOnClusterClickListener and setOnClusterItemClickListener don`t handle any clicks. The reason in MarkerManager method onMarkerClick

Collection collection = mAllObjects.get(marker);

mAllObjects have only markers from KML file and ignore ClusterManager objects

Environment details

Library versions: maps-ktx:3.1.0, maps-utils-ktx:3.1.0

Steps to reproduce

  1. create map with kml layer and cluster manager with few markers
  2. try to handle click to cluster or cluster item

Typo in Repository description.

Sorry simple issues.

I found typo at Repository description.

Kotin extensions (KTX)

I think better than ‘Kotlin extensions’

Add GitHub release for version 3.3.0

Hello, I can see that there's a version 3.3.0 on Maven Central, but there's currently no entry in GitHub release telling us what the changes are.

Enable Travis builds

Enable Travis builds so that a build gets triggered on master. Enable GitHub checks to run Travis on new PRs, too.

Problem adding this library as a dependency

There is an issue with including this library by itself where classes are not able to be found at runtime. Stacktrace:

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.maps.android.SphericalUtil" on path: DexPathList[[zip file "/data/app/com.google.codelabs.findlocalplacesinar-IlY-Zx_cOMFwQ5RPtmGgug==/base.apk"],nativeLibraryDirectories=[/data/app/com.google.codelabs.findlocalplacesinar-IlY-Zx_cOMFwQ5RPtmGgug==/lib/x86, /data/app/com.google.codelabs.findlocalplacesinar-IlY-Zx_cOMFwQ5RPtmGgug==/base.apk!/lib/x86, /system/lib, /system/product/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)

My build.gradle looks like this:

dependencies {
    implementation 'com.google.maps.android:maps-utils-ktx:0.1.1'
}

PR #10 was meant to solve this but looks like there are still issues.

awaitMap can prevent cancellation forever, triggering memory leaks or suspending deadlocks

The awaitMap() extension function for SupportMapFragment uses the non cancellable suspendCoroutine function from the kotlin.coroutines package, so if the map is never shown, it'll never resume, even if cancelled.

The solution is to use suspendCancellationCoroutine from the kotlinx.coroutines package, even if there's no way to unregister the underlying callback in the current Google Maps API for Android.

It's better than what we have now because in the first case, the leaked objects can reach well beyond the SupportMapFragment, while in the second case, we only have a temporary leak (until the callback finally gets called, for example after the map is shown, or once the SupportMapFragment gets garbage collected).

Offer can throw, crashing the app on edge cases where cancellation happens in another thread

setOnCameraIdleListener { offer(CameraIdleEvent) }
setOnCameraMoveCanceledListener { offer(CameraMoveCanceledEvent) }
setOnCameraMoveListener { offer(CameraMoveEvent) }
setOnCameraMoveStartedListener { offer(CameraMoveStartedEvent(it)) }

Relevant issue with workaround that this library can use (with internal visibility): Kotlin/kotlinx.coroutines#974

Add MapView.awaitMap()

MapView is missing awaitMap(). It's available for MapFragment and SupportMapFragment, yet all three classes have getMapAsync(), which would seem to be the only prerequisite and works in the same manner for all three AFAIK.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.