离线使用Android Map App的解决方案?


14

我正在寻找一种开发具有嵌入式地图的android应用程序的方法,该应用程序可以在没有互联网连接的情况下工作(即,我可以获取开放式街道地图的图块以供离线使用吗?)。

我之前通过使用Google Maps API v3开发了Web应用程序。我需要一个通用的答案作为一个具体的答案。我正在尝试找到我需要学习的概念和技术:)

(同时我发现了osmdroid。它可以离线工作吗?)


这并不能真正回答问题。如果您有其他问题,可以点击提问进行提问。一旦您有足够的声誉,您还可以悬赏以吸引更多对此问题的关注。
杰森·谢勒

Osmand不允许根据用户的意愿导入任何自定义地图,而仅允许直接从应用程序下载地图以供离线使用。与我的情况一样,我需要覆盖已转换为* .kmz的拓扑表(栅格地图)。我的要求是离线使用。我正在寻找开发此类离线地图支持android应用程序的适当指南。
surap '16

这并不能真正回答最初的问题,即从何处以及如何获取地图以供离线使用。
MaryBeth

这并不能真正回答问题。如果您有其他问题,可以点击提问进行提问。一旦您有足够的声誉,您还可以悬赏以吸引更多对此问题的关注。- 评论
约翰鲍威尔

Answers:



13

我使用ESRI Android SDK和自定义图块图层制作了离线地图。我使用ArcGIS Server生成了基于图块的地图缓存,然后将这些图块插入SQLite数据库并根据该行中的行和列对其进行查询。它非常有用,如果您需要端到端的自定义地图,这是一种非常有用的方法。

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;   
}

}


能否请您分享一些代码?
gregm 2013年

我添加了完成此工作的自定义图层类。
eptiliom

7

我已经为Android开发了带有离线地图的应用程序。您要使用的唯一免费工具是OSMDroid,否则使用ESRI。OSMDroid API与Google的API相同,因此,如果您要从一个切换到另一个,这很容易。

请查看这篇文章,其中提供了有关如何将Google Maps集成到OSMDroid的示例(它还为您提供了一般用法的想法)。


2

iPhone和其他设备有一个名为xGPS的出色应用。您可能需要查看一下以获取想法,因为它允许用户预先缓存他们所需的地图。当我深入非洲,佛罗里达大沼泽地,划船或任何我没有手机覆盖的地方时,我会使用它。我将在旅行前缓存地图,然后可以在没有互联网的情况下正常使用iPhone上的GPS。

基本上,他们的xGPS所做的事情以及您想做的就是在手机上本地缓存地图图块。这些手机上的空间有限。是的,即使您的手机上有32GB的内存,也可能足以在所有缩放级别(比例)上缓存一个小国家/地区。这些手机(除非以某种方式连接到外部存储设备)都没有足够的空间来缓存所有缩放级别的世界。我想这将需要PB的存储空间。

因此,您需要能够要求用户在线时缓存“区域”或地图,以便他可以离线使用它们。使用xGPS,我可以在我感兴趣的区域上绘制一个多边形,并指定要缓存的缩放级别。然后,它将开始从手机本身或计算机上的程序中为我全部下载到我的手机上。然后,应用程序上有一个按钮,允许我在断开互联网连接时切换到“离线”模式。


2

尝试使用NextGIS Mobile SDK。在线/离线模式包括编辑和与服务器自动同步(NextGIS Web)。栅格和矢量层,自定义输入形式,所有类型的几何支持。

可以在Google Play商店中找到示例应用程序NextGIS Mobile- https://play.google.com/store/apps/details? id=com.nextgis.mobile

来源在这里:https : //github.com/nextgis/android_gisapp

说明文件:http : //docs.nextgis.com/docs_ngmobile/source/toc.html

另一个简单的应用程序在这里:https : //github.com/nextgis/android_muni_gisconf

SDK文档:http//docs.nextgis.com/ngmobile_dev/toc.html


1

当前版本的ArcGIS Android SDK完全支持脱机地图。本示例将向您展示如何使用本地图块包作为底图,以及如何将在线要素保留为离线要素,您可以通过这些方式进行编辑。我也可以在github上找到要点,以简化参考。


1

我建议看一下Nutiteq 3D maps SDK,它具有脱机功能和有趣的功能,例如3D支持。它是由专门的开发商公司在其背后制造的,因此它具有专门的商业支持,并且比大型供应商提供的灵活性更大。免责声明:我是它的开发者。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.