Android 高德地图 添加 天地图 卫星瓦片图片 离线缓存

由于天地图的地图接口请求有次数限制,我们做了本地缓存机制

原理是先查找本地目录是否有保存的瓦片图片,有的话直接返回路径,没有的话去请求天地图加载并保存到本地。

话不多说,直接上代码

我们加载在线瓦片代码是下面这样的,不知道的可以看我上片文章

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

就这一行代码,不对的地方,欢迎大家指正交流

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值