p-lr / MapCompose

A fast, memory efficient Jetpack Compose library to display tiled maps, with support for markers, paths, and rotation.
Apache License 2.0
224 stars 20 forks source link

Can I use it with OSM? #62

Closed mtangoo closed 2 years ago

mtangoo commented 2 years ago

I was searching for a Google map SDK alternative and found this library but am confused as to how I can use it with an OSM.

can someone share any insight? I have read readme many times but cannot understand how I can make it work with OSM.

note I was finding something that works with Openstreet map and Compose

nachtien commented 2 years ago

It looks like it would work since osm gives 256x256, try plugging the url in the sample app to test it out: https://tile.openstreetmap.org/${z}/${x}/${y}.png

mtangoo commented 2 years ago

Sorry for late reply and thanks for the comment. Am going to test it and see!

basurahan commented 2 years ago

did you make it work?

p-lr commented 2 years ago

I can assure you that it works. I'm using it in my trekking app

basurahan commented 2 years ago

Thanks for sharing your app now I can have a reference

ThomasBernard03 commented 1 year ago

I get the error file not found when I use the OSM url but the image is displayed correctly when I click on the link: https:/tile.openstreetmap.org/18/131069/131070.png

In my Viewmodel :

val tileStreamProvider = TileStreamProvider { row, col, zoomLvl ->
    FileInputStream(File("https://tile.openstreetmap.org/${zoomLvl}/${row}/${col}.png")) // or it can be a remote HTTP fetch
}

val mapSize = 67108864
val state: MapState by mutableStateOf(
    MapState(levelCount = 19, fullWidth = mapSize, fullHeight = mapSize, workerCount = 1).apply {
        addLayer(tileStreamProvider)
        enableRotation()
    }
)

In my screen :

MapUI(
    state = viewModel.state,
    modifier = Modifier.weight(1f)
)

Am I implementing it the right way, or am I missing something?

ThomasBernard03 commented 1 year ago

I also try with this method but not working...


    val tileStreamProvider = TileStreamProvider { row, col, zoomLvl ->
        try {
            val url = "http://tile.openstreetmap.org/$zoomLvl/$col/$row.png"
            val connection = withContext(Dispatchers.Main) {
                URL(url).openConnection()
            } as HttpURLConnection
            connection.inputStream
        } catch (e: Exception) {
            Timber.tag("OSM").e(e)
            null
        }
    }
Nohus commented 1 year ago

There seem to me multiple issues with that code fragment. The URL schema is different, I think you want it to be https. You are also doing networking on the main thread, which is not allowed on Android. "Not working" can really mean anything from the app crashing to the map rendering incorrectly, what's actually wrong or what error are you getting?

ThomasBernard03 commented 1 year ago

Yes, I'm sorry, I had actually tested on the Main thread and in HTTP because I didn't know where the problem was coming from. Here is the correct code:

val tileStreamProvider = TileStreamProvider { row, col, zoomLvl ->
    try {
        val url = "https://tile.openstreetmap.org/$zoomLvl/$col/$row.png"
        val connection = withContext(Dispatchers.IO) {
            URL(url).openConnection()
        } as HttpURLConnection
        connection.inputStream
    } catch (e: Exception) {
        Timber.tag("OSM").e(e)
        null
    }
}

For each http request I get this error :

java.io.FileNotFoundException: https://tile.openstreetmap.org/18/131072/131073.png at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:255) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30) at fr.ubismart.pve.ui.fps.ui.screen.ParkingControl.ParkingControlViewModel$tileStreamProvider$1.getTileStream(ParkingControlViewModel.kt:37) at fr.ubismart.pve.ui.fps.ui.screen.ParkingControl.ParkingControlViewModel$tileStreamProvider$1$getTileStream$1.invokeSuspend(Unknown Source:15) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923)

And I have a black/empty MapUI
Nohus commented 1 year ago

I think you may be missing a connection.connect(), try something like this:

TileStreamProvider { row, col, zoomLvl ->
    try {
        val url = URL("https://tile.openstreetmap.org/$zoomLvl/$col/$row.png")
        val connection = url.openConnection() as HttpURLConnection
        connection.doInput = true
        connection.connect()
        BufferedInputStream(connection.inputStream)
    } catch (e: Exception) {
        Timber.tag("OSM").e(e)
        null
    }
}
ThomasBernard03 commented 1 year ago

No same error ....

java.io.FileNotFoundException: https://tile.openstreetmap.org/18/131073/131069.png at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:255) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30) at fr.ubismart.pve.ui.fps.ui.screen.ParkingControl.ParkingControlViewModel$tileStreamProvider$1.getTileStream(ParkingControlViewModel.kt:38) at ovh.plrapps.mapcompose.core.TileCollector$worker$1.invokeSuspend$getBitmap$6(TileCollector.kt:121) at ovh.plrapps.mapcompose.core.TileCollector$worker$1.access$invokeSuspend$getBitmap$6(Unknown Source:0) at ovh.plrapps.mapcompose.core.TileCollector$worker$1$bitmapForLayers$1$1.invokeSuspend(TileCollector.kt:140) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923) 2023-07-07 14:23:11.235 5887-18137 OSM fr.ubismart.pve E java.io.FileNotFoundException: https://tile.openstreetmap.org/18/131070/131072.png at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:255) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30) at fr.ubismart.pve.ui.fps.ui.screen.ParkingControl.ParkingControlViewModel$tileStreamProvider$1.getTileStream(ParkingControlViewModel.kt:38) at ovh.plrapps.mapcompose.core.TileCollector$worker$1.invokeSuspend$getBitmap$6(TileCollector.kt:121) at ovh.plrapps.mapcompose.core.TileCollector$worker$1.access$invokeSuspend$getBitmap$6(Unknown Source:0) at ovh.plrapps.mapcompose.core.TileCollector$worker$1$bitmapForLayers$1$1.invokeSuspend(TileCollector.kt:140) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923)

Nohus commented 1 year ago

FileNotFoundException can be thrown by HttpURLConnection for different reasons. Try logging getResponseCode() from it to see what's the actual server response.

mtangoo commented 1 year ago

did you make it work?

Sorry I didn't try as we had to start with Google maps to speed up things. I will come back to it again!

ThomasBernard03 commented 1 year ago

It return 403 :(

Nohus commented 1 year ago

So it's not really a problem with your code, the service is just blocking you, which could be for any reason. Maybe have a look here: https://operations.osmfoundation.org/policies/tiles/

mtangoo commented 1 year ago

It return 403 :(

OSM discourages use of it for your app. You need to setup your own OSM like server to serve your app

ThomasBernard03 commented 1 year ago

Oh by switching on France servers it works !