maplibre / maplibre-plugins-android

MapLibre Native for Android Plugins
https://maplibre.org/
BSD 2-Clause "Simplified" License
18 stars 22 forks source link

MapLibre Android: Using textField on SymbolLayer/SymbolOptions makes the symbol invisible. #60

Open EllisGlaeser opened 1 month ago

EllisGlaeser commented 1 month ago

Using the SymbolManager or SymbolLayer to display symbols is working fine, but as soon as I add the textField property, it breaks the symbol and it no longer appears.

I have read several past issues similar to this where people have said it's related to the font, but I just want to use the default font and can't even figure out a way to change where the font is coming from, just the textFont property that wants the font name.

I am using the default Style Builder:

mapboxMap.setStyle(Style.Builder())

This is how I'm adding the source & layer (from a custom waypoint class):

val identifier = waypoint.icon().id()
val feature = Feature.fromGeometry(Point.fromLngLat(waypoint.backing.longitude, waypoint.backing.latitude))
val point = FeatureCollection.fromFeature(feature)
val source = GeoJsonSource(identifier, point)
val symbolLayer = SymbolLayer(GPMapLayers.WAYPOINTS.layerID + waypoint.uuid, identifier).withProperties(
      PropertyFactory.iconImage(identifier),
      PropertyFactory.textField(waypoint.title()),
      PropertyFactory.textSize(12f),
      PropertyFactory.textColor("#000000")
)

style.addSource(source)
style.addLayer(symbolLayer)

I have also tried passing "sans-serif" (the default Android font as well as the default font for MapLibre Android), as well as Open Sans Regular & Arial Unicode MS Regular, the defaults for MapBox.

I was using an older version of MapLibre Android, but updated to Version 11 to try and fix the problem. With the older version, I was using a SymbolManager to add the symbols to the map, but it appears MapLibre 11 doesn't support the Annotation Plugin. Is this the case, or am I missing something?

louwers commented 1 month ago

Could you share the snippet that doesn't work?

We released a new version of the Annotation plugin that is compatible with MapLibre Native Android 11.0.0.

EllisGlaeser commented 1 month ago

Where I used to be using the Symbol Manager, it won't let me, saying the SymbolManager needs a MapboxMap as a param instead of MapLibreMap.

val symbolManager = SymbolManager(mapView, mapLibreMap, style)
symbolManager.iconAllowOverlap = true
symbolManager.textAllowOverlap = true
symbolManager.iconIgnorePlacement = true
symbolManager.addDragListener(this)
this.symbolManager = symbolManager

What's the new version of the plugin? I see this, but that doesn't get me the SymbolManager. Is this something different?: implementation 'com.maplibre.maplibresdk:maplibre-android-plugin-annotation-v9:0.9.0' from https://github.com/maplibre/maplibre-plugins-android/tree/main/plugin-annotation

This is what I have currently: implementation 'org.maplibre.gl:android-plugin-annotation-v9:1.0.0'

The code for the symbol layer works just fine if I take out the textField, but as soon as I add that the symbol disappears completely.

louwers commented 1 month ago

Try using the latest version from Maven Central (3.0.0) https://central.sonatype.com/artifact/org.maplibre.gl/android-plugin-annotation-v9

EllisGlaeser commented 1 month ago

Okay, I updated to that version and I get the SymbolManager again, but adding the textField still prevents the symbol from appearing on the map.

This is the simplest way I've tried it:

var symbol = SymbolOptions()
          withLatLng(waypoint.latLng())
          .withIconImage(identifier)
          .withIconSize(scale)
          .withTextField(waypoint.title())
symbolMgr.create(symbol)
EllisGlaeser commented 1 month ago

Do you have any other ideas? Is this just a bug in the code, or is there anything else I can do to make it work?

alminav commented 3 weeks ago

Have the same problem with org.maplibre.gl:android-sdk:11.0.0

louwers commented 3 weeks ago

