diff --git a/android/README.txt b/android/README.txt
index 68719911f..c9a708263 100644
--- a/android/README.txt
+++ b/android/README.txt
@@ -12,7 +12,7 @@ ant
ant install
#then run the debugger
-$A/ddms &
+../../android-sdk-linux_x86-1.1_r1/tools/ddms &
#to rebuild and reinstall to emulator:
ant reinstall
diff --git a/android/build.xml b/android/build.xml
index 9f4e7b0b9..a7b411996 100644
--- a/android/build.xml
+++ b/android/build.xml
@@ -26,10 +26,10 @@
-
+
+ value="${basedir}\${external-libs}"
+ else="${basedir}/${external-libs}" >
@@ -105,6 +105,8 @@
+
+
@@ -144,13 +146,19 @@
destdir="${outdir-classes}"
bootclasspath="${android-jar}">
-
+
-
+
+
+
+
+
+
+
@@ -162,7 +170,7 @@
-
+
diff --git a/android/src/net/i2p/util/LogWriter.java b/android/src/net/i2p/util/LogWriter.java
new file mode 100644
index 000000000..847730d4f
--- /dev/null
+++ b/android/src/net/i2p/util/LogWriter.java
@@ -0,0 +1,152 @@
+package net.i2p.util;
+
+/*
+ * public domain
+ *
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * bridge to android logging
+ *
+ * @author zzz
+ */
+class LogWriter implements Runnable {
+ private final static long CONFIG_READ_ITERVAL = 10 * 1000;
+ private long _lastReadConfig = 0;
+ private long _numBytesInCurrentFile = 0;
+ private OutputStream _currentOut; // = System.out
+ private int _rotationNum = -1;
+ private String _logFilenamePattern;
+ private File _currentFile;
+ private LogManager _manager;
+
+ private boolean _write;
+
+ private LogWriter() { // nop
+ }
+
+ public LogWriter(LogManager manager) {
+ _manager = manager;
+ }
+
+ public void stopWriting() {
+ _write = false;
+ }
+
+ public void run() {
+ _write = true;
+ try {
+ while (_write) {
+ flushRecords();
+ rereadConfig();
+ }
+ System.err.println("Done writing");
+ } catch (Exception e) {
+ System.err.println("Error writing the logs: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void flushRecords() { flushRecords(true); }
+ public void flushRecords(boolean shouldWait) {
+ try {
+ List records = _manager._removeAll();
+ if (records == null) return;
+ for (int i = 0; i < records.size(); i++) {
+ LogRecord rec = (LogRecord) records.get(i);
+ writeRecord(rec);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ if (shouldWait) {
+ try {
+ synchronized (this) {
+ this.wait(10*1000);
+ }
+ } catch (InterruptedException ie) { // nop
+ }
+ }
+ }
+ }
+
+
+ private void rereadConfig() {
+ long now = Clock.getInstance().now();
+ if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
+ _manager.rereadConfig();
+ _lastReadConfig = now;
+ }
+ }
+
+ private void writeRecord(LogRecord rec) {
+ if (rec.getThrowable() == null)
+ log(rec.getPriority(), rec.getSourceName(), null, rec.getThreadName(), rec.getMessage());
+ else
+ log(rec.getPriority(), rec.getSourceName(), null, rec.getThreadName(), rec.getMessage(), rec.getThrowable());
+ }
+
+ public void log(int priority, String className, String name, String threadName, String msg) {
+ if (className != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ className,
+ threadName + ' ' + msg);
+ else if (name != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ name,
+ threadName + ' ' + msg);
+ else
+ android.util.Log.println(toAndroidLevel(priority),
+ threadName, msg);
+ }
+
+ public void log(int priority, String className, String name, String threadName, String msg, Throwable t) {
+ if (className != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ className,
+ threadName + ' ' + msg +
+ msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ else if (name != null)
+ android.util.Log.println(toAndroidLevel(priority),
+ name,
+ threadName + ' ' + msg +
+ msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ else
+ android.util.Log.println(toAndroidLevel(priority),
+ threadName,
+ msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
+ }
+
+ private static int toAndroidLevel(int level) {
+ switch (level) {
+ case Log.DEBUG:
+ return android.util.Log.DEBUG;
+ case Log.INFO:
+ return android.util.Log.INFO;
+ case Log.WARN:
+ return android.util.Log.WARN;
+ case Log.ERROR:
+ case Log.CRIT:
+ default:
+ return android.util.Log.ERROR;
+ }
+ }
+
+ private static final String replace(String pattern, int num) {
+ char c[] = pattern.toCharArray();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < c.length; i++) {
+ if ( (c[i] != '#') && (c[i] != '@') )
+ buf.append(c[i]);
+ else
+ buf.append(num);
+ }
+ return buf.toString();
+ }
+}