static final String LOG_CACHE_IMAGE_IN_MEMORY = "Cache image in memory [%s]"; static final String LOG_CACHE_IMAGE_ON_DISC = "Cache image on disc [%s]"; static final String LOG_DELAY_BEFORE_LOADING = "Delay %d ms before loading...  [%s]"; static final String LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING = "...Get cached bitmap from memory after waiting. [%s]"; static final String LOG_LOAD_IMAGE_FROM_DISC_CACHE = "Load image from disc cache [%s]"; static final String LOG_LOAD_IMAGE_FROM_INTERNET = "Load image from Internet [%s]"; static final String LOG_POSTPROCESS_IMAGE = "PostProcess image before displaying [%s]"; static final String LOG_PREPROCESS_IMAGE = "PreProcess image before caching in memory [%s]"; static final String LOG_RESUME_AFTER_PAUSE = ".. Resume loading [%s]"; static final String LOG_START_DISPLAY_IMAGE_TASK = "Start display image task [%s]"; static final String LOG_TASK_CANCELLED = "ImageView is reused for another image. Task is cancelled. [%s]"; static final String LOG_TASK_INTERRUPTED = "Task was interrupted [%s]"; static final String LOG_WAITING_FOR_IMAGE_LOADED = "Image already is loading. Waiting... [%s]"; static final String LOG_WAITING_FOR_RESUME = "ImageLoader is paused. Waiting...  [%s]"; public class Debug {
    
    static String TAG = "DebugTools";

    public static  boolean DEBUG = true; 
    public static void dLog(String tag,String str){
        if(!DEBUG){
            return;
        }

        Log.v(tag, str);
        
    }
    public static void log(String tag,String str){
        
        Log.v(tag, str);
        
    }
    public static void dLog(String str){
        dLog(TAG, str);
    }
    public static void dLog(Object o){
        dLog(TAG, o.toString());
    }
    public static void dLog(Object[] os){
        for(Object o:os){
            dLog(TAG, o.toString());
        }
    }
    public static void dLog(Throwable t){
        if(!DEBUG){
            return;
        }
        
        Log.e(TAG, "",t);
        
    }
    public static void log(String str){
        log(TAG, str);
    }
    
    /**
     * init user for debug 
     * */
    public static void initUserForTest(EditText user,EditText pass){
        if(!DEBUG){
            return;
        }
        if(user!=null&&pass!=null){
//            pass.setText(AppSetting.PASSWORD);
//            user.setText(AppSetting.USER);
//            dLog("p : "+AppSetting.PASSWORD+" u: "+AppSetting.USER);
        }
        
    }
    public static void dLog(String tag,String str,Exception e){
        if(!DEBUG){
            return;
        }
        
        Log.e(tag, str,e);
        
    }
    
    /**
     * easy to modify control
     * */
    public static void log(String tag,String str,Exception e){
        
        Log.e(tag, str,e);
        
    }
    
    public static void dLog(String tag,Exception e){
        dLog(tag, "",e);
    }
    public static void dLog(Exception e){
        dLog(TAG, "",e);
    }
    public static void dLogCursor(Exception e){
        dLog("sfa_cursor", "cursor exception ",e);
    }
    
    public static void log( Exception e){
        log(TAG, "",e);
    }
    public static void log(String tag,Exception e){
        log(tag, "",e);
    }
    
    /********
     * ºÄÊ±´òÓ¡
     */
    private static Map<String,Long> times=new HashMap<String, Long>();
    public static void beginTime(String name){
    	times.put(name, System.currentTimeMillis());
    }
    public static void traceTime(String name,String msg){
    	Long start = times.get(name);
    	dLog(msg+"----ºÄÊ±:"+(System.currentTimeMillis()-start));
    }
    public static void endTime(String name){
    	Long start = times.get(name);
    	dLog(name+"----ºÄÊ±:"+(System.currentTimeMillis()-start));
    	times.remove(name);
    }
}
 public interface ImageLoadingListener {

	/**
	 * Is called when image loading task was started
	 * 
	 * @param imageUri Loading image URI
	 * @param view View for image
	 */
	void onLoadingStarted(String imageUri, View view);

	/**
	 * Is called when an error was occurred during image loading
	 * 
	 * @param imageUri Loading image URI
	 * @param view View for image
	 * @param failReason {@linkplain FailReason The reason} why image loading was failed
	 */
	void onLoadingFailed(String imageUri, View view, FailReason failReason);

	/**
	 * Is called when image is loaded successfully (and displayed in View if one was specified)
	 * 
	 * @param imageUri Loaded image URI
	 * @param view View for image
	 * @param loadedImage Bitmap of loaded and decoded image
	 */
	void onLoadingComplete(String imageUri, View view, Bitmap loadedImage,String filePath);

	/**
	 * Is called when image loading task was cancelled because View for image was reused in newer task
	 * 
	 * @param imageUri Loading image URI
	 * @param view View for image
	 */
	void onLoadingCancelled(String imageUri, View view);
} public final class IoUtils {

	private static final int BUFFER_SIZE = 8 * 1024; // 8 KB 

	private IoUtils() {
	}

	public static void copyStream(InputStream is, OutputStream os) throws IOException {
		byte[] bytes = new byte[BUFFER_SIZE];
		while (true) {
			int count = is.read(bytes, 0, BUFFER_SIZE);
			if (count == -1) {
				break;
			}
			os.write(bytes, 0, count);
		}
	}

	public static void closeSilently(Closeable closeable) {
	    if(null!=closeable){
	        try {
	            closeable.close();
	        } catch (Exception e) {
	            // Do nothing
	        }
	    }
	}
} public final class StorageUtils {

	private static final String INDIVIDUAL_DIR_NAME = "uil-images";

	private StorageUtils() {
	}

	/**
	 * Returns application cache directory. Cache directory will be created on SD card
	 * <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted. Else - Android defines cache directory on
	 * device's file system.
	 * 
	 * @param context Application context
	 * @return Cache {@link File directory}
	 */
	public static File getCacheDirectory(Context context) {
		File appCacheDir = null;
		if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
			appCacheDir = getExternalCacheDir(context);
		}
		if (appCacheDir == null) {
			appCacheDir = context.getCacheDir();
		}
		return appCacheDir;
	}

	/**
	 * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
	 * created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted. Else -
	 * Android defines cache directory on device's file system.
	 * 
	 * @param context Application context
	 * @return Cache {@link File directory}
	 */
	public static File getIndividualCacheDirectory(Context context) {
		File cacheDir = getCacheDirectory(context);
		File individualCacheDir = new File(cacheDir, INDIVIDUAL_DIR_NAME);
		if (!individualCacheDir.exists()) {
			if (!individualCacheDir.mkdir()) {
				individualCacheDir = cacheDir;
			}
		}
		return individualCacheDir;
	}

	/**
	 * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
	 * is mounted. Else - Android defines cache directory on device's file system.
	 * 
	 * @param context Application context
	 * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
	 * @return Cache {@link File directory}
	 */
	public static File getOwnCacheDirectory(Context context, String cacheDir) {
		File appCacheDir = null;
		if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
			appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
		}
		if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
			appCacheDir = context.getCacheDir();
		}
		return appCacheDir;
	}

	public static File getDiscCacheFile(String uri,DiscCacheAware discCache,DiscCacheAware reserveDiscCache){
        File imageFile = discCache.get(uri);
        File cacheDir = imageFile.getParentFile();
        DebugUtil.dLog("getDiscCacheFile:"+uri+",imageFile:"+imageFile.getAbsolutePath()+",cacheDir:"+cacheDir.getAbsolutePath());
        if (cacheDir == null || (!cacheDir.exists() && !cacheDir.mkdirs())) {
            imageFile = reserveDiscCache.get(uri);
        }
        return imageFile;
	}
	/**
	 * sdcard/android/data/com.android.liu.two/cache
	 * <p> sdcard/android/data/pkgName/cache
	 * */
	private static File getExternalCacheDir(Context context) {
		File dataDir = new File(Environment.getExternalStorageDirectory(), Configs.storeName);
		File appCacheDir = new File(dataDir, "image");
//		File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
//		File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
		if (!appCacheDir.exists()) {
			if (!appCacheDir.mkdirs()) {
				L.w("Unable to create external cache directory");
				return null;
			}
			try {
				new File(appCacheDir, ".nomedia").createNewFile();
			} catch (IOException e) {
				L.i("Can't create \".nomedia\" file in application external cache directory");
			}
		}
		return appCacheDir;
	}
}
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_CACHE_IMAGE_IN_MEMORY;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_CACHE_IMAGE_ON_DISC;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_DELAY_BEFORE_LOADING;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_LOAD_IMAGE_FROM_DISC_CACHE;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_LOAD_IMAGE_FROM_INTERNET;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_POSTPROCESS_IMAGE;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_PREPROCESS_IMAGE;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_RESUME_AFTER_PAUSE;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_START_DISPLAY_IMAGE_TASK;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_TASK_CANCELLED;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_TASK_INTERRUPTED;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_WAITING_FOR_IMAGE_LOADED;
import static com.nostra13.universalimageloader.core.ImageLoader.LOG_WAITING_FOR_RESUME;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import android.widget.ImageView;
import com.android.apis.util.Debug;
import com.nostra13.universalimageloader.cache.disc.DiscCacheAware;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.FailReason.FailType;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.assist.ViewScaleType;
import com.nostra13.universalimageloader.core.download.ImageDownloader;
import com.nostra13.universalimageloader.utils.IoUtils;
import com.nostra13.universalimageloader.utils.L;
import com.nostra13.universalimageloader.utils.StorageUtils;
/*******************************************************************************
 * Copyright 2011-2013 Sergey Tarasevich
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package com.nostra13.universalimageloader.core;






/**
 * Presents load'n'display image task. Used to load image from Internet or file system, decode it to {@link Bitmap}, and
 * display it in {@link ImageView} using {@link DisplayBitmapTask}.
 * 
 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 * @since 1.3.1
 * @see ImageLoaderConfiguration
 * @see ImageLoadingInfo
 */
