Soluzione per l'app per mappe Android con utilizzo offline?


14

Sono alla ricerca di un modo per sviluppare un'app per Android con mappe incorporate in grado di funzionare senza una connessione Internet (cioè posso ottenere i riquadri della mappa stradale aperta per l'uso offline?).

Ho già sviluppato app Web utilizzando Google Maps API V3. Ho bisogno di una risposta generale come specifica. Sto cercando di trovare i concetti e le tecnologie che devo imparare :)

(Nel frattempo ho trovato osmdroid. Funziona offline?)


Questo non risponde davvero alla domanda. Se hai una domanda diversa, puoi farla facendo clic su Poni domanda . Puoi anche aggiungere una taglia per attirare più attenzione a questa domanda una volta che hai abbastanza reputazione .
Jason Scheirer,

Osmand non consente di importare mappe personalizzate su richiesta dell'utente, ma consente di scaricare mappe direttamente dall'app per l'utilizzo offline. Come nel mio caso, devo sovrapporre toposheet (mappe raster) che sono stati convertiti in * .kmz. Il mio requisito è per l'utilizzo offline. Sto cercando una guida adeguata per sviluppare tale applicazione Android di supporto di mappe offline.
Surap

Questo in realtà non risponde alla domanda originale su dove e come ottenere mappe per l'uso offline.
MaryBeth,

Questo non risponde davvero alla domanda. Se hai una domanda diversa, puoi farla facendo clic su Poni domanda . Puoi anche aggiungere una taglia per attirare più attenzione a questa domanda una volta che hai abbastanza reputazione . - Dalla recensione
John Powell,

Risposte:



13

Ho creato una mappa offline usando l'SDK Android ESRI e un layer di piastrelle personalizzato. Ho usato un server ArcGIS per generare una cache di mappe basata su tile, quindi ho inserito quelle piastrelle in un database SQLite e le ho interrogate in base a riga e colonna da lì. Funziona benissimo e se hai bisogno di mappe personalizzate end-to-end, è un metodo molto utilizzabile.

package com.main.utilinspect;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParser;

import android.content.Context;
import android.util.Log;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.esri.core.internal.c.d;
import com.esri.core.internal.c.h;
import com.esri.core.internal.c.l;

import com.esri.android.map.TiledServiceLayer;

