`
tianya84
  • 浏览: 25786 次
社区版块
存档分类
最新评论

GIS的学习(十五)Osmdroid中TileSource几点研究

 
阅读更多

  在osmdroid中下载titleSource的地图碎片title文件是否缓存的以及缓存大小的问题:

1.针对osmdroid的title文件缓存规律如下,第一次请求之后,缓存保存一定日期之后删除。

具体代码参考如下:

public class MapTileDownloader extends MapTileModuleProviderBase

Java代码   收藏代码
  1. private class TileLoader extends MapTileModuleProviderBase.TileLoader {  
  2.   
  3.     @Override  
  4.     public Drawable loadTile(final MapTileRequestState aState) throws CantContinueException {  
  5.   
  6.         if (mTileSource == null) {  
  7.             return null;  
  8.         }  
  9.   
  10.         InputStream in = null;  
  11.         OutputStream out = null;  
  12.         final MapTile tile = aState.getMapTile();  
  13.   
  14.         try {  
  15.   
  16.             if (mNetworkAvailablityCheck != null  
  17.                     && !mNetworkAvailablityCheck.getNetworkAvailable()) {  
  18.                 if (DEBUGMODE) {  
  19.                     logger.debug("Skipping " + getName() + " due to NetworkAvailabliltyCheck.");  
  20.                 }  
  21.                 return null;  
  22.             }  
  23.   
  24.             final String tileURLString = mTileSource.getTileURLString(tile);  
  25.   
  26.             if (DEBUGMODE) {  
  27.                 logger.debug("Downloading Maptile from url: " + tileURLString);  
  28.             }  
  29.   
  30.             if (TextUtils.isEmpty(tileURLString)) {  
  31.                 return null;  
  32.             }  
  33.   
  34.             final HttpClient client = new DefaultHttpClient();  
  35.             final HttpUriRequest head = new HttpGet(tileURLString);  
  36.             final HttpResponse response = client.execute(head);  
  37.   
  38.             // Check to see if we got success  
  39.             final org.apache.http.StatusLine line = response.getStatusLine();  
  40.             if (line.getStatusCode() != 200) {  
  41.                 logger.warn("Problem downloading MapTile: " + tile + " HTTP response: " + line);  
  42.                 return null;  
  43.             }  
  44.   
  45.             final HttpEntity entity = response.getEntity();  
  46.             if (entity == null) {  
  47.                 logger.warn("No content downloading MapTile: " + tile);  
  48.                 return null;  
  49.             }  
  50.             in = entity.getContent();  
  51.   
  52.             final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();  
  53.             out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);  
  54.             StreamUtils.copy(in, out);  
  55.             out.flush();  
  56.             final byte[] data = dataStream.toByteArray();  
  57.             final ByteArrayInputStream byteStream = new ByteArrayInputStream(data);  
  58.   
  59.             // Save the data to the filesystem cache  
  60.             if (mFilesystemCache != null) {  
  61.                 mFilesystemCache.saveFile(mTileSource, tile, byteStream);  
  62.                 byteStream.reset();  
  63.             }  
  64.             final Drawable result = mTileSource.getDrawable(byteStream);  
  65.   
  66.             return result;  
  67.         } catch (final UnknownHostException e) {  
  68.             // no network connection so empty the queue  
  69.             logger.warn("UnknownHostException downloading MapTile: " + tile + " : " + e);  
  70.             throw new CantContinueException(e);  
  71.         } catch (final LowMemoryException e) {  
  72.             // low memory so empty the queue  
  73.             logger.warn("LowMemoryException downloading MapTile: " + tile + " : " + e);  
  74.             throw new CantContinueException(e);  
  75.         } catch (final FileNotFoundException e) {  
  76.             logger.warn("Tile not found: " + tile + " : " + e);  
  77.         } catch (final IOException e) {  
  78.             logger.warn("IOException downloading MapTile: " + tile + " : " + e);  
  79.         } catch (final Throwable e) {  
  80.             logger.error("Error downloading MapTile: " + tile, e);  
  81.         } finally {  
  82.             StreamUtils.closeStream(in);  
  83.             StreamUtils.closeStream(out);  
  84.         }  
  85.   
  86.         return null;  
  87.     }  

 

首先采用在第一次请求地图的碎片时候,通过httpclient下载相关的碎片,下载成功之后,mFilesystemCache 是一个文件系统缓存处理器,缓存访问过的 地图碎片信息。

 

 

文件系统缓存器IFilesystemCache的一个具体实现如下:

public class TileWriter implements IFilesystemCache, OpenStreetMapTileProviderConstants

Java代码   收藏代码
  1. public class TileWriter implements IFilesystemCache, OpenStreetMapTileProviderConstants {  
  2.   
  3.     // ===========================================================  
  4.     // Constants  
  5.     // ===========================================================  
  6.   
  7.     private static final Logger logger = LoggerFactory.getLogger(TileWriter.class);  
  8.   
  9.     // ===========================================================  
  10.     // Fields  
  11.     // ===========================================================  
  12.   
  13.     /** amount of disk space used by tile cache **/  
  14.     private static long mUsedCacheSpace;  
  15.   
  16.     // ===========================================================  
  17.     // Constructors  
  18.     // ===========================================================  
  19.   
  20.     public TileWriter() {  
  21.   
  22.         // do this in the background because it takes a long time  
  23.         final Thread t = new Thread() {  
  24.             @Override  
  25.             public void run() {  
  26.                 mUsedCacheSpace = 0// because it's static  
  27.                 calculateDirectorySize(TILE_PATH_BASE);  
  28.                 if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {  
  29.                     cutCurrentCache();  
  30.                 }  
  31.                 if (DEBUGMODE) {  
  32.                     logger.debug("Finished init thread");  
  33.                 }  
  34.             }  
  35.         };  
  36.         t.setPriority(Thread.MIN_PRIORITY);  
  37.         t.start();  
  38.     }  
  39.   
  40.     // ===========================================================  
  41.     // Getter & Setter  
  42.     // ===========================================================  
  43.   
  44.     /** 
  45.      * Get the amount of disk space used by the tile cache. This will initially be zero since the 
  46.      * used space is calculated in the background. 
  47.      * 
  48.      * @return size in bytes 
  49.      */  
  50.     public static long getUsedCacheSpace() {  
  51.         return mUsedCacheSpace;  
  52.     }  
  53.   
  54.     // ===========================================================  
  55.     // Methods from SuperClass/Interfaces  
  56.     // ===========================================================  
  57.   
  58.     @Override  
  59.     public boolean saveFile(final ITileSource pTileSource, final MapTile pTile,  
  60.             final InputStream pStream) {  
  61.   
  62.         final File file = new File(TILE_PATH_BASE, pTileSource.getTileRelativeFilenameString(pTile)  
  63.                 + TILE_PATH_EXTENSION);  
  64.   
  65.         final File parent = file.getParentFile();  
  66.         if (!parent.exists() && !createFolderAndCheckIfExists(parent)) {  
  67.             return false;  
  68.         }  
  69.   
  70.         BufferedOutputStream outputStream = null;  
  71.         try {  
  72.             outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath()),  
  73.                     StreamUtils.IO_BUFFER_SIZE);  
  74.             final long length = StreamUtils.copy(pStream, outputStream);  
  75.   
  76.             mUsedCacheSpace += length;  
  77.             if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {  
  78.                 cutCurrentCache(); // TODO perhaps we should do this in the background  
  79.             }  
  80.         } catch (final IOException e) {  
  81.             return false;  
  82.         } finally {  
  83.             if (outputStream != null) {  
  84.                 StreamUtils.closeStream(outputStream);  
  85.             }  
  86.         }  
  87.         return true;  
  88.     }  
  89.   
  90.     // ===========================================================  
  91.     // Methods  
  92.     // ===========================================================  
  93.   
  94.     private boolean createFolderAndCheckIfExists(final File pFile) {  
  95.         if (pFile.mkdirs()) {  
  96.             return true;  
  97.         }  
  98.         if (DEBUGMODE) {  
  99.             logger.debug("Failed to create " + pFile + " - wait and check again");  
  100.         }  
  101.   
  102.         // if create failed, wait a bit in case another thread created it  
  103.         try {  
  104.             Thread.sleep(500);  
  105.         } catch (final InterruptedException ignore) {  
  106.         }  
  107.         // and then check again  
  108.         if (pFile.exists()) {  
  109.             if (DEBUGMODE) {  
  110.                 logger.debug("Seems like another thread created " + pFile);  
  111.             }  
  112.             return true;  
  113.         } else {  
  114.             if (DEBUGMODE) {  
  115.                 logger.debug("File still doesn't exist: " + pFile);  
  116.             }  
  117.             return false;  
  118.         }  
  119.     }  
  120.   
  121.     private void calculateDirectorySize(final File pDirectory) {  
  122.         final File[] z = pDirectory.listFiles();  
  123.         if (z != null) {  
  124.             for (final File file : z) {  
  125.                 if (file.isFile()) {  
  126.                     mUsedCacheSpace += file.length();  
  127.                 }  
  128.                 if (file.isDirectory() && !isSymbolicDirectoryLink(pDirectory, file)) {  
  129.                     calculateDirectorySize(file); // *** recurse ***  
  130.                 }  
  131.             }  
  132.         }  
  133.     }  
  134.   
  135.     /** 
  136.      * Checks to see if it appears that a directory is a symbolic link. It does this by comparing 
  137.      * the canonical path of the parent directory and the parent directory of the directory's 
  138.      * canonical path. If they are equal, then they come from the same true parent. If not, then 
  139.      * pDirectory is a symbolic link. If we get an exception, we err on the side of caution and 
  140.      * return "true" expecting the calculateDirectorySize to now skip further processing since 
  141.      * something went goofy. 
  142.      */  
  143.     private boolean isSymbolicDirectoryLink(final File pParentDirectory, final File pDirectory) {  
  144.         try {  
  145.             final String canonicalParentPath1 = pParentDirectory.getCanonicalPath();  
  146.             final String canonicalParentPath2 = pDirectory.getCanonicalFile().getParent();  
  147.             return !canonicalParentPath1.equals(canonicalParentPath2);  
  148.         } catch (final IOException e) {  
  149.             return true;  
  150.         } catch (final NoSuchElementException e) {  
  151.             // See: http://code.google.com/p/android/issues/detail?id=4961  
  152.             // See: http://code.google.com/p/android/issues/detail?id=5807  
  153.             return true;  
  154.         }  
  155.   
  156.     }  
  157.   
  158.     private List<File> getDirectoryFileList(final File aDirectory) {  
  159.         final List<File> files = new ArrayList<File>();  
  160.   
  161.         final File[] z = aDirectory.listFiles();  
  162.         if (z != null) {  
  163.             for (final File file : z) {  
  164.                 if (file.isFile()) {  
  165.                     files.add(file);  
  166.                 }  
  167.                 if (file.isDirectory()) {  
  168.                     files.addAll(getDirectoryFileList(file));  
  169.                 }  
  170.             }  
  171.         }  
  172.   
  173.         return files;  
  174.     }  
  175.   
  176.     /** 
  177.      * If the cache size is greater than the max then trim it down to the trim level. This method is 
  178.      * synchronized so that only one thread can run it at a time. 
  179.      */  
  180.     private void cutCurrentCache() {  
  181.   
  182.         synchronized (TILE_PATH_BASE) {  
  183.   
  184.             if (mUsedCacheSpace > TILE_TRIM_CACHE_SIZE_BYTES) {  
  185.   
  186.                 logger.info("Trimming tile cache from " + mUsedCacheSpace + " to "  
  187.                         + TILE_TRIM_CACHE_SIZE_BYTES);  
  188.   
  189.                 final List<File> z = getDirectoryFileList(TILE_PATH_BASE);  
  190.   
  191.                 // order list by files day created from old to new  
  192.                 final File[] files = z.toArray(new File[0]);  
  193.                 Arrays.sort(files, new Comparator<File>() {  
  194.                     @Override  
  195.                     public int compare(final File f1, final File f2) {  
  196.                         return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());  
  197.                     }  
  198.                 });  
  199.   
  200.                 for (final File file : files) {  
  201.                     if (mUsedCacheSpace <= TILE_TRIM_CACHE_SIZE_BYTES) {  
  202.                         break;  
  203.                     }  
  204.   
  205.                     final long length = file.length();  
  206.                     if (file.delete()) {  
  207.                         mUsedCacheSpace -= length;  
  208.                     }  
  209.                 }  
  210.   
  211.                 logger.info("Finished trimming tile cache");  
  212.             }  
  213.         }  
  214.     }  
  215.   
  216. }  

 

在TileWriter 文件缓存器创建的时候,

1.创建一个线程检查相关的文件大小

代码如下:

Java代码   收藏代码
  1. public TileWriter() {  
  2.   
  3.  // do this in the background because it takes a long time  
  4.  final Thread t = new Thread() {  
  5.   @Override  
  6.   public void run() {  
  7.    mUsedCacheSpace = 0// because it's static  
  8.    calculateDirectorySize(TILE_PATH_BASE);  
  9.    if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {  
  10.     cutCurrentCache();  
  11.    }  
  12.    if (DEBUGMODE) {  
  13.     logger.debug("Finished init thread");  
  14.    }  
  15.   }  
  16.  };  
  17.  t.setPriority(Thread.MIN_PRIORITY);  
  18.  t.start();  
  19. }  

 2.在缓存中保存文件缓存的过程如下:

Java代码   收藏代码
  1. @Override  
  2. public boolean saveFile(final ITileSource pTileSource, final MapTile pTile,  
  3.         final InputStream pStream) {  
  4.   
  5.     final File file = new File(TILE_PATH_BASE, pTileSource.getTileRelativeFilenameString(pTile)  
  6.             + TILE_PATH_EXTENSION);  
  7.   
  8.     final File parent = file.getParentFile();  
  9.     if (!parent.exists() && !createFolderAndCheckIfExists(parent)) {  
  10.         return false;  
  11.     }  
  12.   
  13.     BufferedOutputStream outputStream = null;  
  14.     try {  
  15.         outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath()),  
  16.                 StreamUtils.IO_BUFFER_SIZE);  
  17.         final long length = StreamUtils.copy(pStream, outputStream);  
  18.   
  19.         mUsedCacheSpace += length;  
  20.         if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {  
  21.             cutCurrentCache(); // TODO perhaps we should do this in the background  
  22.         }  
  23.     } catch (final IOException e) {  
  24.         return false;  
  25.     } finally {  
  26.         if (outputStream != null) {  
  27.             StreamUtils.closeStream(outputStream);  
  28.         }  
  29.     }  
  30.     return true;  
  31. }  

 

3.清理文件缓存的方法实现如下:

Java代码   收藏代码
  1. /** 
  2.      * If the cache size is greater than the max then trim it down to the trim level. This method is 
  3.      * synchronized so that only one thread can run it at a time. 
  4.      */  
  5.     private void cutCurrentCache() {  
  6.   
  7.         synchronized (TILE_PATH_BASE) {  
  8.   
  9.             if (mUsedCacheSpace > TILE_TRIM_CACHE_SIZE_BYTES) {  
  10.   
  11.                 logger.info("Trimming tile cache from " + mUsedCacheSpace + " to "  
  12.                         + TILE_TRIM_CACHE_SIZE_BYTES);  
  13.   
  14.                 final List<File> z = getDirectoryFileList(TILE_PATH_BASE);  
  15.   
  16.                 // order list by files day created from old to new  
  17.                 final File[] files = z.toArray(new File[0]);  
  18.                 Arrays.sort(files, new Comparator<File>() {  
  19.                     @Override  
  20.                     public int compare(final File f1, final File f2) {  
  21.                         return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());  
  22.                     }  
  23.                 });  
  24.   
  25.                 for (final File file : files) {  
  26.                     if (mUsedCacheSpace <= TILE_TRIM_CACHE_SIZE_BYTES) {  
  27.                         break;  
  28.                     }  
  29.   
  30.                     final long length = file.length();  
  31.                     if (file.delete()) {  
  32.                         mUsedCacheSpace -= length;  
  33.                     }  
  34.                 }  
  35.   
  36.                 logger.info("Finished trimming tile cache");  
  37.             }  
  38.         }  
  39.     }  

 

由上述代码可以看出:看出缓存大于最大值时候清理缓存

Java代码   收藏代码
  1. /** 30 days */  
  2. public static final long TILE_EXPIRY_TIME_MILLISECONDS = 1000L * 60 * 60 * 24 * 30;  
  3.   
  4. /** 600 Mb */  
  5. public static final long TILE_MAX_CACHE_SIZE_BYTES = 600L * 1024 * 1024;  
  6.   
  7. /** 500 Mb */  
  8. public static final long TILE_TRIM_CACHE_SIZE_BYTES = 500L * 1024 * 1024;  

 

Java代码   收藏代码
  1. if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {  
  2.  cutCurrentCache(); // TODO perhaps we should do this in the background  
  3. }  

原文:http://topmanopensource.iteye.com/blog/1664631

 

 

 

分享到:
评论

相关推荐

    osmdroid 加载geopackage离线底图

    加载GeoPackage离线底图到osmdroid中,首先需要确保你的项目已经正确集成osmdroid库。通常,这可以通过在build.gradle文件中添加osmdroid依赖来实现。例如: ```groovy dependencies { implementation 'org....

    Osmdroid源码

    在深入研究Osmdroid源码时,你需要关注以下几个关键模块: 1. **MapView**:这是Osmdroid的核心组件,它负责地图的显示和用户交互。在源码中,你可以看到如何处理触控事件,以及如何更新地图视图。 2. **TileSource*...

    javagui源码-TileSource:Java中基于图块的游戏的基本代码。这是游戏GUI的入门代码

    通过研究TileSource的源码,我们可以学习到如何在Java环境中构建一个基本的游戏GUI,理解图块化布局的实现,以及游戏开发中的一些核心概念。同时,这也为我们提供了一个实践Java GUI编程和游戏开发的实例。

    xamarin.android 一个简单的地图Demo

    在Xamarin中,我们可以利用Java Bindings Library将Java库(如osmdroid-android-binding-4.2)转化为C#代码,以便在Xamarin.Android项目中使用。 要创建这个简单的地图Demo,首先需要在Xamarin项目中添加osmdroid库...

    openscales学习笔记8.24

    在8.24这个阶段的学习中,可能涉及到的关键技术点包括: 1. **地图瓦片(Tile)渲染**:OpenScales支持瓦片地图服务,如OpenStreetMap或Google Maps,通过将大地理区域分割成小块(瓦片)来高效加载和显示地图。这...

    海图数据如何加载到osgearth中.doc

    在IT行业中,尤其是在地理信息系统(GIS)领域,海图数据的处理和可视化是至关重要的。本文将详细讲解如何将S57格式的海图数据转换为TMS(Tile Map Service)瓦片,并将其加载到osgearth这个开源的地球可视化框架中...

    VB+MapX鹰眼图

    在IT行业中,VB(Visual Basic)是一种经典的...通过这个项目,开发者可以学习到如何将GIS功能集成到桌面应用中,以及如何创建交互式的地图导航工具。对于有兴趣在GIS领域进行开发的人来说,这是一个很好的实践项目。

    离线单独加载GeoWebCache的切片

    GeoWebCache(GWC)是一种基于开源地理信息系统(GIS)软件GeoServer的缓存服务,它能够预先生成地图切片并存储在本地或分布式存储系统中,以提高...通过研究源码,你可以更深入地理解上述知识点,并学习如何实际应用。

    WP8 地图示例

    在这个示例中,开发者可以学习如何初始化地图控件,设置中心点、缩放级别,以及添加图层和标记。 地图控件是WP8地图API的核心组件,用于在应用程序中显示地图。通过设置MapControl的Center属性,可以改变地图的中心...

    openlayers 3 源码

    OpenLayers 3 是一个强大的...总的来说,OpenLayers 3 源码研究涉及地图绘制、数据处理、用户交互等多个方面,对提升GIS开发技能大有裨益。通过深入理解并实践,开发者可以构建出功能强大、用户体验优秀的Web地图应用。

    Openlary4加载ArcGIS离线瓦片地图

    在IT行业中,地图服务是许多应用的核心组成部分,特别是在地理信息系统(GIS)中。OpenLayers是一个流行的开源JavaScript库,用于在Web浏览器中展示地图。而ArcGIS则是Esri公司提供的一个全面的GIS平台,包括在线...

    openlayers 2.9.1最新api文档

    OpenLayers 是一个开源JavaScript库,专门用于...以上只是OpenLayers 2.9.1 API的部分关键知识点,实际使用中,开发者还需要参考apidocs中的详细文档,理解各个类、方法和属性的具体用法,以充分利用这个强大的GIS库。

    Openlayer 加载Echarts省市轮廓,XYZ方式加载TMS瓦片底图

    在IT行业中,地图渲染是数据可视化的一个重要领域,OpenLayers 和 ECharts 都是流行的开源库,分别在Web GIS和数据图表展示上有着广泛的应用。本文将深入探讨如何利用OpenLayers加载Echarts省市轮廓,并通过XYZ方式...

    osgearth加载本地离线影像瓦片地图

    在IT领域,尤其是在地理信息系统(GIS)中,加载本地离线影像瓦片地图是一个常见的需求。osgEarth是一个基于OpenSceneGraph(OSG)的开源库,它提供了将2D地图和3D地形集成到实时3D场景中的能力。本教程将深入探讨...

    wapianxiazai0214.7z

    瓦片地图下载,免安装,可兼容OpenLayer,这一主题涉及到的是Web地图开发中的关键技术和工具。瓦片地图是一种常见的在线地图展示方式,它将大范围、高分辨率的地图分割成多个小块(通常为256x256像素的图片),每个...

    openlayer加载本地切片

    要加载本地切片,你需要创建一个TileSource实例,然后将其添加到Map对象中。这里是一个基本示例: ```javascript // 创建一个新的OpenLayers Map对象 var map = new ol.Map({ target: 'map', // 指定地图容器的...

    openlayers发布简易离线地图DEMO

    在这个DEMO中,我们重点关注两个关键点:地图瓦片的组织和OpenLayers的配置。 1. **地图瓦片的组织**: 地图瓦片通常按照一定的网格系统进行分块,如XYZ网格(X、Y轴坐标和Zoom级别)。每个瓦片都是一个固定大小...

    Python库 | large-image-source-pil-1.6.3.dev17.tar.gz

    《Python库:深入理解large-image-source-pil》 在Python的世界里,库是开发者们的重要工具...无论是在科学研究、地图制图,还是在医疗影像分析等领域,这个库都能发挥重要作用,帮助开发者更好地应对大型图像的挑战。

    openlayers5加载geooserver发布线图层.zip

    在IT行业中,地图服务的开发和应用是GIS(地理信息系统)领域的重要组成部分。OpenLayers是一个流行的JavaScript库,用于创建交互式地图应用,而GeoServer是一个开源的WMS(Web Map Service)服务器,它允许发布和...

    openlayers发布离线地图DEMO

    OpenLayers 是一个强大的开源JavaScript库,用于在网页上创建交互式的地图应用。它支持多种地图服务,包括WMS...通过学习和理解这个DEMO,你可以进一步掌握OpenLayers的操作,并将其应用到更复杂和定制化的地图项目中。

Global site tag (gtag.js) - Google Analytics