I am unable to reproduce this. When I edit BulkSymbolActivity.java and use withTextField

            options.add(new SymbolOptions()
                .withGeometry((Point) feature.geometry())
                .withIconImage(IMAGE_ID_FIRE_HYDRANT)
                .withTextField("Test")

The text label shows up as expected.

Could you try to reproduce this problem using the demo app in this repo?

image

EllisGlaeser commented 3 weeks ago

Yes, the sample app works. My implementation uses Kotlin + Jetpack Compose and hosts the MapView in an AndroidView. Is that the difference? I tried to create a sample version of what I'm doing but I'm having trouble getting a map style to load like how the sample app does.

EllisGlaeser commented 1 week ago

It seems like this is related to how I am loading the map. We have a selection of maps that we load by adding a custom Source class via a RasterLayer like this:

val mbSource = this.activeMBSource
if (mbSource != null) {
     val s = mbSource.maplibreSource
     val activeMapSource = style.getSource(s.id)

 // If mbSource contains raster tiles
     val rasterLayer = RasterLayer("basemap_layer_id", mbSource.sourceId)
      rasterLayer.maxZoom = mbSource.mapSource.maxZoomLevel.toFloat()
       style.addLayer(rasterLayer)

   // If mbSource contains vector tiles
       val vectorLayer = LineLayer("vector_layer_id", mbSource.sourceId)
       style.addLayer(vectorLayer)
}

As soon as I switched to a MapTiler map like this, the waypoint title worked just fine:

val mapId = "streets-v2"
val styleUrl = "https://api.maptiler.com/maps/$mapId/style.json?key=$key"
EllisGlaeser commented 1 week ago

Does the textField only work when you're using vector maps? Here's a simple example you can try out to replicate it. In this case, the symbol doesn't appear even when the textField isn't there, which isn't the problem I'm having in my actual project, but I'm assuming they are related. Without the map source, the marker appears on the black screen, but once you add the raster source it doesn't show.

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MapLibre.getInstance(this)

        mapView = MapView(this)

        setContent {
            loadMap(mapView)
            MapLibreSymbolsExampleTheme {
                AndroidView(
                    {
                        mapView
                    }
                )
            }
        }
    }

    private fun loadMap(mapView: MapView) {
        mapView.getMapAsync { map ->
            map.setStyle(Style.Builder()) { style ->
                val sourceURL = "https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}"
                val source = RasterSource("usNat", TileSet("3.0.0", sourceURL))
                val sourceID = "usNat"

                val coordinate = LatLng(48.11166, 121.11486)

                val symbolManager = SymbolManager(mapView, map, style)
                val imgName = "Point"
                val bmp = BitmapFactory.decodeResource(this@MainActivity.resources, R.drawable.markerbrown)

                // Once you add the source, you can't see the image.
//                style.addSource(source)
                style.addLayer(RasterLayer("map-layer", sourceID))
                style.addImage(imgName, bmp)

                symbolManager.create(
                    SymbolOptions()
                        .withLatLng(coordinate)
                        .withIconImage(imgName)
                        .withIconSize(1f)
                        .withSymbolSortKey(1f)
                        // If you take out the text field, the marker appears.
//                        .withTextField(imgName)
                )

                map.cameraPosition = CameraPosition.Builder().target(coordinate).zoom(10.0).build()
            }
        }
    }
    implementation ("org.maplibre.gl:android-sdk:11.0.0")
    implementation("org.maplibre.gl:android-plugin-annotation-v9:3.0.0")

Here is the image I'm using:

markerbrown

alminav commented 1 week ago

I'm using GeoJson source val fileUri = "file://" + file.path val geojson = GeoJsonSource( fileName, URI(fileUri) ) loadedMapStyle.addSource(geojson)

Now I have another problem with android sdk 35, app crash:

D visibilityChanged oldVisibility=true newVisibility=false I Davey! duration=800ms; Flags=0, FrameTimelineVsyncId=457535, IntendedVsync=9545426079372, Vsync=9546159412676, InputEventId=0, HandleInputStart=9546170112000, AnimationStart=9546170128800, PerformTraversalsStart=9546170553700, DrawStart=9546173098000, FrameDeadline=9545476079370, FrameInterval=9546168752300, FrameStartTime=16666666, SyncQueued=9546175706200, SyncStart=9546175999600, IssueDrawCommandsStart=9546176303100, SwapBuffers=9546214247100, FrameCompleted=9546226744800, DequeueBufferDuration=26800, QueueBufferDuration=899300, GpuCompleted=9546226744800, SwapBuffersCompleted=9546215546300, DisplayPresentTime=0, CommandSubmissionCompleted=9546214247100, D app_time_stats: avg=107.19ms min=5.32ms max=820.12ms count=9 D app_time_stats: avg=123.08ms min=4.74ms max=735.12ms count=9 E terminating with uncaught exception of type mapbox::sqlite::Exception: unable to open database file A Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 16259 (MBTilesFileSour), pid 16149 (om.almica.oscim) D app_time_stats: avg=5.81ms min=1.57ms max=64.79ms count=55 A Cmdline: com.almica.oscim A pid: 16149, tid: 16259, name: MBTilesFileSour >>> com.almica.oscim <<< A #01 pc 0000000000a6efab /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #02 pc 0000000000a6f19e /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #03 pc 0000000000a6f052 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #04 pc 0000000000a6e755 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #05 pc 0000000000a6e6dc /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (__cxa_throw+108) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #06 pc 00000000009231b7 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #07 pc 00000000008ff48d /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #08 pc 00000000008fbe39 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #09 pc 0000000000903c14 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #10 pc 0000000000580946 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #11 pc 0000000000581cab /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #12 pc 00000000008dfe6b /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #13 pc 00000000008df25a /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #14 pc 00000000008df097 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #15 pc 0000000000902d49 /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0) A #16 pc 0000000000902b7b /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!libmaplibre.so (offset 0x85c000) (BuildId: 2e0f644b1edee2ad714fd9499988911277d951e0)

