赞
踩
由于天地图的地图接口请求有次数限制,我们做了本地缓存机制
原理是先查找本地目录是否有保存的瓦片图片,有的话直接返回路径,没有的话去请求天地图加载并保存到本地。
话不多说,直接上代码
我们加载在线瓦片代码是下面这样的,不知道的可以看我上片文章
String real_url = String.format(url, zoom, y, x);
LatLng mLatLng = mAMap.getProjection().fromScreenLocation(new Point(x,y));
Log.e("getTileUrl",x+","+y+""+" "+mLatLng+" "+real_url);
return new URL(real_url);
我们需要对这部分代码进行修改,修改后如下
加载影像底图部分
String ALBUM_PATH = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath()+"/Cache/";
Bitmap mBitmap; String mFileDirName = String.format("L%02d/", zoom + 1)+"img/"; String mFileName = String.format("%s", TileXYToQuadKey(x, y, zoom));//为了不在手机的图片中显示,取消jpg后缀,文件名自己定义,写入和读取一致即可,由于有自己的bingmap图源服务,所以此处我用的bingmap的文件名 String LJ = ALBUM_PATH +mFileDirName+ mFileName; Log.e("getTileUrl是图片否存在: ", "getTileUrl: "+(MapImageCache.getInstance().isBitmapExit( mFileName,ALBUM_PATH +mFileDirName))+""); if (MapImageCache.getInstance().isBitmapExit( mFileName,ALBUM_PATH +mFileDirName)) {//判断本地是否有图片文件,如果有返回本地url,如果没有,缓存到本地并返回googleurl Log.e("存在: ","file://" + LJ); return new URL("file://" + LJ); }else{ String real_url = String.format(url, zoom, y, x); mBitmap = getImageBitmap(getImageStream(real_url)); try { saveFile(mBitmap, mFileName, mFileDirName); } catch (IOException e) { e.printStackTrace(); } Log.e("不存在: ",real_url); return new URL(real_url);
加载标注部分
Bitmap mBitmap; String mFileDirName = String.format("L%02d/", zoom + 1)+"title/"; String mFileName = String.format("%s", TileXYToQuadKey(x, y, zoom));//为了不在手机的图片中显示,取消jpg后缀,文件名自己定义,写入和读取一致即可,由于有自己的bingmap图源服务,所以此处我用的bingmap的文件名 String LJ = ALBUM_PATH +mFileDirName+ mFileName; Log.e("名称是否存在: ", mFileName+"getTileUrl: "+(MapImageCache.getInstance().isBitmapExit( mFileName,ALBUM_PATH +mFileDirName))+""); if (MapImageCache.getInstance().isBitmapExit( mFileName,ALBUM_PATH +mFileDirName)) {//判断本地是否有图片文件,如果有返回本地url,如果没有,缓存到本地并返回googleurl return new URL("file://" + LJ); }else{ String real_url = String.format(url2, zoom, y, x); mBitmap = getImageBitmap(getImageStream(real_url)); try { saveFile(mBitmap, mFileName, mFileDirName); } catch (IOException e) { e.printStackTrace(); } return new URL(real_url); }
下面是缓存过程用到的一些方法
/** * 瓦片数据坐标转换 */ private String TileXYToQuadKey(int tileX, int tileY, int levelOfDetail) { StringBuilder quadKey = new StringBuilder(); for (int i = levelOfDetail; i > 0; i--) { char digit = '0'; int mask = 1 << (i - 1); if ((tileX & mask) != 0) { digit++; } if ((tileY & mask) != 0) { digit++; digit++; } quadKey.append(digit); } return quadKey.toString(); }
/** * 保存文件 */ public void saveFile(final Bitmap bm, final String fileName, final String fileDirName) throws IOException { new Thread(new Runnable() { @Override public void run() { try { if(bm != null) { File dirFile = new File(ALBUM_PATH + fileDirName); if(!dirFile.exists()){ dirFile.mkdirs(); Log.e("创建文件夹",(dirFile.exists())+""); } File myCaptureFile = new File(ALBUM_PATH + fileDirName + fileName); // Log.e("保存路径",myCaptureFile.getPath()); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile)); bm.compress(Bitmap.CompressFormat.PNG, 80, bos); bos.flush(); bos.close(); } } catch (IOException e) { e.printStackTrace(); } } }).start(); } public Bitmap getImageBitmap(InputStream imputStream){ // 将所有InputStream写到byte数组当中 byte[] targetData = null; if(imputStream != null){ byte[] bytePart = new byte[4096]; while (true) { try { int readLength = imputStream.read(bytePart); if (readLength == -1) { break; } else { byte[] temp = new byte[readLength + (targetData == null ? 0 : targetData.length)]; if (targetData != null) { System.arraycopy(targetData, 0, temp, 0, targetData.length); System.arraycopy(bytePart, 0, temp, targetData.length, readLength); } else { System.arraycopy(bytePart, 0, temp, 0, readLength); } targetData = temp; } } catch (Exception e) { e.printStackTrace(); } } } // 指使Bitmap通过byte数组获取数据 Bitmap bitmap = BitmapFactory.decodeByteArray(targetData, 0, targetData.length); return bitmap; } public InputStream getImageStream(String path) throws Exception{ URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){ return conn.getInputStream(); } return null; }
MapImageCache类 ,这个类就是判断了一下本地路径是否存在图片缓存
import java.io.File; public class MapImageCache { private static MapImageCache mNetImageViewCache = new MapImageCache(); private MapImageCache() { } public static MapImageCache getInstance() { return mNetImageViewCache; } /** * 判断图片是否存在首先判断内存中是否存在然后判断本地是否存在 * * @param url * @return */ public boolean isBitmapExit(String url,String path) { //boolean isExit = containsKey(url); boolean isExit = false; if (false == isExit) { isExit = isLocalHasBmp(url,path); } return isExit; } /* * 判断本地有没有 */ private boolean isLocalHasBmp(String name,String path) { boolean isExit = true; // String name = name; String filePath = path; File file = new File(filePath, name); if (file.exists()) { } else { isExit = false; } return isExit; } }
在加载离线实现的过程中参考了一个大佬博客Android的关于高德地图加载谷歌瓦片,并缓存本地的功能._android h5缓存地图瓦片-CSDN博客
使用大佬的方法,每次加载离线瓦片数据地图就是黑色的只有标注,后来发现是加载缓存标注图片时,标注图片的背景变成了黑色,原因就是保存的时候图片格式是JPEG,只需要把JPEG改成PNG即可解决了
bm.compress(Bitmap.CompressFormat.PNG, 80, bos);
就这一行代码,不对的地方,欢迎大家指正交流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。