package com.androidol.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.androidol.Map;
import com.androidol.R;
import com.androidol.events.Event;
import com.androidol.events.TileEvents;
import com.androidol.layer.Layer;
import com.androidol.layer.osm.Mapnik;
import com.androidol.test.io.TestAndoridSDCardIO;
import com.androidol.test.proj4j.TestProjection;
import com.androidol.util.Util;
import com.androidol.util.tiles.StreamUtils;
import com.androidol.util.tiles.TileHttpLoader;
import com.vividsolutions.jts.geom.Coordinate;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.ZoomControls;
public class TestActivity extends Activity {
protected static final int THREAD_POOL_SIZE = 8;
protected static final int TEST_TILES_NUM = 8;
protected ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
protected ExecutorService threadPool2 = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
protected ThreadGroup threadGroup = new ThreadGroup("thread_group");
protected int zoom = 0;
protected double centerX = 0.0;
protected double centerY = 0.0;
protected Context context = null;
protected ConcurrentHashMap<String, ArrayList<Future<Bitmap>>> queue = new ConcurrentHashMap<String, ArrayList<Future<Bitmap>>>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
this.context = findViewById(R.id.layout).getContext();
// testing thread canceling
/*
ZoomControls zoomControls = (ZoomControls)findViewById(R.id.zoomcontrols);
zoomControls.setZoomSpeed(340); // half second
zoomControls.setOnZoomInClickListener(new OnClickListener() {
public void onClick(View view) {
zoomIn();
}
});
zoomControls.setOnZoomOutClickListener(new OnClickListener() {
public void onClick(View view) {
zoomOut();
}
});
*/
//testThreading();
/*
TestAndoridSDCardIO test = new TestAndoridSDCardIO();
test.testEnvironment();
//for(int i=0; i<100; i++) {
//test.testReadFileFromSDCard();
test.testWriteFileToSDCard();
//test.testReadFileFromContext(this.context);
//}
*/
TestProjection.testProjection();
}
/*
private void zoomIn() {
//Util.printDebugMessage("...zoomin...");
this.zoom = this.zoom + 1;
String signature = "signature_" + String.valueOf(this.zoom);
//
Iterator<String> iterator = this.queue.keySet().iterator();
while(iterator.hasNext()) {
String key = (String)iterator.next();
ArrayList<Future<Bitmap>> threads = this.queue.get(key);
if(threads != null) {
Util.printDebugMessage("...should cancel how many threads? " + threads.size());
for(int i=0; i<threads.size(); i++) {
if(threads.get(i) != null) {
if(threads.get(i).isDone() == false) {
Util.printDebugMessage("...##cancel thread with signature: " + key);
if(threads.get(i).cancel(true)) {
Util.printDebugMessage("@@...successfully cancelled thread with signature: " + key);
} else {
Util.printDebugMessage("...fail to cancel thread with signature: " + key);
}
} else {
Util.printDebugMessage("...cuz it's done can not cancel thread with signature: " + key);
}
}
//threads.remove(i);
}
}
iterator.remove();
}
//ArrayList<Future<Bitmap>> futures = new ArrayList<Future<Bitmap>>();
for(int i=0, j=79; i<TEST_TILES_NUM; i++, j++) {
this.threadPool2.submit(
new TileDrawerRunnable("http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/8/70/"+j, signature)
);
}
//this.queue.put(signature, futures);
}
private void zoomOut() {
Util.printDebugMessage("...zoomout...");
}
private class TileDrawerRunnable implements Runnable {
protected String url = "";
protected String signature = "";
public TileDrawerRunnable(String url, String signature) {
super();
this.url = url;
this.signature = signature;
}
@Override
public void run() {
TileLoaderCallable tileLoader = new TileLoaderCallable(url, signature);
Future<Bitmap> future = TestActivity.this.threadPool.submit(tileLoader);
if(TestActivity.this.queue.get(this.signature) == null) {
ArrayList<Future<Bitmap>> futures = new ArrayList<Future<Bitmap>>();
TestActivity.this.queue.put(this.signature, futures);
}
TestActivity.this.queue.get(this.signature).add(future);
//Util.printDebugMessage("...add to queue...signaturee: " + this.signature + "...tile: " + this.url.subSequence(this.url.length()-2, this.url.length()));
try {
Bitmap bitmap = (Bitmap)future.get();
//Util.printDebugMessage("...get back result...signaturee: " + this.signature + "...tile: " + this.url.subSequence(this.url.length()-2, this.url.length()));
if(bitmap!=null && bitmap.isRecycled()==false) {
Util.printDebugMessage("...ready to draw...signaturee: " + this.signature + "...tile: " + this.url.subSequence(this.url.length()-2, this.url.length()));
}
} catch(ExecutionException e) {
Util.printDebugMessage(e.getMessage());
} catch(InterruptedException e) {
Util.printDebugMessage(e.getMessage());
}
}
}
private class TileLoaderCallable implements Callable<Bitmap> {
protected String url = "";
protected String signature = "";
public TileLoaderCallable(String url, String signature) {
super();
this.url = url;
this.signature = signature;
}
@Override
public Bitmap call() {
InputStream in = null;
OutputStream out = null;
Bitmap bitmap = null;
try {
Util.printDebugMessage("...start loading...signature: " + TileLoaderCallable.this.signature + "...tile: " + TileLoaderCallable.this.url.subSequence(TileLoaderCallable.this.url.length()-2, TileLoaderCallable.this.url.length()) + "...");
Thread.sleep(5000);
in = new BufferedInputStream(new URL(url).openStream(), 8192);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 8192);
StreamUtils.copy(in, out);
out.flush();
byte[] data = dataStream.toByteArray();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
if(bitmap!=null && bitmap.isRecycled()==false) {
bitmap.recycle();
}
Util.printDebugMessage("...finished loading signature: " + TileLoaderCallable.this.signature + "...tile: " + TileLoaderCallable.this.url.subSequence(TileLoaderCallable.this.url.length()-2, TileLoaderCallable.this.url.length()) + "...");
} catch(IOException e) {
Util.printDebugMessage(e.getMessage());
} catch(InterruptedException e) {
Util.printDebugMessage(e.getMessage());
} finally {
Util.printDebugMessage("...do finally " + TileLoaderCallable.this.signature + "...tile: " + TileLoaderCallable.this.url.subSequence(TileLoaderCallable.this.url.length()-2, TileLoaderCallable.this.url.length()) + "...");
}
//Util.printDebugMessage("...before quiting " + TileLoaderCallable.this.signature + "...tile: " + TileLoaderCallable.this.url.subSequence(TileLoaderCallable.this.url.length()-2, TileLoaderCallable.this.url.length()) + "...");
return bitmap;
}
}
*/
// ==================================================================================================
// test code for threading
// ==================================================================================================
/*
private void testThreading() {
for(int i=0; i<THREAD_POOL_SIZE; i++) {
// thread group and setUncaughtExceptionHandler
// NOTE: thread doesn't count in group when thread passed into ExecutorService
// NOTE: thread name doesn't apply in group when thread passed into ExecutorService
Thread thread = new TestThread(this.threadGroup, "test-thread-"+i); //
// NOTE: setUncaughtExceptionHandler() doesn't take effect when thread passed into ExecutorService
thread.setUncaughtExceptionHandler(
new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// TODO Auto-generated method stub
Util.printDebugMessage("...runtime exception caught...");
}
}
);
// Or call static setDefaultUncaughtExceptionHandler() on Thread
Thread.setDefaultUncaughtExceptionHandler(
new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// TODO Auto-generated method stub
Util.printDebugMessage("...runtime exception caught...");
}
}
);
thread.start();
this.threadPool.execute(new TestThread());
// anonymous class implements Runnable
this.threadPool.execute(
new Runnable() {
@Override
public void run() {
Util.printDebugMessage("...started a thread for fs loading...");
try {
Util.printDebugMessage("...is thread interrupted " + Thread.currentThread().isInterrupted() + "...");
// interrupt() only set the interrupted flag to true, not forcibly terminating a thread
Thread.currentThread().interrupt();
Util.printDebugMessage("...is thread interrupted after interrupt() call..." + Thread.currentThread().isInterrupted() + "...");
if(Thread.currentThread().isInterrupted()) {
Util.printDebugMessage("...you can choose to terminate the thread here...");
}
Thread.interrupted(); // Thread.interrupted() reset interrupted flag to false again
Util.printDebugMessage("...is thread interrupted after Thread.interrupted() call..." + Thread.currentThread().isInterrupted() + "...");
//
} catch(InterruptedException e) {
} catch(Exception e) {
//
} finally {
//
Util.printDebugMessage("...finished a thread for fs loading...");
}
}
}
);
}
}
private class TestThread extends Thread {
public TestThread() {
super();
}
public TestThread(ThreadGroup group, String threadName) {
super(group, threadName);
}
@Override
public void run() {
Util.printDebugMessage("...started a thread: " + Thread.currentThread().getName() + "...");
Util.printDebugMessage("...active threads in thread group: " + TestActivity.this.threadGroup.activeCount() + "...");
Coordinate coord = null;
coord.distance(coord);
try {
//Util.printDebugMessage("...is thread interrupted " + Thread.currentThread().isInterrupted() + "...");
// interrupt() only set the interrupted flag to true, not forcibly terminating a thread
Thread.currentThread().interrupt();
//Util.printDebugMessage("...is thread interrupted after interrupt() call..." + Thread.currentThread().isInterrupted() + "...");
if(Thread.currentThread().isInterrupted()) {
//Util.printDebugMessage("...you can choose to terminate the thread here...");
}
Thread.interrupted(); // Thread.interrupted() reset interrupted flag to false again
//Util.printDebugMessage("...is thread interrupted after Thread.interrupted() call..." + Thread.currentThread().isInterrupted() + "...");
//
} catch(InterruptedException e) {
Util.printDebugMessage("...terminate a thread: " + Thread.currentThread().getName() + "...");
return;
} catch(Exception e) {
//
} finally {
//
Util.printDebugMessage("...ended a thread: " + Thread.currentThread().getName() + "...");
}
}
}
*/
// ==================================================================================================
// Test the memory limit of Android application loading bitmap using BitmapFactory.decodeByteArray
// ==================================================================================================
/*
protected Bitmap[] cache = new Bitmap[81];
protected long totalSize = 0;
private void testLoadBitmapsSingleThread() {
for(int i=79; i<145; i++) {
InputStream in = null;
OutputStream out = null;
final int idx = i;
try {
String url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/tile/8/70/" + idx + ".jpg";
Util.printDebugMessage("...load tile from url: tile/8/70/" + idx + "...");
in = new BufferedInputStream(new URL(url).openStream(), 8192);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 8192);
StreamUtils.copy(in, out);
out.flush();
byte[] data = dataStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//TestActivity.this.cache[idx-79] = bitmap;
TestActivity.this.cache[idx-79] = Bitmap.createBitmap(bitmap);
bitmap.recycle();
Util.printDebugMessage(" ...bytes decoded: " + data.length/1024 + " kb");
TestActivity.this.totalSize = TestActivity.this.totalSize + data.length/1024;
Util.printDebugMessage(" ...bytes decoded: " + TestActivity.this.totalSize + " kb");
} catch(Exception e) {
Util.printErrorMessage("...error loading tile...exception: " + e.getClass().getSimpleName() + "...", e);
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
}
}
}
*/
/*
private void testLoadBitmapsMultiThreads() {
for(int i=79; i<145; i++) {
final int idx = i;
this.threadPool.execute(
new Runnable() {
@Override
public void run() {
InputStream in = null;
OutputStream out = null;
try {
String url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/tile/8/70/" + idx + ".jpg";
Util.printDebugMessage("...load tile from url: tile/8/70/" + idx + "...");
in = new BufferedInputStream(new URL(url).openStream(), 8192);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 8192);
StreamUtils.copy(in, out);
out.flush();
byte[] data = dataStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
TestActivity.this.cache[idx-79] = Bitmap.createBitmap(bitmap);
bitmap.recycle();
Util.printDebugMessage(" ...bytes decoded: " + data.length/1024 + " kb");
TestActivity.this.totalSize = TestActivity.this.totalSize + data.length/1024;
Util.printDebugMessage(" ...bytes decoded: " + TestActivity.this.totalSize + " kb");
} catch(Exception e) {
Util.printErrorMessage("...error loading tile...exception: " + e.getClass().getSimpleName() + "...", e);
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
}
}
});
}
}
*/
}