package me.xiaopan.sketchsample.util; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.locks.ReentrantLock; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import me.xiaopan.sketch.Configuration; import me.xiaopan.sketch.SLogType; import me.xiaopan.sketch.SLog; import me.xiaopan.sketch.cache.DiskCache; import me.xiaopan.sketch.feature.ImagePreprocessor; import me.xiaopan.sketch.feature.PreProcessResult; import me.xiaopan.sketch.request.ImageFrom; import me.xiaopan.sketch.request.LoadRequest; import me.xiaopan.sketch.request.UriScheme; import me.xiaopan.sketch.util.DiskLruCache; import me.xiaopan.sketch.util.SketchUtils; /** * 在继承ImagePreprocessor的基础上扩展了解析XPK文件的图标 */ public class MyImagePreprocessor extends ImagePreprocessor { public MyImagePreprocessor() { logName = "MyImagePreprocessor"; } @Override public boolean isSpecific(LoadRequest loadRequest) { return super.isSpecific(loadRequest) || isXpkFile(loadRequest); } @Override public PreProcessResult process(LoadRequest loadRequest) { if (isXpkFile(loadRequest)) { return getXpkIconCacheFile(loadRequest); } return super.process(loadRequest); } private boolean isXpkFile(LoadRequest loadRequest) { return loadRequest.getUriScheme() == UriScheme.FILE && SketchUtils.checkSuffix(loadRequest.getRealUri(), ".xpk"); } /** * 获取XPK图标的缓存文件 */ private PreProcessResult getXpkIconCacheFile(LoadRequest loadRequest) { String realUri = loadRequest.getRealUri(); Configuration configuration = loadRequest.getConfiguration(); File xpkFile = new File(realUri); if (!xpkFile.exists()) { return null; } long lastModifyTime = xpkFile.lastModified(); String diskCacheKey = realUri + "." + lastModifyTime; DiskCache diskCache = configuration.getDiskCache(); ReentrantLock diskCacheEditLock = diskCache.getEditLock(diskCacheKey); diskCacheEditLock.lock(); PreProcessResult result = readXpkIcon(diskCache, loadRequest, diskCacheKey, realUri); diskCacheEditLock.unlock(); return result; } private PreProcessResult readXpkIcon(DiskCache diskCache, LoadRequest loadRequest, String diskCacheKey, String realUri) { DiskCache.Entry xpkIconDiskCacheEntry = diskCache.get(diskCacheKey); if (xpkIconDiskCacheEntry != null) { return new PreProcessResult(xpkIconDiskCacheEntry, ImageFrom.DISK_CACHE); } ZipFile zipFile; try { zipFile = new ZipFile(realUri); } catch (IOException e) { e.printStackTrace(); return null; } InputStream inputStream; ZipEntry zipEntry = zipFile.getEntry("icon.png"); if (zipEntry == null) { if (SLogType.REQUEST.isEnabled()) { SLog.w(SLogType.REQUEST, logName, "not found icon.png in. %s", loadRequest.getKey()); } return null; } try { inputStream = zipFile.getInputStream(zipEntry); } catch (IOException e) { e.printStackTrace(); return null; } DiskCache.Editor diskCacheEditor = diskCache.edit(diskCacheKey); OutputStream outputStream; if (diskCacheEditor != null) { try { outputStream = new BufferedOutputStream(diskCacheEditor.newOutputStream(), 8 * 1024); } catch (IOException e) { e.printStackTrace(); diskCacheEditor.abort(); SketchUtils.close(inputStream); return null; } } else { outputStream = new ByteArrayOutputStream(); } try { byte[] buffer = new byte[8 * 1024]; int realLength; while (true) { realLength = inputStream.read(buffer); if (realLength < 0) { break; } outputStream.write(buffer, 0, realLength); } if (diskCacheEditor != null) { diskCacheEditor.commit(); } } catch (DiskLruCache.EditorChangedException e) { e.printStackTrace(); diskCacheEditor.abort(); return null; } catch (IOException e) { e.printStackTrace(); if (diskCacheEditor != null) { diskCacheEditor.abort(); } return null; } catch (DiskLruCache.ClosedException e) { e.printStackTrace(); diskCacheEditor.abort(); return null; } catch (DiskLruCache.FileNotExistException e) { e.printStackTrace(); diskCacheEditor.abort(); return null; } finally { SketchUtils.close(inputStream); SketchUtils.close(outputStream); } if (diskCacheEditor != null) { xpkIconDiskCacheEntry = diskCache.get(diskCacheKey); if (xpkIconDiskCacheEntry != null) { return new PreProcessResult(xpkIconDiskCacheEntry, ImageFrom.LOCAL); } else { if (SLogType.REQUEST.isEnabled()) { SLog.w(SLogType.REQUEST, logName, "not found xpk icon cache file. %s", loadRequest.getKey()); } return null; } } else { return new PreProcessResult(((ByteArrayOutputStream) outputStream).toByteArray(), ImageFrom.LOCAL); } } }