diff --git a/code/boot.js b/code/boot.js
index d9fb8ced..de78ee60 100644
--- a/code/boot.js
+++ b/code/boot.js
@@ -507,7 +507,8 @@ window.setupLayerChooserApi = function() {
function boot() {
try { //EXPERIMENTAL TEST
- window.debug.console.overwriteNativeIfRequired();
+ if(!isSmartphone()) // TODO remove completly?
+ window.debug.console.overwriteNativeIfRequired();
console.log('loading done, booting. Built: @@BUILDDATE@@');
if(window.deviceID) console.log('Your device ID: ' + window.deviceID);
diff --git a/mobile/res/drawable-hdpi/ic_action_error_red.png b/mobile/res/drawable-hdpi/ic_action_error_red.png
new file mode 100644
index 00000000..11b15bf5
Binary files /dev/null and b/mobile/res/drawable-hdpi/ic_action_error_red.png differ
diff --git a/mobile/res/drawable-hdpi/ic_action_warning_yellow.png b/mobile/res/drawable-hdpi/ic_action_warning_yellow.png
new file mode 100644
index 00000000..a17ff07b
Binary files /dev/null and b/mobile/res/drawable-hdpi/ic_action_warning_yellow.png differ
diff --git a/mobile/res/drawable-mdpi/ic_action_error_red.png b/mobile/res/drawable-mdpi/ic_action_error_red.png
new file mode 100644
index 00000000..32c908f5
Binary files /dev/null and b/mobile/res/drawable-mdpi/ic_action_error_red.png differ
diff --git a/mobile/res/drawable-mdpi/ic_action_warning_yellow.png b/mobile/res/drawable-mdpi/ic_action_warning_yellow.png
new file mode 100644
index 00000000..f490edf4
Binary files /dev/null and b/mobile/res/drawable-mdpi/ic_action_warning_yellow.png differ
diff --git a/mobile/res/drawable-xhdpi/ic_action_error_red.png b/mobile/res/drawable-xhdpi/ic_action_error_red.png
new file mode 100644
index 00000000..f0a24cd2
Binary files /dev/null and b/mobile/res/drawable-xhdpi/ic_action_error_red.png differ
diff --git a/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png b/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png
new file mode 100644
index 00000000..2349e7e4
Binary files /dev/null and b/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png differ
diff --git a/mobile/res/drawable-xxhdpi/ic_action_error_red.png b/mobile/res/drawable-xxhdpi/ic_action_error_red.png
new file mode 100644
index 00000000..7f13403e
Binary files /dev/null and b/mobile/res/drawable-xxhdpi/ic_action_error_red.png differ
diff --git a/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png b/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png
new file mode 100644
index 00000000..6b729940
Binary files /dev/null and b/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png differ
diff --git a/mobile/res/layout/activity_main.xml b/mobile/res/layout/activity_main.xml
index d4a8ccbc..2d95b955 100644
--- a/mobile/res/layout/activity_main.xml
+++ b/mobile/res/layout/activity_main.xml
@@ -4,20 +4,58 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
-
-
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/res/layout/view_log_msg.xml b/mobile/res/layout/view_log_msg.xml
new file mode 100644
index 00000000..b8ec471a
--- /dev/null
+++ b/mobile/res/layout/view_log_msg.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile/res/menu/main.xml b/mobile/res/menu/main.xml
index 63790b3f..bffdd6ab 100644
--- a/mobile/res/menu/main.xml
+++ b/mobile/res/menu/main.xml
@@ -1,48 +1,52 @@
-
\ No newline at end of file
diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml
index 816353f7..0c93c513 100644
--- a/mobile/res/values/strings.xml
+++ b/mobile/res/values/strings.xml
@@ -2,6 +2,7 @@
IITC Mobile
+ Toggle map visibility
IITC Mobile Settings
IITC Plugins
Share using…
@@ -140,6 +141,7 @@
Clear Cookies
Search
+ Debug
Choose account to login
Login failed.
Search Locations
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java b/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java
new file mode 100644
index 00000000..2244ac16
--- /dev/null
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java
@@ -0,0 +1,89 @@
+package com.cradle.iitc_mobile;
+
+import android.annotation.SuppressLint;
+import android.database.DataSetObserver;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.cradle.iitc_mobile.Log.Message;
+
+import java.text.SimpleDateFormat;
+
+public class IITC_LogAdapter extends ArrayAdapter implements Log.Receiver {
+ @SuppressLint("SimpleDateFormat")
+ private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("HH:mm:ss.SSS");
+
+ private int mObservers = 0;
+ private IITC_Mobile mIitc;
+
+ public IITC_LogAdapter(IITC_Mobile iitc) {
+ super(iitc, 0);
+ mIitc = iitc;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Message item = getItem(position);
+ View v = mIitc.getLayoutInflater().inflate(R.layout.view_log_msg, parent, false);
+
+ ImageView iv = (ImageView) v.findViewById(R.id.log_type);
+ switch (item.getPriority()) {
+ case Log.ASSERT:
+ case Log.ERROR:
+ iv.setImageResource(R.drawable.ic_action_error_red);
+ break;
+ case Log.WARN:
+ iv.setImageResource(R.drawable.ic_action_warning_yellow);
+ break;
+ default:
+ iv.setImageResource(R.drawable.ic_action_about);
+ }
+
+ TextView tv;
+
+ tv = (TextView) v.findViewById(R.id.log_tag);
+ tv.setText(item.getTag());
+
+ tv = (TextView) v.findViewById(R.id.log_time);
+ tv.setText(FORMATTER.format(item.getDate()));
+
+ tv = (TextView) v.findViewById(R.id.log_msg);
+ tv.setText(item.getMsg());
+
+ return v;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ super.unregisterDataSetObserver(observer);
+ mObservers--;
+
+ if (mObservers < 1) {
+ clear();
+ Log.removeReceiver(this);
+ }
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ super.registerDataSetObserver(observer);
+
+ if (mObservers < 1)
+ Log.addReceiver(this);
+
+ mObservers++;
+ }
+
+ @Override
+ public void handle(Message message) {
+ this.insert(message, 0);
+ }
+}
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
index 4080e985..b729c581 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
@@ -24,6 +24,9 @@ import android.view.View;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.WebView;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
@@ -49,8 +52,15 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
private boolean mDesktopMode = false;
private boolean mAdvancedMenu = false;
private MenuItem mSearchMenuItem;
+ private View mImageLoading;
+ private ListView mLvDebug;
+ private View mViewDebug;
+ private ImageButton mBtnToggleMap;
+ private EditText mEditCommand;
+ private boolean mDebugging = false;
private boolean mReloadNeeded = false;
private boolean mIsLoading = true;
+ private boolean mShowMapInDebug = false;
private final Stack mDialogStack = new Stack();
// Used for custom back stack handling
@@ -73,7 +83,14 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_main);
+ mImageLoading = findViewById(R.id.imageLoading);
mIitcWebView = (IITC_WebView) findViewById(R.id.iitc_webview);
+ mLvDebug = (ListView) findViewById(R.id.lvDebug);
+ mViewDebug = findViewById(R.id.viewDebug);
+ mBtnToggleMap = (ImageButton) findViewById(R.id.btnToggleMapVisibility);
+ mEditCommand = (EditText) findViewById(R.id.editCommand);
+
+ mLvDebug.setAdapter(new IITC_LogAdapter(this));
// do something if user changed something in the settings
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -425,6 +442,11 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
: R.drawable.ic_action_location_found);
break;
+ case R.id.menu_debug:
+ item.setVisible(mAdvancedMenu && visible);
+ item.setChecked(mDebugging);
+ break;
+
default:
item.setVisible(visible);
}
@@ -480,6 +502,13 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
CookieManager cm = CookieManager.getInstance();
cm.removeAllCookie();
return true;
+ case R.id.menu_debug:
+ mDebugging = !mDebugging;
+ updateViews();
+ invalidateOptionsMenu();
+
+ // TODO remove debugging stuff from JS?
+ return true;
default:
return false;
}
@@ -494,6 +523,7 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
mNavigationHelper.reset();
mMapSettings.reset();
mUserLocation.reset();
+ mIitcWebView.getWebViewClient().reset();
mBackStack.clear();
// iitc starts on map after reload
mCurrentPane = Pane.MAP;
@@ -585,15 +615,54 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
mNavigationHelper.onLoadingStateChanged();
- if (isLoading && !mSharedPrefs.getBoolean("pref_disable_splash", false)) {
- findViewById(R.id.iitc_webview).setVisibility(View.GONE);
- findViewById(R.id.imageLoading).setVisibility(View.VISIBLE);
+ updateViews();
+ }
+
+ private void updateViews() {
+ if (!mDebugging) {
+ mViewDebug.setVisibility(View.GONE);
+ mLvDebug.setVisibility(View.GONE);
+
+ if (mIsLoading && !mSharedPrefs.getBoolean("pref_disable_splash", false)) {
+ mIitcWebView.setVisibility(View.GONE);
+ mImageLoading.setVisibility(View.VISIBLE);
+ } else {
+ mIitcWebView.setVisibility(View.VISIBLE);
+ mImageLoading.setVisibility(View.GONE);
+ }
} else {
- findViewById(R.id.iitc_webview).setVisibility(View.VISIBLE);
- findViewById(R.id.imageLoading).setVisibility(View.GONE);
+ // if the debug container is invisible (and we are about to show it), select the text box
+ boolean select = mViewDebug.getVisibility() != View.VISIBLE;
+
+ mImageLoading.setVisibility(View.GONE); // never show splash screen while debugging
+ mViewDebug.setVisibility(View.VISIBLE);
+
+ if (select) {
+ mEditCommand.requestFocus();
+ mEditCommand.selectAll();
+ }
+
+ if (mShowMapInDebug) {
+ mBtnToggleMap.setImageResource(R.drawable.ic_action_view_as_list);
+ mIitcWebView.setVisibility(View.VISIBLE);
+ mLvDebug.setVisibility(View.GONE);
+ } else {
+ mBtnToggleMap.setImageResource(R.drawable.ic_action_map);
+ mIitcWebView.setVisibility(View.GONE);
+ mLvDebug.setVisibility(View.VISIBLE);
+ }
}
}
+ /**
+ * onClick handler for R.id.btnToggleMapVisibility, assigned in activity_main.xml
+ */
+ public void onToggleMapVisibility(View v)
+ {
+ mShowMapInDebug = !mShowMapInDebug;
+ updateViews();
+ }
+
private void deleteUpdateFile() {
File file = new File(getExternalFilesDir(null).toString() + "/iitcUpdate.apk");
if (file != null) file.delete();
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java
index 9c4df290..5b68fb33 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java
@@ -336,16 +336,11 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
add(Pane.COMPACT);
add(Pane.PUBLIC);
add(Pane.FACTION);
-
- if (mPrefs.getBoolean("pref_advanced_menu", false)) {
- add(Pane.DEBUG);
- }
}
}
public static class Pane {
public static final Pane COMPACT = new Pane("compact", "Compact", R.drawable.ic_action_view_as_list_compact);
- public static final Pane DEBUG = new Pane("debug", "Debug", R.drawable.ic_action_error);
public static final Pane FACTION = new Pane("faction", "Faction", R.drawable.ic_action_cc_bcc);
public static final Pane FULL = new Pane("full", "Full", R.drawable.ic_action_view_as_list);
public static final Pane INFO = new Pane("info", "Info", R.drawable.ic_action_about);
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java
index a191f9ef..fad0eee3 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java
@@ -15,14 +15,14 @@ public class IITC_WebChromeClient extends WebChromeClient {
public IITC_WebChromeClient(IITC_Mobile iitcm) {
mIitcm = iitcm;
}
+
/**
* our webchromeclient should share geolocation with the iitc script
*
* allow access by default
*/
@Override
- public void onGeolocationPermissionsShowPrompt(String origin,
- GeolocationPermissions.Callback callback) {
+ public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
@@ -42,10 +42,14 @@ public class IITC_WebChromeClient extends WebChromeClient {
* remove splash screen if any JS error occurs
*/
@Override
- public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
- if (consoleMessage.messageLevel() == ConsoleMessage.MessageLevel.ERROR) {
+ public boolean onConsoleMessage(ConsoleMessage message) {
+ if (message.messageLevel() == ConsoleMessage.MessageLevel.ERROR) {
mIitcm.setLoadingState(false);
}
- return super.onConsoleMessage(consoleMessage);
+
+ if (Log.log(message))
+ return true; // message was handled
+
+ return super.onConsoleMessage(message);
}
}
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
index e0934d8f..c2337785 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
@@ -6,6 +6,7 @@ import android.net.Uri;
import android.net.http.SslError;
import android.os.Environment;
import android.preference.PreferenceManager;
+import android.text.TextUtils;
import android.util.Log;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceResponse;
@@ -86,7 +87,7 @@ public class IITC_WebViewClient extends WebViewClient {
scripts.add("script/user-location.user.js");
}
- String js = "(function(){['" + join(scripts, "','") + "'].forEach(function(src) {" +
+ String js = "(function(){['" + TextUtils.join("','", scripts) + "'].forEach(function(src) {" +
"var script = document.createElement('script');script.src = 'iitcm://'+src;" +
"(document.body || document.head || document.documentElement).appendChild(script);" +
"});})();";
@@ -94,64 +95,16 @@ public class IITC_WebViewClient extends WebViewClient {
view.loadJS(js);
}
- static public String join(List list, String conjunction)
- {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (String item : list)
- {
- if (first)
- first = false;
- else
- sb.append(conjunction);
- sb.append(item);
- }
- return sb.toString();
- }
-
/**
* this method is called automatically when the Google login form is opened.
*/
@Override
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
- Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args);
mIitcInjected = false;
+ // Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args);
// ((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args);
}
- // read a file into a string
- // use the full path for File
- // if asset == true use the asset manager to open file
- // public String fileToString(String file, boolean asset) {
- // Scanner s = null;
- // String src = "";
- // if (!asset) {
- // File js_file = new File(file);
- // try {
- // s = new Scanner(js_file).useDelimiter("\\A");
- // } catch (FileNotFoundException e) {
- // e.printStackTrace();
- // Log.d("iitcm", "failed to parse file " + file);
- // return "false";
- // }
- // } else {
- // // load plugins from asset folder
- // AssetManager am = mIitc.getAssets();
- // try {
- // s = new Scanner(am.open(file)).useDelimiter("\\A");
- // } catch (IOException e) {
- // e.printStackTrace();
- // Log.d("iitcm", "failed to parse file assets/" + file);
- // return "false";
- // }
- // }
- //
- // if (s != null) {
- // src = s.hasNext() ? s.next() : "";
- // }
- // return src;
- // }
-
// Check every external resource if it’s okay to load it and maybe replace
// it
// with our own content. This is used to block loading Niantic resources
@@ -220,4 +173,8 @@ public class IITC_WebViewClient extends WebViewClient {
return true;
}
}
+
+ public void reset() {
+ mIitcInjected = false;
+ }
}
diff --git a/mobile/src/com/cradle/iitc_mobile/Log.java b/mobile/src/com/cradle/iitc_mobile/Log.java
new file mode 100644
index 00000000..e0ca4e1e
--- /dev/null
+++ b/mobile/src/com/cradle/iitc_mobile/Log.java
@@ -0,0 +1,220 @@
+package com.cradle.iitc_mobile;
+
+import android.webkit.ConsoleMessage;
+import android.webkit.ConsoleMessage.MessageLevel;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+public final class Log {
+ private static final HashMap CONSOLE_MAPPING;
+ private static final List RECEIVERS = new LinkedList();
+
+ public static final String CONSOLE_TAG = "iitcm-console";
+ public static final String DEFAULT_TAG = "iitcm";
+
+ public static final int ASSERT = android.util.Log.ASSERT;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int WARN = android.util.Log.WARN;
+
+ static {
+ CONSOLE_MAPPING = new HashMap();
+ CONSOLE_MAPPING.put(MessageLevel.TIP, android.util.Log.VERBOSE);
+ CONSOLE_MAPPING.put(MessageLevel.LOG, android.util.Log.INFO);
+ CONSOLE_MAPPING.put(MessageLevel.WARNING, android.util.Log.WARN);
+ CONSOLE_MAPPING.put(MessageLevel.ERROR, android.util.Log.ERROR);
+ CONSOLE_MAPPING.put(MessageLevel.DEBUG, android.util.Log.DEBUG);
+ };
+
+ private static synchronized void log(int priority, String tag, String msg, Throwable tr) {
+ Date now = new Date();
+
+ Message message = new Message(now, priority, tag, msg, tr);
+ for (Receiver receiver : RECEIVERS) {
+ receiver.handle(message);
+ }
+ }
+
+ public static void d(String msg) {
+ d(DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static void d(String tag, String msg) {
+ log(android.util.Log.DEBUG, tag, msg, null);
+ android.util.Log.d(tag, msg);
+ }
+
+ @Deprecated
+ public static void d(String tag, String msg, Throwable tr) {
+ log(android.util.Log.DEBUG, tag, msg, tr);
+ android.util.Log.d(tag, msg, tr);
+ }
+
+ public static void d(String msg, Throwable tr) {
+ d(DEFAULT_TAG, msg, tr);
+ }
+
+ public static void e(String msg) {
+ e(DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static void e(String tag, String msg) {
+ log(android.util.Log.ERROR, tag, msg, null);
+ android.util.Log.e(tag, msg);
+ }
+
+ @Deprecated
+ public static void e(String tag, String msg, Throwable tr) {
+ log(android.util.Log.ERROR, tag, msg, tr);
+ android.util.Log.e(tag, msg, tr);
+ }
+
+ public static void e(String msg, Throwable tr) {
+ e(DEFAULT_TAG, msg, tr);
+ }
+
+ public static void i(String msg) {
+ i(DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static void i(String tag, String msg) {
+ log(android.util.Log.INFO, tag, msg, null);
+ android.util.Log.i(tag, msg);
+ }
+
+ @Deprecated
+ public static void i(String tag, String msg, Throwable tr) {
+ log(android.util.Log.INFO, tag, msg, tr);
+ android.util.Log.i(tag, msg, tr);
+ }
+
+ public static void i(String msg, Throwable tr) {
+ i(DEFAULT_TAG, msg, tr);
+ }
+
+ public static boolean log(ConsoleMessage message) {
+ final String msg = message.sourceId() + ":" + message.lineNumber() + ": " + message.message();
+ final Integer priority = CONSOLE_MAPPING.get(message.messageLevel());
+
+ if (priority != null) {
+ log(priority, CONSOLE_TAG, msg, null);
+ android.util.Log.println(priority, CONSOLE_TAG, msg);
+ return true;
+ }
+
+ Log.w(CONSOLE_TAG, "Warning: unknown message level in Logger.log(ConsoleMessage message): "
+ + message.messageLevel().ordinal() + "/" + message.messageLevel().name());
+ return false;
+ }
+
+ public static int println(int priority, String msg) {
+ return println(priority, DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static int println(int priority, String tag, String msg) {
+ log(priority, tag, msg, null);
+ return android.util.Log.println(priority, tag, msg);
+ }
+
+ public static void v(String msg) {
+ v(DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static void v(String tag, String msg) {
+ log(android.util.Log.VERBOSE, tag, msg, null);
+ android.util.Log.v(tag, msg);
+ }
+
+ @Deprecated
+ public static void v(String tag, String msg, Throwable tr) {
+ log(android.util.Log.VERBOSE, tag, msg, tr);
+ android.util.Log.v(tag, msg, tr);
+ }
+
+ public static void v(String msg, Throwable tr) {
+ v(DEFAULT_TAG, msg, tr);
+ }
+
+ public static void w(String msg) {
+ w(DEFAULT_TAG, msg);
+ }
+
+ @Deprecated
+ public static void w(String tag, String msg) {
+ log(android.util.Log.WARN, tag, msg, null);
+ android.util.Log.w(tag, msg);
+ }
+
+ @Deprecated
+ public static void w(String tag, String msg, Throwable tr) {
+ log(android.util.Log.WARN, tag, msg, tr);
+ android.util.Log.w(tag, msg, tr);
+ }
+
+ public static void w(String msg, Throwable tr) {
+ w(DEFAULT_TAG, msg, tr);
+ }
+
+ private Log() {
+ // prevent instantiation
+ throw new UnsupportedOperationException();
+ }
+
+ public static class Message {
+ private Date mDate;
+ private String mMsg;
+ private int mPriority;
+ private String mTag;
+ private Throwable mTr;
+
+ private Message(Date date, int priority, String tag, String msg, Throwable tr) {
+ mDate = date;
+ mPriority = priority;
+ mTag = tag;
+ mMsg = msg;
+ mTr = tr;
+ }
+
+ public Date getDate() {
+ return this.mDate;
+ }
+
+ public String getMsg() {
+ return this.mMsg;
+ }
+
+ public int getPriority() {
+ return this.mPriority;
+ }
+
+ public String getTag() {
+ return this.mTag;
+ }
+
+ public Throwable getTr() {
+ return this.mTr;
+ }
+ }
+
+ public static interface Receiver {
+ void handle(Message message);
+ }
+
+ public static void removeReceiver(Log.Receiver receiver) {
+ RECEIVERS.remove(receiver);
+ }
+
+ public static void addReceiver(Log.Receiver receiver) {
+ RECEIVERS.add(receiver);
+ }
+}