[Bug]: Local Filesystem raster tiles
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 2.9k
- Forks
- 947
- Avg merge
- 6d 37m
- Merged PRs (30d)
- 1
Description
Mapbox Implementation
Mapbox
Mapbox Version
default
Platform
Android
@rnmapbox/maps version
10.1.6
Standalone component to reproduce
import React, { useEffect} from 'react';
import Mapbox from '@rnmapbox/maps';
import { StyleSheet, View, Alert } from 'react-native';
import * as FileSystem from 'expo-file-system';
const styles = StyleSheet.create({
map: {
width: '100%',
height: '100%',
}
});
const CreateOfflineMaps = () => {
const TILE_FOLDER = `${FileSystem.documentDirectory}tiles`;
const MAP_URL = 'http://c.tile.openstreetmap.org';
useEffect(() => {
const test = async () => {
// check if a test png exists, if not then download them
const fileInfo = await FileSystem.getInfoAsync(`${TILE_FOLDER}/1/0/0.png`)
if (!fileInfo.exists) {
downloadTiles();
}
}
test();
}, []);
const downloadTiles = async () => {
// just a few top level tiles to test
const tiles = [{ x: 0, y: 0, z: 1 }, { x: 1, y: 1, z: 1 }, { x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 1 }, { x: 0, y: 1, z: 1 }];
// Create directory for tiles
for (const tile of tiles) {
const folder = `${TILE_FOLDER}/${tile.z}/${tile.x}`
await FileSystem.makeDirectoryAsync(folder, { intermediates: true })
}
// Download tiles in batches to avoid excessive promises in flight
const BATCH_SIZE = 100
let batch = []
for (const tile of tiles) {
const fetchUrl = `${MAP_URL}/${tile.z}/${tile.x}/${tile.y}.png`
const localLocation = `${TILE_FOLDER}/${tile.z}/${tile.x}/${tile.y}.png`
const tilePromise = FileSystem.downloadAsync(fetchUrl, localLocation)
batch.push(tilePromise)
if (batch.length >= BATCH_SIZE) {
await Promise.all(batch)
batch = []
}
}
await Promise.all(batch)
alert('Finished downloading tiles.')
}
// tile url here can be replace with "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png" and it works fine
const styleJSON = {
"version": 8,
"name": "Offline Test",
"sources": {
"offline": {
"type": "raster",
"tiles": [
`${FileSystem.documentDirectory}tiles/{z}/{x}/{y}.png`
]
}
},
"layers": [{
"id": "test",
"type": "raster",
"source": "offline",
}]
}
return (
<View style={styles.container}>
<Mapbox.MapView
style={styles.map}
styleJSON={JSON.stringify(styleJSON)}
>
</Mapbox.MapView>
</View>
);
}
export default CreateOfflineMaps
Observed behavior and steps to reproduce
If you allow the tiles to be downloaded, and reload or leave and re-enter this component, the app will crash on android (development build for expo).
Here are my relevant package versions (I'm using expo):
"@rnmapbox/maps": "^10.1.6",
"expo": "^49.0.21",
"expo-file-system": "~15.4.5",
"react": "18.2.0",
"react-native": "0.72.6",
Expected behavior
Should just show the map tiles
Notes / preliminary analysis
I don't get any errors from my terminal or anything really, it simply crashes. The code works fine if you replace the tile url with an online one like "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png" and it also works as expected with the downloaded tiles on iOS.
Additional links and references
I am trying to do something similar to what is done here and downloading tiles based on this tutorial (this part works great).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied standalone React Native component in an Android Expo development build, using the local raster tile URL and then the online URL for comparison. Reproduce the crash after reload or re-entering the component and inspect the Android failure; done means the downloaded tiles render without crashing, matching the iOS behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, javascript, react-native
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100