package com.androidol.util.tiles;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.androidol.constants.UtilConstants;
import com.androidol.events.Event;
import com.androidol.events.TileEvents;
import com.androidol.tile.Tile;
import com.androidol.util.Util;
public class TileHttpFutureLoader extends TileHttpLoader implements UtilConstants {
/**
* Constructor TileHttpLoader
*
* @param context
* @param tileFSLoader
*/
public TileHttpFutureLoader(Context context, TileFileSystemLoader tileFSLoader, TileEvents tileEvents) {
super(context, tileFSLoader, tileEvents);
}
/**
* API Method: loadHttpTileAsync
*
* @param url
* @param callback
*/
public Future<?> loadHttpTileAsync(final String url, final String signature, final Tile tile) {
Future<?> future = this.threadPool.submit(
new Runnable() {
@Override
public void run() {
InputStream in = null;
OutputStream out = null;
try {
//Thread.sleep(1000);
//Util.printDebugMessage("@...started a thread for http loading...signature: " + signature);
//Util.printDebugMessage("...load tile from url: " + url + "...");
in = new BufferedInputStream(new URL(url).openStream(), IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
StreamUtils.copy(in, out);
out.flush();
byte[] data = dataStream.toByteArray();
TileHttpFutureLoader.this.tileFSLoader.saveFile(url, data);
//Util.printDebugMessage("...tile saved to: " + url + "...");
/*
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Event evt = new Event(TileEvents.FS_LOAD_SUCCESS);
evt.attach("tile", tile);
evt.attach("bitmap", bitmap);
TileHttpLoader.this.events.triggerEvent(TileEvents.HTTP_LOAD_SUCCESS, new Event(TileEvents.HTTP_LOAD_SUCCESS, evt));
*/
TileHttpFutureLoader.this.events.triggerEvent(TileEvents.HTTP_LOAD_SUCCESS, new Event(TileEvents.HTTP_LOAD_SUCCESS, url));
synchronized(this) {
TileHttpFutureLoader.this.pendingQueue.remove(url);
}
//Util.printDebugMessage(" ...tile " + url + " removed from TileHttpLoader pending queue...");
//Util.printDebugMessage(" ...TileHttpLoader pending queue size: " + TileHttpLoader.this.pendingQueue.size());
// TODO: when doing threads canceling, what will happen if a loading gets canceled? will it throw exception?
} catch(Exception e) {
//TileHttpLoader.this.events.triggerEvent(TileEvents.HTTP_LOAD_FAILURE, new Event(TileEvents.HTTP_LOAD_FAILURE, url));
//Util.printErrorMessage(e.getClass().getName());
Util.printErrorMessage("...error loading tile from http...exception: " + e.getMessage());
/*
* TODO What to do when loading tile caused an error?
* Also remove it from the mPending?
* Doing not blocks it for the whole existence of this TileDownloder.
*/
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
TileHttpFutureLoader.this.pendingQueue.remove(url);
//Util.printDebugMessage("@...finished a thread for http loading...signature: " + signature);
}
}
});
return future;
}
/**
* getTileAsync
*
* @param url
* @param callback
*/
public Future<?> getTileAsync(final String url, final String signature, Tile tile) {
if(this.pendingQueue.contains(url)) {
//Util.printDebugMessage("...tile " + url + " already in the queue...skip loading from http....");
return null;
}
synchronized(this) {
this.pendingQueue.add(url);
}
//Util.printDebugMessage(" ...tile " + url + " added in TileHttpLoader pending queue...queue size: " + this.pendingQueue.size());
//Util.printDebugMessage(" ...TileHttpLoader pending queue size: " + TileHttpLoader.this.pendingQueue.size());
return loadHttpTileAsync(url, signature, tile);
}
}