final class LoadAndDisplayImageTask implements Runnable {

	private static final int ATTEMPT_COUNT_TO_DECODE_BITMAP = 3;
	private static final int BUFFER_SIZE = 8 * 1024; // 8 Kb

	private static final String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%";

	private final ImageLoaderEngine engine;
	private final ImageLoadingInfo imageLoadingInfo;
	private final Handler handler;

	// Helper references
	private final ImageLoaderConfiguration configuration;
	private final ImageDownloader downloader;
	private final ImageDownloader networkDeniedDownloader;
	private final ImageDownloader slowNetworkDownloader;
	private final boolean loggingEnabled;
	final String uri;
	final String encodedUri;
	private final String memoryCacheKey;
	final ImageView imageView;
	private final ImageSize targetSize;
	final DisplayImageOptions options;
	final ImageLoadingListener listener;

	public LoadAndDisplayImageTask(ImageLoaderEngine engine, ImageLoadingInfo imageLoadingInfo, Handler handler) {
		this.engine = engine;
		this.imageLoadingInfo = imageLoadingInfo;
		this.handler = handler;

		configuration = engine.configuration;
		downloader = configuration.downloader;
		networkDeniedDownloader = configuration.networkDeniedDownloader;
		slowNetworkDownloader = configuration.slowNetworkDownloader;
		loggingEnabled = configuration.loggingEnabled;
		uri = imageLoadingInfo.uri;
		encodedUri = Uri.encode(uri, ALLOWED_URI_CHARS);
		memoryCacheKey = imageLoadingInfo.memoryCacheKey;
		imageView = imageLoadingInfo.imageView;
		targetSize = imageLoadingInfo.targetSize;
		options = imageLoadingInfo.options;
		listener = imageLoadingInfo.listener;
	}

