From cadb6e8c1e1f09afef2a0c3bc4edf443ccf0d2e8 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 24 Jun 2011 03:23:19 +0000 Subject: [PATCH] - Set android log tag to "I2P" - Log to console buffer too - New log activity - Debug status output when router not running - More logging utility methods --- AndroidManifest.xml | 4 + res/layout/logs_header.xml | 8 ++ res/layout/logs_list_item.xml | 7 ++ res/layout/main.xml | 12 +++ res/raw/logger_config | 1 + .../android/router/activity/LogActivity.java | 70 +++++++++++++++++ .../android/router/activity/MainActivity.java | 75 +++++++++++++------ .../android/router/service/RouterService.java | 7 +- src/net/i2p/android/router/util/Util.java | 63 ++++++++++++++++ src/net/i2p/util/LogWriter.java | 34 ++++++--- 10 files changed, 248 insertions(+), 33 deletions(-) create mode 100644 res/layout/logs_header.xml create mode 100644 res/layout/logs_list_item.xml create mode 100644 src/net/i2p/android/router/activity/LogActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6481eee1c..45d816fe9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -50,5 +50,9 @@ android:label="Address Book" android.theme="@android:style/Theme.NoTitleBar" > </activity> + <activity android:name=".activity.LogActivity" + android:label="Logs" + android.theme="@android:style/Theme.NoTitleBar" > + </activity> </application> </manifest> diff --git a/res/layout/logs_header.xml b/res/layout/logs_header.xml new file mode 100644 index 000000000..b3a12859b --- /dev/null +++ b/res/layout/logs_header.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="8dp" + android:textSize="18sp" + android:text="Logs" > +</TextView> diff --git a/res/layout/logs_list_item.xml b/res/layout/logs_list_item.xml new file mode 100644 index 000000000..7e058a0f9 --- /dev/null +++ b/res/layout/logs_list_item.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="6dp" + android:textSize="16sp" > +</TextView> diff --git a/res/layout/main.xml b/res/layout/main.xml index fd46fb27d..5620f4e19 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -69,6 +69,18 @@ android:layout_height="wrap_content" android:text="Address Book" /> + <Button + android:id="@+id/logs_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Logs" + /> + <Button + android:id="@+id/error_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Error Logs" + /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" diff --git a/res/raw/logger_config b/res/raw/logger_config index f73f9459b..b83d079e0 100644 --- a/res/raw/logger_config +++ b/res/raw/logger_config @@ -1,3 +1,4 @@ +logger.consoleBufferSize=250 logger.dateFormat=MM/dd HH:mm:ss.SSS logger.defaultLevel=INFO logger.displayOnScreen=true diff --git a/src/net/i2p/android/router/activity/LogActivity.java b/src/net/i2p/android/router/activity/LogActivity.java new file mode 100644 index 000000000..a4ba44e85 --- /dev/null +++ b/src/net/i2p/android/router/activity/LogActivity.java @@ -0,0 +1,70 @@ +package net.i2p.android.router.activity; + +import android.app.ListActivity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.Collections; +import java.util.List; + +import net.i2p.I2PAppContext; +import net.i2p.android.router.R; + +public class LogActivity extends ListActivity { + + boolean errorsOnly; + + final static String ERRORS_ONLY = "errors_only"; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + // Grab context if router has started, otherwise create new + // FIXME dup contexts, locking, ... + List<String> msgs; + String header; + I2PAppContext ctx = I2PAppContext.getCurrentContext(); + if (ctx != null) { + Intent intent = getIntent(); + errorsOnly = intent.getBooleanExtra(ERRORS_ONLY, false); + if (errorsOnly) { + msgs = ctx.logManager().getBuffer().getMostRecentCriticalMessages(); + } else { + msgs = ctx.logManager().getBuffer().getMostRecentMessages(); + } + int sz = msgs.size(); + if (sz == 0) { + header = "No messages"; + } else if (sz == 1) { + header = "1 message"; + } else { + header = sz + " messages, newest first"; + Collections.reverse(msgs); + } + } else { + msgs = Collections.EMPTY_LIST; + header = "No messages"; + } + + // set the header + TextView tv = (TextView) getLayoutInflater().inflate(R.layout.logs_header, null); + tv.setText(header); + ListView lv = getListView(); + lv.addHeaderView(tv, "", false); + setListAdapter(new ArrayAdapter<String>(this, R.layout.logs_list_item, msgs)); + + // set the callback + lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int pos, long id) { + // make it bigger or something + } + }); + } +} diff --git a/src/net/i2p/android/router/activity/MainActivity.java b/src/net/i2p/android/router/activity/MainActivity.java index 23934f087..4220a301f 100644 --- a/src/net/i2p/android/router/activity/MainActivity.java +++ b/src/net/i2p/android/router/activity/MainActivity.java @@ -38,16 +38,16 @@ public class MainActivity extends I2PActivityBase { super.onCreate(savedInstanceState); setContentView(R.layout.main); - Button news = (Button) findViewById(R.id.news_button); - news.setOnClickListener(new View.OnClickListener() { + Button b = (Button) findViewById(R.id.news_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), NewsActivity.class); startActivity(intent); } }); - Button notes = (Button) findViewById(R.id.releasenotes_button); - notes.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.releasenotes_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), TextResourceActivity.class); intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt); @@ -55,8 +55,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button licenses = (Button) findViewById(R.id.licenses_button); - licenses.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.licenses_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), LicenseActivity.class); //Intent intent = new Intent(view.getContext(), TextResourceActivity.class); @@ -65,8 +65,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button website = (Button) findViewById(R.id.website_button); - website.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.website_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), WebActivity.class); //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/").build()); @@ -75,8 +75,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button faq = (Button) findViewById(R.id.faq_button); - faq.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.faq_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), WebActivity.class); //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/faq").build()); @@ -85,8 +85,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button welcome = (Button) findViewById(R.id.welcome_button); - welcome.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.welcome_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), WebActivity.class); // default is to display the welcome_html resource @@ -94,16 +94,33 @@ public class MainActivity extends I2PActivityBase { } }); - Button addressbook = (Button) findViewById(R.id.addressbook_button); - addressbook.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.addressbook_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(view.getContext(), AddressbookActivity.class); startActivity(intent); } }); - Button start = (Button) findViewById(R.id.router_start_button); - start.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.logs_button); + b.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + Intent intent = new Intent(view.getContext(), LogActivity.class); + startActivity(intent); + } + }); + + b = (Button) findViewById(R.id.error_button); + b.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + Intent intent = new Intent(view.getContext(), LogActivity.class); + intent.putExtra(LogActivity.ERRORS_ONLY, true); + startActivity(intent); + } + }); + + b = (Button) findViewById(R.id.router_start_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { RouterService svc = _routerService; if (svc != null && _isBound) { @@ -116,8 +133,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button stop = (Button) findViewById(R.id.router_stop_button); - stop.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.router_stop_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { RouterService svc = _routerService; if (svc != null && _isBound) { @@ -128,8 +145,8 @@ public class MainActivity extends I2PActivityBase { } }); - Button quit = (Button) findViewById(R.id.router_quit_button); - quit.setOnClickListener(new View.OnClickListener() { + b = (Button) findViewById(R.id.router_quit_button); + b.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { RouterService svc = _routerService; if (svc != null && _isBound) { @@ -157,6 +174,7 @@ public class MainActivity extends I2PActivityBase { { super.onStart(); _handler.removeCallbacks(_updater); + _handler.removeCallbacks(_oneShotUpdate); if (_savedStatus != null) { TextView tv = (TextView) findViewById(R.id.main_status_text); tv.setText(_savedStatus); @@ -170,6 +188,7 @@ public class MainActivity extends I2PActivityBase { { super.onStop(); _handler.removeCallbacks(_updater); + _handler.removeCallbacks(_oneShotUpdate); } @Override @@ -227,10 +246,11 @@ public class MainActivity extends I2PActivityBase { private void updateStatus() { RouterContext ctx = getRouterContext(); TextView tv = (TextView) findViewById(R.id.main_status_text); +/*** if (!Util.isConnected(this)) { tv.setText("No Internet connection is available"); tv.setVisibility(View.VISIBLE); - } else if (ctx != null) { + } else ****/ if (ctx != null) { int active = ctx.commSystem().countActivePeers(); int known = Math.max(ctx.netDb().getKnownRouters() - 1, 0); int inEx = ctx.tunnelManager().getFreeTunnelCount(); @@ -273,7 +293,18 @@ public class MainActivity extends I2PActivityBase { tv.setText(_savedStatus); tv.setVisibility(View.VISIBLE); } else { - tv.setVisibility(View.INVISIBLE); + //tv.setVisibility(View.INVISIBLE); + RouterService svc = _routerService; + String status = + "connected? " + Util.isConnected(this) + + "\nhave ctx? " + (ctx != null) + + "\nhave svc? " + (svc != null) + + "\nis bound? " + _isBound + + "\nsvc state: " + (svc == null ? "null" : svc.getState()) + + "\ncan start? " + (svc == null ? "null" : svc.canManualStart()) + + "\ncan stop? " + (svc == null ? "null" : svc.canManualStop()); + tv.setText(status); + tv.setVisibility(View.VISIBLE); } } diff --git a/src/net/i2p/android/router/service/RouterService.java b/src/net/i2p/android/router/service/RouterService.java index ff722ea7e..91775dff9 100644 --- a/src/net/i2p/android/router/service/RouterService.java +++ b/src/net/i2p/android/router/service/RouterService.java @@ -27,7 +27,7 @@ import net.i2p.util.NativeBigInteger; * Runs the router */ public class RouterService extends Service { - private enum State {INIT, WAITING, STARTING, RUNNING, + public enum State {INIT, WAITING, STARTING, RUNNING, // unplanned (router stopped itself), next: killSelf() STOPPING, STOPPED, // button, don't kill service when stopped, stay in MANUAL_STOPPED @@ -218,6 +218,11 @@ public class RouterService extends Service { return rv; } + /** debug */ + public String getState() { + return _state.toString(); + } + public boolean canManualStop() { return _state == State.WAITING || _state == State.STARTING || _state == State.RUNNING; } diff --git a/src/net/i2p/android/router/util/Util.java b/src/net/i2p/android/router/util/Util.java index 85637fd5a..bd909bdfa 100644 --- a/src/net/i2p/android/router/util/Util.java +++ b/src/net/i2p/android/router/util/Util.java @@ -7,6 +7,9 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; +import net.i2p.I2PAppContext; +import net.i2p.util.Log; + public abstract class Util { private static final boolean _isEmulator = Build.MODEL.equals("sdk"); @@ -39,4 +42,64 @@ public abstract class Util { return current; } + private static final String ANDROID_TAG = "I2P"; + + public static void e(String m) { + e(m, null); + } + + /** + * Log to the context logger if available (which goes to the console buffer + * and to logcat), else just to logcat. + */ + public static void e(String m, Throwable t) { + I2PAppContext ctx = I2PAppContext.getCurrentContext(); + if (ctx != null) + ctx.logManager().getLog(Util.class).log(Log.ERROR, m, t); + else if (t != null) + android.util.Log.e(ANDROID_TAG, m + ' ' + t + ' ' + android.util.Log.getStackTraceString(t)); + else + android.util.Log.e(ANDROID_TAG, m); + } + + public static void w(String m) { + w(m, null); + } + + public static void w(String m, Throwable t) { + I2PAppContext ctx = I2PAppContext.getCurrentContext(); + if (ctx != null) + ctx.logManager().getLog(Util.class).log(Log.WARN, m, t); + else if (t != null) + android.util.Log.w(ANDROID_TAG, m + ' ' + t + ' ' + android.util.Log.getStackTraceString(t)); + else + android.util.Log.w(ANDROID_TAG, m); + } + + public static void i(String m) { + i(m, null); + } + + public static void i(String m, Throwable t) { + I2PAppContext ctx = I2PAppContext.getCurrentContext(); + if (ctx != null) + ctx.logManager().getLog(Util.class).log(Log.INFO, m, t); + else if (t != null) + android.util.Log.i(ANDROID_TAG, m + ' ' + t + ' ' + android.util.Log.getStackTraceString(t)); + else + android.util.Log.i(ANDROID_TAG, m); + } + public static void d(String m) { + d(m, null); + } + + public static void d(String m, Throwable t) { + I2PAppContext ctx = I2PAppContext.getCurrentContext(); + if (ctx != null) + ctx.logManager().getLog(Util.class).log(Log.DEBUG, m, t); + else if (t != null) + android.util.Log.d(ANDROID_TAG, m + ' ' + t + ' ' + android.util.Log.getStackTraceString(t)); + else + android.util.Log.d(ANDROID_TAG, m); + } } diff --git a/src/net/i2p/util/LogWriter.java b/src/net/i2p/util/LogWriter.java index be06b7c0c..22dcf9c7d 100644 --- a/src/net/i2p/util/LogWriter.java +++ b/src/net/i2p/util/LogWriter.java @@ -105,6 +105,12 @@ class LogWriter implements Runnable { else log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage(), rec.getThrowable()); + // to be viewed on android screen + String val = LogRecordFormatter.formatRecord(_manager, rec, true); + _manager.getBuffer().add(val); + if (rec.getPriority() >= Log.ERROR) + _manager.getBuffer().addCritical(val); + // we always add to the console buffer, but only sometimes write to stdout if (_manager.getDisplayOnScreenLevel() <= rec.getPriority()) { if (_manager.displayOnScreen()) { @@ -114,6 +120,8 @@ class LogWriter implements Runnable { } } + private static final String ANDROID_LOG_TAG = "I2P"; + public void log(int priority, Class src, String name, String threadName, String msg) { if (src != null) { String tag = src.getName(); @@ -121,15 +129,18 @@ class LogWriter implements Runnable { if (dot >= 0) tag = tag.substring(dot + 1); android.util.Log.println(toAndroidLevel(priority), - tag, - '[' + threadName + "] " + msg); + ANDROID_LOG_TAG, + tag + + " [" + threadName + "] " + msg); } else if (name != null) android.util.Log.println(toAndroidLevel(priority), - name, - '[' + threadName + "] " + msg); + ANDROID_LOG_TAG, + name + + " [" + threadName + "] " + msg); else android.util.Log.println(toAndroidLevel(priority), - threadName, msg); + ANDROID_LOG_TAG, + '[' + threadName + "] " + msg); } public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) { @@ -139,17 +150,20 @@ class LogWriter implements Runnable { if (dot >= 0) tag = tag.substring(dot + 1); android.util.Log.println(toAndroidLevel(priority), - tag, - '[' + threadName + "] " + msg + + ANDROID_LOG_TAG, + tag + + " [" + threadName + "] " + msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t)); } else if (name != null) android.util.Log.println(toAndroidLevel(priority), - name, - '[' + threadName + "] " + msg + + ANDROID_LOG_TAG, + name + + " [" + threadName + "] " + msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t)); else android.util.Log.println(toAndroidLevel(priority), - threadName, + ANDROID_LOG_TAG, + '[' + threadName + "] " + msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t)); } -- GitLab