Korzystasz z niestandardowych kafelków mapy z Google Map API V2 na Androida.?

10

Szukam sposobu na użycie niestandardowych kafelków mapy za pomocą Google Maps API V2 dla Androida.

Piszę aplikację, która utworzy własne mapy w czasie rzeczywistym z danymi pochodzącymi od robota.

Aplikacja musi pokazać operatorowi tę mapę. Operator musi wchodzić w interakcje z tą mapą, pozwalając punktom trasy itp.

Chcę użyć silnika GoogleMap, aby zrobić to samo, co ta strona:

http://cdn.mikecouturier.com/blog.mikecouturier.com/tilesgenerator/index.html

Problem polega na tym, że używał interfejsu API JavaScript, gdy chcę korzystać z interfejsu API Androida

Czy jest jakiś sposób na użycie niestandardowej mapy kafelków na Androidzie z Google Maps Engine?

Już zastanawiam się, jak korzystać z ArcGIS, ale wolę używać interfejsu API bez płacenia za licencję.

MonkeyJLuffy
źródło

Odpowiedzi:

8

Tak, możesz używać niestandardowych kafelków z Android Maps API v2 - możesz zobaczyć w pełni działający przykład w naszej aplikacji OpenTripPlanner dla Androida na Github . (Możesz także pobrać aplikację bezpośrednio z Google Play )

Obsługujemy następujących dostawców kafelków:

  • LyrkOpenStreetMap
  • MapQuestOpenStreetMap
  • Mapnik
  • CycleMap
  • Google (normalny, satelitarny, hybrydowy, teren)

Naszą klasę CustomUrlTileProvider można zobaczyć tutaj na Github , a także wkleiłem ją poniżej:

public class CustomUrlTileProvider extends UrlTileProvider {

    private String baseUrl;

    public CustomUrlTileProvider(int width, int height, String url) {
        super(width, height);
        this.baseUrl = url;
    }

    @Override
    public URL getTileUrl(int x, int y, int zoom) {
        try {
            return new URL(baseUrl.replace("{z}", "" + zoom).replace("{x}", "" + x)
                    .replace("{y}", "" + y));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

A oto kod, który przełącza się między dostawcami kafelków mapy, w zależności od preferencji użytkownika:

/**
 * Changes the tiles used to display the map and sets max zoom level.
 *
 * @param overlayString tiles URL for custom tiles or description for
 *                      Google ones
 */
public void updateOverlay(String overlayString) {
    int tile_width = OTPApp.CUSTOM_MAP_TILE_SMALL_WIDTH;
    int tile_height = OTPApp.CUSTOM_MAP_TILE_SMALL_HEIGHT;

    if (overlayString == null) {
        overlayString = mPrefs.getString(OTPApp.PREFERENCE_KEY_MAP_TILE_SOURCE,
                mApplicationContext.getResources()
                        .getString(R.string.map_tiles_default_server));
    }
    if (mSelectedTileOverlay != null) {
        mSelectedTileOverlay.remove();
    }
    if (overlayString.startsWith(OTPApp.MAP_TILE_GOOGLE)) {
        int mapType = GoogleMap.MAP_TYPE_NORMAL;

        if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_HYBRID)) {
            mapType = GoogleMap.MAP_TYPE_HYBRID;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_NORMAL)) {
            mapType = GoogleMap.MAP_TYPE_NORMAL;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_TERRAIN)) {
            mapType = GoogleMap.MAP_TYPE_TERRAIN;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_SATELLITE)) {
            mapType = GoogleMap.MAP_TYPE_SATELLITE;
        }
        mMap.setMapType(mapType);
        mMaxZoomLevel = mMap.getMaxZoomLevel();
    } else {
        if (overlayString.equals(getResources().getString(R.string.tiles_mapnik))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_mapnik_max_zoom);
        } else if (overlayString.equals(getResources().getString(R.string.tiles_lyrk))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_lyrk_max_zoom);
            tile_width = OTPApp.CUSTOM_MAP_TILE_BIG_WIDTH;
            tile_height = OTPApp.CUSTOM_MAP_TILE_BIG_HEIGHT;
        } else {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_maquest_max_zoom);
        }

        mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
        CustomUrlTileProvider mTileProvider = new CustomUrlTileProvider(
                tile_width,
                tile_height, overlayString);
        mSelectedTileOverlay = mMap.addTileOverlay(
                new TileOverlayOptions().tileProvider(mTileProvider)
                        .zIndex(OTPApp.CUSTOM_MAP_TILE_Z_INDEX));

        if (mMap.getCameraPosition().zoom > mMaxZoomLevel) {
            mMap.moveCamera(CameraUpdateFactory.zoomTo(mMaxZoomLevel));
        }
    }
}

