我正在寻找一种开发具有嵌入式地图的android应用程序的方法,该应用程序可以在没有互联网连接的情况下工作(即,我可以获取开放式街道地图的图块以供离线使用吗?)。
我之前通过使用Google Maps API v3开发了Web应用程序。我需要一个通用的答案作为一个具体的答案。我正在尝试找到我需要学习的概念和技术:)
(同时我发现了osmdroid。它可以离线工作吗?)
我正在寻找一种开发具有嵌入式地图的android应用程序的方法,该应用程序可以在没有互联网连接的情况下工作(即,我可以获取开放式街道地图的图块以供离线使用吗?)。
我之前通过使用Google Maps API v3开发了Web应用程序。我需要一个通用的答案作为一个具体的答案。我正在尝试找到我需要学习的概念和技术:)
(同时我发现了osmdroid。它可以离线工作吗?)
Answers:
您在寻找移动/蜂窝应用程序的开发吗?因为新版Google平板电脑随附矢量格式的离线Google地图,而不是栅格图块。
Google Honeycomb(平板电脑)完全支持Google Maps Offline(矢量)
底部的视频说明并显示了该应用程序。
我使用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;
}
}
我已经为Android开发了带有离线地图的应用程序。您要使用的唯一免费工具是OSMDroid,否则使用ESRI。OSMDroid API与Google的API相同,因此,如果您要从一个切换到另一个,这很容易。
请查看这篇文章,其中提供了有关如何将Google Maps集成到OSMDroid的示例(它还为您提供了一般用法的想法)。
iPhone和其他设备有一个名为xGPS的出色应用。您可能需要查看一下以获取想法,因为它允许用户预先缓存他们所需的地图。当我深入非洲,佛罗里达大沼泽地,划船或任何我没有手机覆盖的地方时,我会使用它。我将在旅行前缓存地图,然后可以在没有互联网的情况下正常使用iPhone上的GPS。
基本上,他们的xGPS所做的事情以及您想做的就是在手机上本地缓存地图图块。这些手机上的空间有限。是的,即使您的手机上有32GB的内存,也可能足以在所有缩放级别(比例)上缓存一个小国家/地区。这些手机(除非以某种方式连接到外部存储设备)都没有足够的空间来缓存所有缩放级别的世界。我想这将需要PB的存储空间。
因此,您需要能够要求用户在线时缓存“区域”或地图,以便他可以离线使用它们。使用xGPS,我可以在我感兴趣的区域上绘制一个多边形,并指定要缓存的缩放级别。然后,它将开始从手机本身或计算机上的程序中为我全部下载到我的手机上。然后,应用程序上有一个按钮,允许我在断开互联网连接时切换到“离线”模式。
尝试使用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
我建议看一下Nutiteq 3D maps SDK,它具有脱机功能和有趣的功能,例如3D支持。它是由专门的开发商公司在其背后制造的,因此它具有专门的商业支持,并且比大型供应商提供的灵活性更大。免责声明:我是它的开发者。