	@Override
	public void run() {
		AtomicBoolean pause = engine.getPause();
		if (pause.get()) {
			synchronized (pause) {
				log(LOG_WAITING_FOR_RESUME, memoryCacheKey);
				try {
					pause.wait();
				} catch (InterruptedException e) {
					L.e(LOG_TASK_INTERRUPTED, memoryCacheKey);
					return;
				}
				log(LOG_RESUME_AFTER_PAUSE, memoryCacheKey);
			}
		}
		if (checkTaskIsNotActual()) return;

		if (options.shouldDelayBeforeLoading()) {
			log(LOG_DELAY_BEFORE_LOADING, options.getDelayBeforeLoading(), memoryCacheKey);
			try {
				Thread.sleep(options.getDelayBeforeLoading());
			} catch (InterruptedException e) {
				L.e(LOG_TASK_INTERRUPTED, memoryCacheKey);
				return;
			}

			if (checkTaskIsNotActual()) return;
		}

		ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock;
		log(LOG_START_DISPLAY_IMAGE_TASK, memoryCacheKey);
		if (loadFromUriLock.isLocked()) {
			log(LOG_WAITING_FOR_IMAGE_LOADED, memoryCacheKey);
		}

		loadFromUriLock.lock();
		Bitmap bmp;
		try {
			if (checkTaskIsNotActual()) return;

			bmp = configuration.memoryCache.get(memoryCacheKey);
			if (bmp == null) {
				bmp = tryLoadBitmap();
				if (bmp == null) return;

				if (checkTaskIsNotActual() || checkTaskIsInterrupted()) return;

				if (options.shouldPreProcess()) {
					log(LOG_PREPROCESS_IMAGE, memoryCacheKey);
					bmp = options.getPreProcessor().process(bmp);
				}
				if (options.isCacheInMemory()) {
					log(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey);
					configuration.memoryCache.put(memoryCacheKey, bmp);
				}
			} else {
				log(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey);
			}

			if (options.shouldPostProcess()) {
				log(LOG_POSTPROCESS_IMAGE, memoryCacheKey);
				bmp = options.getPostProcessor().process(bmp);
			}
		} finally {
			loadFromUriLock.unlock();
		}

		if (checkTaskIsNotActual() || checkTaskIsInterrupted()) return;

		DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine);
		displayBitmapTask.setLoggingEnabled(loggingEnabled);
		handler.post(displayBitmapTask);
	}

	/**
	 * Check whether the image URI of this task matches to image URI which is actual for current ImageView at this
	 * moment and fire {@link ImageLoadingListener#onLoadingCancelled()} event if it doesn't.
	 */
	private boolean checkTaskIsNotActual() {
		String currentCacheKey = engine.getLoadingUriForView(imageView);
		// Check whether memory cache key (image URI) for current ImageView is actual. 
		// If ImageView is reused for another task then current task should be cancelled.
		boolean imageViewWasReused = !memoryCacheKey.equals(currentCacheKey);
		if (imageViewWasReused) {
			handler.post(new Runnable() {
				@Override
				public void run() {
					listener.onLoadingCancelled(uri, imageView);
				}
			});
		}

		if (imageViewWasReused) log(LOG_TASK_CANCELLED, memoryCacheKey);
		return imageViewWasReused;
	}

	/** Check whether the current task was interrupted */
	private boolean checkTaskIsInterrupted() {
		boolean interrupted = Thread.interrupted();
		if (interrupted) log(LOG_TASK_INTERRUPTED, memoryCacheKey);
		return interrupted;
	}

	private Bitmap tryLoadBitmap() {
		DiscCacheAware discCache = configuration.discCache;
        File imageFile = StorageUtils.getDiscCacheFile(uri, configuration.discCache, configuration.reserveDiscCache);