Oto zrzut ekranu kafelków MapQuest OpenStreetMap: wprowadź opis zdjęcia tutaj

Aby uzyskać więcej informacji na temat tworzenia własnych kafelków, zobacz dokumentację Google dla TileOverlay, a także wiki OpenStreetMap dla „Tworzenie własnych kafelków” .

W szczególności dokumentacja Google mówi:

Zwróć uwagę, że świat jest rzutowany za pomocą projekcji Mercator (patrz Wikipedia) z lewą (zachodnią) stroną mapy odpowiadającą -180 stopniom długości geograficznej i prawą (wschodnią) stroną mapy odpowiadającą 180 stopniom długości geograficznej. Aby mapa była kwadratowa, górna (północna) strona mapy odpowiada 85,0511 stopni szerokości geograficznej, a dolna (południowa) strona mapy odpowiada -85.0511 stopni szerokości geograficznej. Obszary poza tym zakresem szerokości geograficznej nie są renderowane.

Na każdym poziomie powiększenia mapa jest podzielona na kafelki, a tylko kafelki pokrywające ekran są pobierane i renderowane. Każdy kafelek jest kwadratowy, a mapa jest podzielona na kafelki w następujący sposób:

  • Na poziomie powiększenia 0 jeden kafelek reprezentuje cały świat. Współrzędne tego kafelka to (x, y) = (0, 0).

  • Na poziomie powiększenia 1 świat jest podzielony na 4 płytki ułożone w siatkę 2 x 2. ...

  • Na poziomie powiększenia N świat jest podzielony na 4N kafelki ułożone w siatkę 2N x 2N.

Pamiętaj, że minimalny poziom powiększenia obsługiwany przez aparat (który może zależeć od różnych czynników) to GoogleMap.getMinZoomLevel, a maksymalny poziom powiększenia to GoogleMap.getMaxZoomLevel.

Współrzędne płytek są mierzone od lewego górnego (północno-zachodniego) rogu mapy. Na poziomie powiększenia N wartości x współrzędnych płytki wynoszą od 0 do 2N - 1 i zwiększają się z zachodu na wschód, a wartości y mieszczą się w zakresie od 0 do 2N - 1 i zwiększają się z północy na południe.

Sformatowane adresy URL używane w systemie OTP Android w odniesieniu do każdego dostawcy kafelków wyglądają następująco:

Tak więc dla powyższych dostawców obrazy kafelkowe są plikami PNG ułożonymi w strukturze katalogów wskazanej w dokumentacji Google. Postępowałbyś w podobnym formacie, aby stworzyć własne kafelki mapy hostowane na twoim serwerze. Pamiętaj, że te adresy URL / obrazy muszą być publicznie dostępne dla urządzenia mobilnego (tzn. Nie mogą być chronione hasłem).

Sean Barbeau
źródło
Dziękuję za poświęcony czas. Czy można używać w pełni utworzonych przeze mnie obrazów w osobistym repozytorium? Jaki jest format tego kafelka? A arborescencja?
MonkeyJLuffy,
@MonkeyJLuffy Właśnie dodałem trochę informacji na dole mojej odpowiedzi. Daj mi znać, jeśli po przeczytaniu nadal masz pytania.
Sean Barbeau
1

Najbardziej rozbudowane rozwiązanie, jakie znalazłem, znajduje się w tej odpowiedzi StackOverflow :

Zasadniczo musisz wdrożyć własnego TileProvider i używać go jako TileOverlay

W kilku aplikacjach użyliśmy tego rodzaju warstwy do wyświetlenia kafelków na mapie, ale okazało się, że kafelki zajmowały dużo miejsca. Dlatego przeszliśmy na używanie mbtiles i tej biblioteki do wyświetlania danych z mbtiles na mapie.

Devdatta Tengshe
źródło