package com.dayu.pipirrapp.utils;
|
|
import android.graphics.Bitmap;
|
import android.graphics.BitmapFactory;
|
import android.net.Uri;
|
import android.util.Log;
|
|
import com.dayu.pipirrapp.MyApplication;
|
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
import okhttp3.ResponseBody;
|
|
/**
|
* author: zuo
|
* Date: 2024-09-06
|
* Time: 17:59
|
* 备注: 完成地图缓存策略
|
*/
|
public class MapJpgUtils {
|
static String TAG = "MapJpgUtils";
|
|
static MapJpgUtils mapJpgUtils;
|
|
String childName = "mapCache";
|
String fileType = ".jpg";
|
|
public static MapJpgUtils getInsatance() {
|
if (mapJpgUtils == null) {
|
mapJpgUtils = new MapJpgUtils();
|
}
|
return mapJpgUtils;
|
}
|
|
|
// 获取缓存瓦片文件
|
public File getCachedTile(String url) {
|
String fileName = hashUrl(url); // URL 转换为唯一的哈希值或文件名
|
String folderPath = extractTileInfoFromUrl(url);
|
File cacheDir = new File(MyApplication.myApplication.getCacheDir() + File.separator + childName + File.separator + folderPath); // 瓦片存储目录
|
if (!cacheDir.exists()) {
|
cacheDir.mkdirs();
|
}
|
return new File(cacheDir, fileName);
|
}
|
|
// 使用 MD5 哈希 URL 作为文件名
|
private String hashUrl(String url) {
|
try {
|
MessageDigest digest = MessageDigest.getInstance("MD5");
|
digest.update(url.getBytes());
|
byte[] hashBytes = digest.digest();
|
StringBuilder sb = new StringBuilder();
|
for (byte b : hashBytes) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString() + fileType;
|
} catch (NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
return String.valueOf(url.hashCode());
|
}
|
}
|
|
// 保存瓦片到缓存
|
public boolean saveTileToCache(String url, ResponseBody body) {
|
|
try {
|
//从 URL 中提取瓦片的 Z/X/Y 值
|
String folderPath = extractTileInfoFromUrl(url);
|
|
File tileFile = new File(MyApplication.myApplication.getCacheDir() + File.separator + childName + File.separator + folderPath + File.separator + hashUrl(url));
|
if (!tileFile.getParentFile().exists()) {
|
tileFile.getParentFile().mkdirs();
|
}
|
InputStream inputStream = null;
|
OutputStream outputStream = null;
|
|
try {
|
byte[] fileReader = new byte[4096];
|
long fileSizeDownloaded = 0;
|
|
inputStream = body.byteStream();
|
outputStream = new FileOutputStream(tileFile);
|
|
while (true) {
|
int read = inputStream.read(fileReader);
|
|
if (read == -1) {
|
break;
|
}
|
outputStream.write(fileReader, 0, read);
|
fileSizeDownloaded += read;
|
}
|
|
outputStream.flush();
|
// 保存完成后,记录缓存创建时间
|
tileFile.setLastModified(System.currentTimeMillis());
|
if (validateImageFile(tileFile)) {
|
// 校验下载文件大小和实际大小是否一致
|
long actualFileSize = tileFile.length();
|
if (fileSizeDownloaded == actualFileSize) {
|
Log.d(TAG, "文件大小匹配,下载大小:" + fileSizeDownloaded + " 字节,实际大小:" + actualFileSize + " 字节");
|
return true;
|
} else {
|
//保存失败,删除文件
|
tileFile.delete();
|
Log.e(TAG, "文件大小不匹配,下载大小:" + fileSizeDownloaded + " 字节,实际大小:" + actualFileSize + " 字节");
|
return false;
|
}
|
} else {
|
//保存失败,删除文件
|
tileFile.delete();
|
Log.d(TAG, "保存失败,文件没有保存完整");
|
return false;
|
}
|
|
} catch (Exception e) {
|
return false;
|
} finally {
|
if (inputStream != null) {
|
inputStream.close();
|
}
|
if (outputStream != null) {
|
outputStream.close();
|
}
|
}
|
} catch (Exception e) {
|
return false;
|
}
|
}
|
|
/**
|
* 判断文件是否存在
|
*
|
* @param url
|
* @return
|
*/
|
public boolean isHasFiles(String url) {
|
String fileName = hashUrl(url); // URL 转换为唯一的哈希值或文件名
|
File cacheDir = new File(MyApplication.myApplication.getCacheDir(), "mapCache"); // 瓦片存储目录
|
if (!cacheDir.exists()) {
|
cacheDir.mkdirs();
|
}
|
if (new File(cacheDir, fileName).exists()) {
|
return true;
|
}
|
return false;
|
}
|
|
// 判断缓存是否过期
|
public boolean isCacheExpired(File cachedFile) {
|
final long cacheValidity = 24 * 60 * 60 * 1000; // 1 天有效期
|
long lastModified = cachedFile.lastModified();
|
return (System.currentTimeMillis() - lastModified) > cacheValidity;
|
}
|
|
/**
|
* 判断当前文件是否完整
|
*
|
* @param url
|
* @return
|
*/
|
public boolean isComplete(String url, long size) {
|
return false;
|
}
|
|
// 清理所有旧缓存
|
public void clearOldCacheFiles() {
|
File cacheDir = new File(MyApplication.myApplication.getCacheDir(), "mapCache");
|
if (cacheDir.exists()) {
|
File[] files = cacheDir.listFiles();
|
if (files != null) {
|
for (File file : files) {
|
file.delete();
|
}
|
}
|
}
|
}
|
|
//清理单个缓存
|
public void clearCacheFile(String url) {
|
File file = new File(MyApplication.myApplication.getCacheDir() + File.separator + childName + File.separator + hashUrl(url) + fileType);
|
if (file.exists()) {
|
file.delete();
|
}
|
}
|
|
|
// 校验图片的完整性
|
public boolean validateImageFile(File tileFile) {
|
if (!tileFile.exists()) {
|
// 文件不存在,视为不完整
|
return false;
|
}
|
// 尝试解析图像
|
Bitmap bitmap = BitmapFactory.decodeFile(tileFile.getAbsolutePath());
|
if (bitmap != null) {
|
// 图像解析成功,文件完整
|
Log.d(TAG, "图像解析成功,文件完整");
|
// 解析完图像后,手动回收Bitmap的内存
|
bitmap.recycle();
|
return true;
|
} else {
|
// 图像解析失败,文件不完整或损坏
|
Log.e(TAG, "图像解析失败,文件不完整或损坏");
|
return false;
|
}
|
}
|
|
|
/**
|
* 判断请求是否为天地图瓦片
|
*
|
* @param url
|
* @return
|
*/
|
public boolean isTianDiTuTileRequest(String url) {
|
return url.contains("tianditu.gov.cn") && url.contains("wmts") && url.contains("TILEMATRIX");
|
}
|
|
|
/**
|
* 从 URL 中提取瓦片的 Z/X/Y 值
|
*
|
* @param url
|
* @return
|
*/
|
public String extractTileInfoFromUrl(String url) {
|
Uri uri = Uri.parse(url);
|
Map<String, String> tileInfo = new HashMap<>();
|
String path = uri.getQueryParameter("TILEMATRIX") + File.separator + uri.getQueryParameter("TILEROW") + File.separator + uri.getQueryParameter("TILECOL");
|
return path;
|
}
|
|
}
|