Cordova-Android should use org.apache.cordova.LOG for logging

* Read LogLevel preference from config.xml
* Replace Log with LOG
* Add addition warning method to LOG
This commit is contained in:
Simon MacDonald 2016-08-22 12:53:41 -04:00
parent 8fbb6d7c62
commit 4a0a7bc424
11 changed files with 97 additions and 95 deletions

View File

@ -20,8 +20,6 @@ package org.apache.cordova;
import org.json.JSONArray; import org.json.JSONArray;
import android.util.Log;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult; import org.apache.cordova.PluginResult;
import org.json.JSONObject; import org.json.JSONObject;
@ -54,7 +52,7 @@ public class CallbackContext {
public void sendPluginResult(PluginResult pluginResult) { public void sendPluginResult(PluginResult pluginResult) {
synchronized (this) { synchronized (this) {
if (finished) { if (finished) {
Log.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage()); LOG.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage());
return; return;
} else { } else {
finished = !pluginResult.getKeepCallback(); finished = !pluginResult.getKeepCallback();

View File

@ -22,7 +22,6 @@ package org.apache.cordova;
import java.util.List; import java.util.List;
import android.app.Activity; import android.app.Activity;
import android.util.Log;
@Deprecated // Use Whitelist, CordovaPrefences, etc. directly. @Deprecated // Use Whitelist, CordovaPrefences, etc. directly.
public class Config { public class Config {

View File

@ -34,7 +34,6 @@ import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -104,17 +103,21 @@ public class CordovaActivity extends Activity {
*/ */
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
loadConfig();
String logLevel = preferences.getString("loglevel", "ERROR");
LOG.setLogLevel(logLevel);
LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting"); LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
LOG.d(TAG, "CordovaActivity.onCreate()"); LOG.d(TAG, "CordovaActivity.onCreate()");
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
loadConfig();
if (!preferences.getBoolean("ShowTitle", false)) { if (!preferences.getBoolean("ShowTitle", false)) {
getWindow().requestFeature(Window.FEATURE_NO_TITLE); getWindow().requestFeature(Window.FEATURE_NO_TITLE);
} }
if (preferences.getBoolean("SetFullscreen", false)) { if (preferences.getBoolean("SetFullscreen", false)) {
Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version."); LOG.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
preferences.set("Fullscreen", true); preferences.set("Fullscreen", true);
} }
if (preferences.getBoolean("Fullscreen", false)) { if (preferences.getBoolean("Fullscreen", false)) {

View File

@ -23,8 +23,6 @@ import java.security.SecureRandom;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import android.util.Log;
/** /**
* Contains APIs that the JS can call. All functions in here should also have * Contains APIs that the JS can call. All functions in here should also have
* an equivalent entry in CordovaChromeClient.java, and be added to * an equivalent entry in CordovaChromeClient.java, and be added to
@ -87,15 +85,15 @@ public class CordovaBridge {
private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException { private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
if (!jsMessageQueue.isBridgeEnabled()) { if (!jsMessageQueue.isBridgeEnabled()) {
if (bridgeSecret == -1) { if (bridgeSecret == -1) {
Log.d(LOG_TAG, action + " call made before bridge was enabled."); LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
} else { } else {
Log.d(LOG_TAG, "Ignoring " + action + " from previous page load."); LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
} }
return false; return false;
} }
// Bridge secret wrong and bridge not due to it being from the previous page. // Bridge secret wrong and bridge not due to it being from the previous page.
if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) { if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) {
Log.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!"); LOG.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!");
clearBridgeSecret(); clearBridgeSecret();
throw new IllegalAccessException(); throw new IllegalAccessException();
} }
@ -175,7 +173,7 @@ public class CordovaBridge {
int secret = generateBridgeSecret(); int secret = generateBridgeSecret();
return ""+secret; return ""+secret;
} else { } else {
Log.e(LOG_TAG, "gap_init called from restricted origin: " + origin); LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
} }
return ""; return "";
} }

View File

@ -24,7 +24,6 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.util.Pair; import android.util.Pair;
import org.json.JSONException; import org.json.JSONException;
@ -147,13 +146,13 @@ public class CordovaInterfaceImpl implements CordovaInterface {
activityResultCallback = null; activityResultCallback = null;
if (callback != null) { if (callback != null) {
Log.d(TAG, "Sending activity result to plugin"); LOG.d(TAG, "Sending activity result to plugin");
initCallbackService = null; initCallbackService = null;
savedResult = null; savedResult = null;
callback.onActivityResult(requestCode, resultCode, intent); callback.onActivityResult(requestCode, resultCode, intent);
return true; return true;
} }
Log.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : ".")); LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : "."));
return false; return false;
} }

View File

@ -21,7 +21,6 @@ package org.apache.cordova;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
@ -245,7 +244,7 @@ public class CordovaWebViewImpl implements CordovaWebView {
@Deprecated @Deprecated
public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) { public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "showing Custom View"); LOG.d(TAG, "showing Custom View");
// if a view already exists then immediately terminate the new one // if a view already exists then immediately terminate the new one
if (mCustomView != null) { if (mCustomView != null) {
callback.onCustomViewHidden(); callback.onCustomViewHidden();
@ -276,7 +275,7 @@ public class CordovaWebViewImpl implements CordovaWebView {
public void hideCustomView() { public void hideCustomView() {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
if (mCustomView == null) return; if (mCustomView == null) return;
Log.d(TAG, "Hiding Custom View"); LOG.d(TAG, "Hiding Custom View");
// Hide the custom view. // Hide the custom view.
mCustomView.setVisibility(View.GONE); mCustomView.setVisibility(View.GONE);

View File

@ -154,6 +154,16 @@ public class LOG {
if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e); if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e);
} }
/**
* Warning log message.
*
* @param tag
* @param e
*/
public static void w(String tag, Throwable e) {
if (LOG.WARN >= LOGLEVEL) Log.w(tag, e);
}
/** /**
* Warning log message. * Warning log message.
* *

View File

@ -21,8 +21,6 @@ package org.apache.cordova;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import android.util.Log;
/** /**
* Holds the list of messages to be sent to the WebView. * Holds the list of messages to be sent to the WebView.
*/ */
@ -83,11 +81,11 @@ public class NativeToJsMessageQueue {
*/ */
public void setBridgeMode(int value) { public void setBridgeMode(int value) {
if (value < -1 || value >= bridgeModes.size()) { if (value < -1 || value >= bridgeModes.size()) {
Log.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value); LOG.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value);
} else { } else {
BridgeMode newMode = value < 0 ? null : bridgeModes.get(value); BridgeMode newMode = value < 0 ? null : bridgeModes.get(value);
if (newMode != activeBridgeMode) { if (newMode != activeBridgeMode) {
Log.d(LOG_TAG, "Set native->JS mode to " + (newMode == null ? "null" : newMode.getClass().getSimpleName())); LOG.d(LOG_TAG, "Set native->JS mode to " + (newMode == null ? "null" : newMode.getClass().getSimpleName()));
synchronized (this) { synchronized (this) {
activeBridgeMode = newMode; activeBridgeMode = newMode;
if (newMode != null) { if (newMode != null) {
@ -220,7 +218,7 @@ public class NativeToJsMessageQueue {
*/ */
public void addPluginResult(PluginResult result, String callbackId) { public void addPluginResult(PluginResult result, String callbackId) {
if (callbackId == null) { if (callbackId == null) {
Log.e(LOG_TAG, "Got plugin result with no callbackId", new Throwable()); LOG.e(LOG_TAG, "Got plugin result with no callbackId", new Throwable());
return; return;
} }
// Don't send anything if there is no result and there is no need to // Don't send anything if there is no result and there is no need to
@ -243,7 +241,7 @@ public class NativeToJsMessageQueue {
private void enqueueMessage(JsMessage message) { private void enqueueMessage(JsMessage message) {
synchronized (this) { synchronized (this) {
if (activeBridgeMode == null) { if (activeBridgeMode == null) {
Log.d(LOG_TAG, "Dropping Native->JS message due to disabled bridge"); LOG.d(LOG_TAG, "Dropping Native->JS message due to disabled bridge");
return; return;
} }
queue.add(message); queue.add(message);
@ -257,7 +255,7 @@ public class NativeToJsMessageQueue {
if (paused && value) { if (paused && value) {
// This should never happen. If a use-case for it comes up, we should // This should never happen. If a use-case for it comes up, we should
// change pause to be a counter. // change pause to be a counter.
Log.e(LOG_TAG, "nested call to setPaused detected.", new Throwable()); LOG.e(LOG_TAG, "nested call to setPaused detected.", new Throwable());
} }
paused = value; paused = value;
if (!value) { if (!value) {

View File

@ -28,7 +28,6 @@ import android.content.res.Configuration;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.util.Log;
/** /**
* PluginManager is exposed to JavaScript in the Cordova WebView. * PluginManager is exposed to JavaScript in the Cordova WebView.
@ -122,7 +121,7 @@ public class PluginManager {
public void exec(final String service, final String action, final String callbackId, final String rawArgs) { public void exec(final String service, final String action, final String callbackId, final String rawArgs) {
CordovaPlugin plugin = getPlugin(service); CordovaPlugin plugin = getPlugin(service);
if (plugin == null) { if (plugin == null) {
Log.d(TAG, "exec() call to unknown plugin: " + service); LOG.d(TAG, "exec() call to unknown plugin: " + service);
PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION); PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
app.sendPluginResult(cr, callbackId); app.sendPluginResult(cr, callbackId);
return; return;
@ -134,7 +133,7 @@ public class PluginManager {
long duration = System.currentTimeMillis() - pluginStartTime; long duration = System.currentTimeMillis() - pluginStartTime;
if (duration > SLOW_EXEC_WARNING_THRESHOLD) { if (duration > SLOW_EXEC_WARNING_THRESHOLD) {
Log.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool()."); LOG.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool().");
} }
if (!wasValidAction) { if (!wasValidAction) {
PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION); PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION);
@ -144,7 +143,7 @@ public class PluginManager {
PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION); PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
callbackContext.sendPluginResult(cr); callbackContext.sendPluginResult(cr);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Uncaught exception from plugin", e); LOG.e(TAG, "Uncaught exception from plugin", e);
callbackContext.error(e.getMessage()); callbackContext.error(e.getMessage());
} }
} }

View File

@ -26,7 +26,6 @@ import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
@ -254,7 +253,7 @@ public class SystemWebChromeClient extends WebChromeClient {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) { public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData(); Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
Log.d(LOG_TAG, "Receive file chooser URL: " + result); LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
uploadMsg.onReceiveValue(result); uploadMsg.onReceiveValue(result);
} }
}, intent, FILECHOOSER_RESULTCODE); }, intent, FILECHOOSER_RESULTCODE);
@ -269,12 +268,12 @@ public class SystemWebChromeClient extends WebChromeClient {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) { public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent); Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
Log.d(LOG_TAG, "Receive file chooser URL: " + result); LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
filePathsCallback.onReceiveValue(result); filePathsCallback.onReceiveValue(result);
} }
}, intent, FILECHOOSER_RESULTCODE); }, intent, FILECHOOSER_RESULTCODE);
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
Log.w("No activity found to handle file chooser intent.", e); LOG.w("No activity found to handle file chooser intent.", e);
filePathsCallback.onReceiveValue(null); filePathsCallback.onReceiveValue(null);
} }
return true; return true;
@ -283,7 +282,7 @@ public class SystemWebChromeClient extends WebChromeClient {
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override @Override
public void onPermissionRequest(final PermissionRequest request) { public void onPermissionRequest(final PermissionRequest request) {
Log.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources())); LOG.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources()));
request.grant(request.getResources()); request.grant(request.getResources());
} }

View File

@ -27,7 +27,6 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.os.Build; import android.os.Build;
import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebSettings.LayoutAlgorithm;
@ -40,6 +39,7 @@ import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine; import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.ICordovaCookieManager; import org.apache.cordova.ICordovaCookieManager;
import org.apache.cordova.LOG;
import org.apache.cordova.NativeToJsMessageQueue; import org.apache.cordova.NativeToJsMessageQueue;
import org.apache.cordova.PluginManager; import org.apache.cordova.PluginManager;
@ -151,20 +151,20 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
Method gingerbread_getMethod = WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class }); Method gingerbread_getMethod = WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
String manufacturer = android.os.Build.MANUFACTURER; String manufacturer = android.os.Build.MANUFACTURER;
Log.d(TAG, "CordovaWebView is running on device made by: " + manufacturer); LOG.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB && if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB &&
android.os.Build.MANUFACTURER.contains("HTC")) android.os.Build.MANUFACTURER.contains("HTC"))
{ {
gingerbread_getMethod.invoke(settings, true); gingerbread_getMethod.invoke(settings, true);
} }
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8"); LOG.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.d(TAG, "Doing the NavDump failed with bad arguments"); LOG.d(TAG, "Doing the NavDump failed with bad arguments");
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore"); LOG.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore."); LOG.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
} }
//We don't save any form data in the application //We don't save any form data in the application
@ -242,14 +242,14 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
try { try {
WebView.setWebContentsDebuggingEnabled(true); WebView.setWebContentsDebuggingEnabled(true);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! "); LOG.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
e.printStackTrace(); e.printStackTrace();
} }
} }
private static void exposeJsInterface(WebView webView, CordovaBridge bridge) { private static void exposeJsInterface(WebView webView, CordovaBridge bridge) {
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) { if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old."); LOG.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically. // Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just // This isn't hard to work-around on the JS side, but it's easier to just
// use the prompt bridge instead. // use the prompt bridge instead.
@ -327,7 +327,7 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
try { try {
webView.getContext().unregisterReceiver(receiver); webView.getContext().unregisterReceiver(receiver);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e); LOG.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
} }
} }
} }