android 项目中开发为了节省周期又或者不重复造轮子都会选择一些开源框架来设计我们的app,而imageloader是加载网络本地图片的一大利器,但是其本身并未提供加密和解密的方法,需要我们从源码中自己改写。
首先简略的说下imageloader的工作原理,在displayImage方法中我们可以看到:
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);//获软引用的图片
if (bmp != null && !bmp.isRecycled()) {
L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);
if (options.shouldPostProcess()) {
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
options, listener, progressListener, engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,
defineHandler(options));
if (options.isSyncLoading()) {
displayTask.run();
} else {
engine.submit(displayTask);
}
} else {
options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
}
} else {如果没有则主要跑<span style="font-family: Arial, Helvetica, sans-serif;">LoadAndDisplayImageTask方法来检索本地缓存文件或网络下载</span>
if (options.shouldShowImageOnLoading()) {
imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));
} else if (options.isResetViewBeforeLoading()) {
imageAware.setImageDrawable(null);
}
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
options, listener, progressListener, engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
defineHandler(options));
if (options.isSyncLoading()) {
displayTask.run();
} else {
engine.submit(displayTask);
}
}
再追溯到
LoadAndDisplayImageTask文件
bmp = configuration.memoryCache.get(memoryCacheKey);//再次检索
if (bmp == null || bmp.isRecycled()) {
bmp = tryLoadBitmap();//尝试从别的地方获取,也就是从文件和网络获取了
if (bmp == null) return; // listener callback already was fired
checkTaskNotActual();
checkTaskInterrupted();
if (options.shouldPreProcess()) {
L.d(LOG_PREPROCESS_IMAGE, memoryCacheKey);
bmp = options.getPreProcessor().process(bmp);
if (bmp == null) {
L.e(ERROR_PRE_PROCESSOR_NULL, memoryCacheKey);
}
}
if (bmp != null && options.isCacheInMemory()) {
L.d(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey);
configuration.memoryCache.put(memoryCacheKey, bmp);
}
} else {
loadedFrom = LoadedFrom.MEMORY_CACHE;
L.d(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey);
}
那么,从网络下载到本地, 再从本地取出解析并加载到页面上就是我们关注的地方了,首先我们看到
tryLoadBitmap
方法过程中,会判断diskCache中是否有我们的缓存文件,如果有则解析,没有通过tryCacheImageOnDisk方法以及downloadImage(),resizeAndSaveImage()来缓存到本地并解析。
那么直接看加密和解密的地方。
加密:
查看源码,我们可以看到IoUtils.java中就是我们下载image到本地的关键之处
public static boolean copyStream(InputStream is, OutputStream os,
CopyListener listener, int bufferSize) throws IOException {
int current = 0;
int total = is.available();
if (total <= 0) {
total = DEFAULT_IMAGE_TOTAL_SIZE;
}
int read;
if (shouldStopLoading(listener, current, total))
return false;
// while ((count = is.read(bytes, 0, bufferSize)) != -1) {
// os.write(bytes, 0, count);
// current += count;
// if (shouldStopLoading(listener, current, total))
// return false;
// }
while ((read = is.read()) != -1) {
os.write(read ^ 0x99);//这个随意,右移>>或<<都可
current++;
if (shouldStopLoading(listener, current, total))
return false;
}
os.flush();
return true;
}
直接在写的方法中,右移之类的改变自己的数据即可
解密:BaseImageDecoder方法中
public Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException {
Bitmap decodedBitmap;
ImageFileInfo imageInfo;
InputStream imageStream = getImageStream(decodingInfo);
if (imageStream == null) {
L.e(ERROR_NO_IMAGE_STREAM, decodingInfo.getImageKey());
return null;
}
try {
imageInfo = defineImageSizeAndRotation(imageStream, decodingInfo);
imageStream = resetStream(imageStream, decodingInfo);
Options decodingOptions = prepareDecodingOptions(
imageInfo.imageSize, decodingInfo);
decodedBitmap =readBitmap(imageStream, decodingOptions);
// decodedBitmap = BitmapFactory.decodeStream(imageStream, null,
// decodingOptions);
} finally {
IoUtils.closeSilently(imageStream);
}
if (decodedBitmap == null) {
L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey());
} else {
decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap,
decodingInfo, imageInfo.exif.rotation,
imageInfo.exif.flipHorizontal);
}
return decodedBitmap;
}
public Bitmap readBitmap(InputStream is,Options decodingOptions) {
Bitmap bitmap = null;
List<Byte> list = new ArrayList();
try {
int read;
while ((read = is.read()) > -1) {
read = read ^ 0X99;
list.add((byte) read);
}
byte[] arr = new byte[list.size()];
int i = 0;
for (Byte item : list) {
arr[i++] = item;
}
bitmap = BitmapFactory.decodeByteArray(arr, 0, list.size(),decodingOptions);
System.out.println(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
即可。谢谢