public class OfflineDbTiledLayer extends TiledServiceLayer {

File workingDirectory;
String mapDefinition;
String databaseName;
private SQLiteDatabase database;
File blankImage;

byte[] blankImageBytes;

private final Object lock = new Object();


private static final String TAG = "OfflineTiledLayer";  


public OfflineDbTiledLayer(Context paramContext, File workingDirectory, String mapDefinition, String databaseName)  {
    super("required");
    this.workingDirectory = workingDirectory;
    this.mapDefinition = mapDefinition;
    this.databaseName = databaseName;

    String databasePath = workingDirectory.getAbsolutePath() + File.separator + databaseName;

    this.database = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 

    this.blankImage = new File(workingDirectory.getAbsolutePath() + File.separator + "blank.png");

    RandomAccessFile raFile = null;

    try {
        raFile = new RandomAccessFile(this.blankImage, "r");

        blankImageBytes = new byte[(int) raFile.length()];
        raFile.readFully(blankImageBytes);

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       
    finally {
        if(raFile != null) {
            try {
                raFile.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }   

    h h1 = null;

    try
    {

    JsonParser paramJsonParser = new JsonFactory()
    .createJsonParser(new File(workingDirectory.getAbsolutePath() + File.separator + mapDefinition));
    paramJsonParser.nextToken();    

    h1 = h.a(paramJsonParser, "test");
    }
    catch(Exception ex){

    }       


    setFullExtent(h1.f());      
    setDefaultSpatialReference(h1.c());
    setInitialExtent(h1.e());

    l l1;
    List list;
    int i;
    double ad[] = new double[i = (list = (l1 = h1.d()).h).size()];
    double ad1[] = new double[i];
    for(int j = 0; j < list.size(); j++)
    {
        ad[j] = ((d)list.get(j)).b();
        ad1[j] = ((d)list.get(j)).a();
    }

    setTileInfo(new com.esri.android.map.TiledServiceLayer.TileInfo(l1.f, ad, ad1, i, l1.c, l1.b, l1.a));

    super.initLayer();
    return;     
}   

private void openDatabase(){
    if(!database.isOpen()){
        String databasePath = workingDirectory.getAbsolutePath() + File.separator + databaseName;
        this.database = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
    }
}

private void closeDatabase(){
    if(database.isOpen()){
        this.database.close();
    }
}

@Override
protected byte[] getTile(int level, int column, int row) throws Exception {
    byte[] tileImage;       

    Log.i(TAG, "getTile");

    Log.i(TAG, "getTile - retrieving tile");            

    synchronized(lock) {

        Log.i(TAG, "getTile - entered synchronized block");

        openDatabase();     

        // First check to see if the tile exists in the database
        Cursor tileCursor = database.rawQuery("SELECT image FROM tiles WHERE level = " + Integer.toString(level) + " AND row = " + Integer.toString(row) + " AND column = " + Integer.toString(column), null);

        if(tileCursor != null && tileCursor.getCount() > 0) {
            tileCursor.moveToFirst();
            tileImage = tileCursor.getBlob(0);
            Log.i(TAG, "getTile - tile found, returning image");                        
        }
        else {
            // The tile does not exist in the database, read the blank placeholder tile and serve it
            tileImage = blankImageBytes;
            Log.i(TAG, "getTile - tile not found returning blank");
        }   

        tileCursor.close();     
        this.database.close();
    }

    Log.i(TAG, "getTile - exited synchronized block");

    return tileImage;   
}

}


Puoi per favore condividere un po 'di codice?
Greg

Ho aggiunto la mia classe di livelli personalizzata che fa il lavoro.
eptiliom

7

Ho sviluppato un'applicazione con mappe offline per Android. L'unico strumento gratuito che vorresti usare è OSMDroid, altrimenti ESRI. L'API OSMDroid è identica a quella di Google, quindi nel caso tu voglia passare da uno all'altro, è un gioco da ragazzi.

Dai un'occhiata a questo post , con un esempio di come integrare Google Maps in OSMDroid (ti dà anche un'idea di come usarlo in generale).


2

Esiste una fantastica app chiamata xGPS per iPhone e altri dispositivi. Potresti voler esaminare questo per ottenere idee perché consente agli utenti di pre-memorizzare nella cache le mappe di cui avranno bisogno. Lo uso quando sono in profondità nella boscaglia in Africa, nelle Everglades della Florida, in barca o ovunque non ho copertura per il cellulare. Memorizzerò in cache le mappe prima del mio viaggio e quindi posso utilizzare il GPS sul mio iPhone normalmente senza INTERNET.

Fondamentalmente ciò che fanno xGPS e ciò che vorresti fare è memorizzare nella cache i riquadri delle mappe localmente sul tuo telefono. Lo spazio su questi telefoni cellulari è limitato. Sì, anche se sul telefono hai 32 GB, potrebbe essere sufficiente memorizzare nella cache un piccolo paese a tutti i livelli di zoom (scale). Nessuno di questi telefoni (a meno che non sia collegato in qualche modo a una memoria esterna) disporrà di spazio sufficiente per memorizzare nella cache il mondo a tutti i livelli di zoom. Immagino che ciò richiederebbe petabyte di spazio di archiviazione.

Quindi devi essere in grado di chiedere al tuo utente di memorizzare nella cache le "regioni" o le mappe quando è online in modo da poterle utilizzare offline. Con xGPS sono in grado di disegnare un poligono sulla mia regione di interesse e specificare quali livelli di zoom voglio memorizzare nella cache. Quindi inizierà a scaricare tutto per me sul mio telefono, dal telefono stesso o da un programma sul mio computer. Quindi c'è un pulsante sull'app che mi permette di passare alla modalità "offline" quando perdo la connettività Internet.


2

Prova a utilizzare NextGIS Mobile SDK. La modalità online / offline include la modifica e la sincronizzazione automatica con il server (NextGIS Web). Livelli raster e vettoriali, moduli di input personalizzati, supporto per tutti i tipi di geometria.

Un'applicazione di esempio NextGIS Mobile è disponibile nel Google Play Store: https://play.google.com/store/apps/details?id=com.nextgis.mobile

Le fonti sono qui: https://github.com/nextgis/android_gisapp

Documentazione: http://docs.nextgis.com/docs_ngmobile/source/toc.html

Un'altra semplice applicazione è qui: https://github.com/nextgis/android_muni_gisconf

Documentazione SDK: http://docs.nextgis.com/ngmobile_dev/toc.html


1

È disponibile il supporto completo per le mappe offline con l'attuale versione di ArcGIS Android SDK. Questo esempio ti mostrerà come lavorare con un pacchetto di tessere locale come mappa di base e perseverare le funzioni online con le funzioni offline da cui è possibile modificare. Ho una sintesi disponibile anche su Github per un riferimento semplificato.


1

Suggerisco di dare un'occhiata all'SDK delle mappe 3D Nutiteq che ha funzionalità offline e interessanti extra come il supporto 3D. È realizzato da una società di sviluppo specializzata dietro di esso, quindi ha un supporto commerciale dedicato e una maggiore flessibilità rispetto ai grandi fornitori. Disclaimer: ne sono uno sviluppatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.