D Configuring clns-6 for other apk /system/framework/org.apache.http.legacy.jar. target_sdk_version=34, uses_libraries=ALL, library_path=/data/app/fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/lib/x86_64:/data/app/fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!/lib/x86_64, permitted_path=/data:/mnt/expand:/data/user/0/com.almica.oscim D Returning zygote-cached class loader: /system_ext/framework/androidx.window.extensions.jar D Returning zygote-cached class loader: /system_ext/framework/androidx.window.sidecar.jar W Unable to open '/data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/ base.dm': No such file or directory W Unable to open '/data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/ base.dm': No such file or directory D Configuring clns-7 for other apk /data/app/~~fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk. target_sdk_version=34, uses_libraries=, library_path=/data/app/fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/lib/x86_64:/data/app/fE5C1Ah-ajYhkUoO_Ne4Aw==/com.almica.oscim-bOGEnYonUsAzWREKnP4HTA==/base.apk!/lib/x86_64, permitted_path=/data:/mnt/expand:/data/user/0/com.almica.oscim V Currently set values for: V angle_gl_driver_selection_pkgs=[] V angle_gl_driver_selection_values=[] V Global.Settings values are invalid: number of packages: 0, number of values: 0 V Neither updatable production driver nor prerelease driver is supported. W Unknown dataspace 0 I Opening libGLESv1_CM_emulation.so I Opening libGLESv2_emulation.so W Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without... W Failed to initialize 101010-2 format, error = EGL_SUCCESS I mapper 4.x is not supported

Do you have any idea?

Am Di., 2. Juli 2024 um 19:16 Uhr schrieb EllisGlaeser < @.***>:

Does the textField only work when you're using vector maps? Here's a simple example you can try out to replicate it. In this case, the symbol doesn't appear even when the textField isn't there, which isn't the problem I'm having in my actual project, but I'm assuming they are related. Without the map source, the marker appears on the black screen, but once you add the raster source it doesn't show.

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)

    MapLibre.getInstance(this)

    mapView = MapView(this)

    setContent {
        loadMap(mapView)
        MapLibreSymbolsExampleTheme {
            AndroidView(
                {
                    mapView
                }
            )
        }
    }
}

private fun loadMap(mapView: MapView) {
    mapView.getMapAsync { map ->
        map.setStyle(Style.Builder()) { style ->
            val sourceURL = "https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}"
            val source = RasterSource("usNat", TileSet("3.0.0", sourceURL))
            val sourceID = "usNat"

            val coordinate = LatLng(48.11166, 121.11486)

            val symbolManager = SymbolManager(mapView, map, style)
            val imgName = "Point"
            val bmp = ***@***.***, R.drawable.markerbrown)

            // Once you add the source, you can't see the image.//                style.addSource(source)
            style.addLayer(RasterLayer("map-layer", sourceID))
            style.addImage(imgName, bmp)

            symbolManager.create(
                SymbolOptions()
                    .withLatLng(coordinate)
                    .withIconImage(imgName)
                    .withIconSize(1f)
                    .withSymbolSortKey(1f)
                    // If you take out the text field, the marker appears.//                        .withTextField(imgName)
            )

            map.cameraPosition = CameraPosition.Builder().target(coordinate).zoom(10.0).build()
        }
    }
}

implementation ("org.maplibre.gl:android-sdk:11.0.0")
implementation("org.maplibre.gl:android-plugin-annotation-v9:3.0.0")

— Reply to this email directly, view it on GitHub https://github.com/maplibre/maplibre-plugins-android/issues/60#issuecomment-2203880996, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACXMU2TMZJQE3ZBT5MP7R7TZKLN55AVCNFSM6AAAAABJMCEH2WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBTHA4DAOJZGY . You are receiving this because you commented.Message ID: @.***>