I am wondering if there is a syntax to print out something in the eclipse console windows. This is just like NSLog in xcode. Thank you
Use the android.util.Log class http://developer.android.com/reference/android/util/Log.html.
For example:
import android.util.Log;
class Someclass {
private static final String TAG = "Someclass";
...
public boolean someMethod(int argument) {
Log.i(TAG, "This is some information log");
if (argument == 0) {
Log.e(TAG, "Error argument is 0!!!");
return false;
}
Log.w(TAG, "Warning returning default value");
return true;
}
};
The reason the TAG variable is assigned like that instead of something like:
Somelcass.class.getSimpleName() is because the reflective method will cause the reflection metta data of the class to be loaded on initialisation, however, the 'preferred' method by android developers prevents that and hence saves CPU and initialisation time.
Take a look at the Log class - it has a number of different logging functions.
Related
I would like to log information in model classes - not necessarily for unit testing purposes but for real life scenarios where I am trying to debug.
However, if I try to use android.util.Log methods I get the following errors when running JUnit tests:
java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.
I understand why this occurs, I should not be using Android framework code in model classes that are designed to be framework independent! I'm not really arguing against the error, but rather I am trying to find a way to work around this.
I have one idea, does this make sense?
Create a CustomLog class along these lines:
public class CustomLog {
private static ILogger mLogger;
public static void setLogger(ILogger logger) {
mLogger = logger;
}
public static void e(String tag, String message) {
mLogger.e(tag, message);
}
}
Where ILogger is an interface with the required methods to perform the log functionality (e, d, etc. methods...)
I could create an ILoggerImpl that uses the android.util.Log methods, and a MockLogger class that simply prints out to System.out.println and/or does nothing (or anything else!).
I think that'd perfectly fit my needs (I would be required to setup my CustomLog class very early on in the lifecycle, but that's not a huge deal).
However, if I ever needed to add third party libraries/outside code to my model classes, this would likely break again in the same manner if the new libraries/code use android.util.Log methods.
So, is there a "catch all" type behavior I could use? What do you think?
One way of solving the "Not mocked" exception you cited is to use PowerMockito to mock the Logging methods. Instead of calling PowerMockito.mockStatic(Log.class); as explained in the linked answer, you can take inspiration from this, and use PowerMockito to replace() Android.util's Log.v, Log.d, Log.i & Log.e with methods that will run System.out.println instead. This allows you to see the logged messages in Android Studio's Run window.
String[] logMethods = {"v", "d", "i", "e"};
InvocationHandler systemOutPrintln = new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StringBuilder messageBuilder = new StringBuilder();
for (int i = 0; i < args.length; i++) {
String arg = args[i].toString();
messageBuilder.append(arg);
// add separators, ASCII art, ...
}
System.out.println(messageBuilder);
return messageBuilder.toString().length();
}
};
for (String logMethod : logMethods) {
replace(method(Log.class, logMethod, String.class, String.class)).with(systemOutPrintln);
replace(method(Log.class, logMethod, String.class, String.class, Throwable.class)).with(systemOutPrintln);
}
Disclaimer: I'm not sure if the above is the most idiomatic implementation.
I want to create a custom annotation which when used on a method, will check if a certain static variable is valid. If not will throw an exception.
e.g:
#IDCheck
public void someMethod() {
//code...
}
Which checks for an ID, stored as a global variable. It should not be null and the value must comply with some rules.
Since this ID keeps changing at runtime, I want to validate it using an annotation at runtime.
What I tried:
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Checks for a valid ID.
* <p>
* This is a marker annotation and it has no specific attributes.
*/
#Target(METHOD)
#Retention(RUNTIME)
public #interface IDCheck {
}
I am not sure how I can do a validation at runtime whenever a method with #IDCheck annotation is invoked.
Tried something like this:
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import javax.lang.model.SourceVersion;
#SupportedAnnotationTypes("IDCheck")
public class IDCheckProcessor extends AbstractProcessor {
#Override
public boolean process(Set<? extends TypeElement> arg0,
RoundEnvironment roundEnv) {
if(!Util.isIDValid()){
//Throw an exception.
return true;
}
return false;
}
#Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
But that code in the process method never gets called.
If you want to check this at runtime, it is not necessary to use an annotation processor.
I recommend you use a proxy and a little reflection to make it happen. You have already defined your annotation. What you need to do is create an interface for the component you want to check and annotate the method declaration there.
public interface MyInterface {
#IDCheck
void someMethod();
}
Then you use Java's dynamic proxy to create a proxy of the interface:
MyInterface instance = Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
new Class[]{MyInterface}, handler);
The third parameter is the important thing here - this is an InvocationHandler. It will get notified each time a method from the proxy has been called. You should override it's invoke() method and implement your validation there. Something like this:
#Override
public Object invoke(Object proxy, Method method, Object[] args) {
if (method.isAnnotationPresent(IDCheck.class)) {
//proceed with navigation and throw exception if invalid
}
// delegate the method execution to a wrapped implementor of the MyInterface
}
This is guaranteed to work at runtime. The performance impact is not very big and it is unlikely it is even noticeable.
I want to validate text inputs with a helper class. I started with a method to prove for a single name with upper case at the beginning and max length of 20 characters:
package xyz.helper;
import java.util.regex.Pattern;
public abstract class InputValidator {
public static boolean checkSingleName(String string) {
return Pattern.matches("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}", string);
}
}
When I test in the Activity for example with "Hello", I get back FALSE and the error message. Is my regular expression wrong?
// Check User entries
private boolean checkEntries() {
boolean validEntry = InputValidator.checkSingleName(title.toString());
if (!validEntry) {
title.setError(getString(R.string.error_occasion));
return false;
}
return true;
}
Thanks for any hints
I think the way you've built the sentence is not right currently. I'd try this way:
return Pattern.compile("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}").matcher("Hello").matches()
Often, in questions like this, it is what you are NOT showing that is the problem.
Demonstration of a working Java implementation of your regex (see http://ideone.com/nFPcic):
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.regex.Pattern;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
if(checkSingleName("Hello")) {
System.out.println("Yes that is valid");
}
else {
System.out.println("No that is not valid");
}// your code goes here
}
public static boolean checkSingleName(String string) {
return Pattern.matches("^[A-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜ]{1}[a-zàáâãäåæçèéêëìíîïñòóôõöøùúûü]{1,19}", string);
}
}
This prints out "Yes that is valid" with "Hello" as the input string. When I add a digit to the name, it prints "Not that is not valid". As expected.
If you are getting a different result, it is because of something you are not showing. Could it be there is a carriage return, space or tab at the start/end of the string you are testing?
Incidentally, you really don't need the {1} after the initial capital letter; and your regex is terribly restrictive. See http://en.wikipedia.org/wiki/Category:Lowercase_proper_names_or_pseudonyms , or even better, http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/ - thought provoking and at times hilarious.
I raised this as a bug on the ORMLite Sourceforge bug tracker but I haven't seen any updates. I didn't see any process docs saying if I need to do anything to pass it to Gray?
Seen testing v4.47 (the behaviour on older ORMLite versions is worse as the config file generation fails much earlier).
My #DatabaseTable classes all include some Android imports, e.g.
import android.content.Context;
Most of my classes extend a single abstract superclass, e.g.
#DatabaseTable(tableName = SongMessage.TABLE_NAME)
public class SongMessage extends AbstractMessage {
However, a few of my classes extend a shared abstract super class, e.g.
#DatabaseTable(tableName = PhotoMessage.TABLE_NAME)
public class PhotoMessage extends SingleImageMessage implements <snip> {
SingleImageMessage extends the same common AbstractMessage:
public abstract class SingleImageMessage extends AbstractMessage {
Running my OrmLiteConfigUtil works fine for my direct subclasses, but doesn't work for the ones which extend the intermediate abstract class:
...
Wrote config for class com.mypackage.TextMessage
Skipping class com.mypackage.PhotoMessage because we got an error finding its definition: android/content/Context
Wrote config for class com.mypackage.SongMessage
...
Sorry for my late reply. ORMLite has been a bit swapped out as of late.
Running my OrmLiteConfigUtil works fine for my direct subclasses, but doesn't work for the ones which extend the intermediate abstract class:
This problem is obviously because of the Context import. Unfortunately the OrmLiteConfigUtil is running locally and does not have access to that class which is only exported as a stub by Google.
One thing that I could do is just catch and log an error only when the superclass cannot be investigated. So the subclass would be outputted correctly. Would that work?
I may need to see more of your abstract class definition. The error, may be coming from the DatabaseFieldConfig.fromField call. The error message indicates that it's trying to find a database type definition for android.content.Context. Is there a field declared in your abstract class that is of that type? Here's the code that produces the error message you're seeing.
private static void writeConfigForTable(BufferedWriter writer, Class<?> clazz) throws SQLException, IOException {
String tableName = DatabaseTableConfig.extractTableName(clazz);
List<DatabaseFieldConfig> fieldConfigs = new ArrayList<DatabaseFieldConfig>();
// walk up the classes finding the fields
try {
for (Class<?> working = clazz; working != null; working = working.getSuperclass()) {
for (Field field : working.getDeclaredFields()) {
DatabaseFieldConfig fieldConfig = DatabaseFieldConfig.fromField(databaseType, tableName, field);
if (fieldConfig != null) {
fieldConfigs.add(fieldConfig);
}
}
}
} catch (Error e) {
System.err.println("Skipping " + clazz + " because we got an error finding its definition: "
+ e.getMessage());
return;
}
if (fieldConfigs.isEmpty()) {
System.out.println("Skipping " + clazz + " because no annotated fields found");
return;
}
#SuppressWarnings({ "rawtypes", "unchecked" })
DatabaseTableConfig<?> tableConfig = new DatabaseTableConfig(clazz, tableName, fieldConfigs);
DatabaseTableConfigLoader.write(writer, tableConfig);
writer.append("#################################");
writer.newLine();
System.out.println("Wrote config for " + clazz);
}
I have tried to trace through the code to see how addJavascriptInterface() on WebView is implemented, but it dives into native code, which basically cripples my ability to grok what is going on.
Specifically, I am trying to determine if the JNI(?) means by which addJavascriptInterface() arranges to call back into Java code relies upon getClass() as part of a reflection strategy, to map method references in JavaScript source to the implementations in Java. I would assume that it has to, and maybe I am searching in the wrong place, but I am not seeing it.
Can anyone point me to the code where the injected Java objects are used, so we can see how that is implemented?
Thanks!
UPDATE
To clarify, I mean using getClass() on the object passed to addJavascriptInterface().
The code that I think you're after is found in external/webkit/Source/WebCore/bridge/jni/. There are two main subdirectories there, jsc and v8 representing the two Javascript engines Android has used. Since V8 is the engine that's been used most recently and for some time, we'll stick with that.
I'm assuming you were able to successfully trace the Java side of the code to get from WebView.addJavascriptInterface() down to BrowserFrame.nativeAddJavaScriptInterface(), I'll leave those details out. The native side is picked up by AddJavaScriptInterface() in external/webkit/Source/WebKit/android/jni/WebCoreFrameBridge.cpp, where the Java object passed in by the application is finally bound to the WebKit frame with bindToWindowObject().
I am trying to determine if the JNI means by which addJavascriptInterface() arranges to call back into Java code relies upon getClass() as part of a reflection strategy
The short answer is yes. They use a lot of wrappers around traditional JNI code, but if you look inside them the accessors on the JNIEnv for doing reflection are present. The wrappers they've created in V8 are:
external/webkit/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
external/webkit/Source/WebCore/bridge/jni/v8/JavaClassJobjectV8.cpp
external/webkit/Source/WebCore/bridge/jni/v8/JavaMethodJobjectV8.cpp
Going back to WebCoreFrameBridge.cpp, before that object the application passed in is bound, the jobject originally handed into the native code via JNI is wrapped in a JavaInstance class, and then converted to an NPObject, which is the final object bound to WebKit. The source for the V8 NPObject is at:
external/webkit/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
We can see in the NPObject implementation that the calls always extract the JavaInstance back out and call methods there. If you look at examples like JavaNPObjectHasMethod() or JavaNPObjectInvoke, you'll notice the following line appear frequently:
instance->getClass()->methodsNamed(name)
This returns the JavaClass wrapper they've created, but if you look into the JavaClassJobjectV8 constructor and associated methods you'll see those familiar reflection calls to the Java object using the JNIEnv (including the actual JNI getClass() call into Dalvik).
So when a method is called by the bound WebKit frame, it finds the associated NPObject, which extracts its JavaInstance wrapper, which in turn uses JNI reflection to get access to the Java methods. The chain of custody here is a little harder to follow, so let me know if what's already provided is sufficient to answer your questions.
Here is what I got:
WebView wv = ...;
wv.addJavascriptInterface(object, name);
this goes to:
public void addJavascriptInterface(Object object, String name) {
checkThread();
mProvider.addJavascriptInterface(object, name);
}
mProvider is an interface of type WebViewProvider as it is declared in in WebView class:
//-------------------------------------------------------------------------
// Private internal stuff
//-------------------------------------------------------------------------
private WebViewProvider mProvider;
The only method I can see that instantiates it is ensureProviderCreated():
private void ensureProviderCreated() {
checkThread();
if (mProvider == null) {
// As this can get called during the base class constructor chain, pass the minimum
// number of dependencies here; the rest are deferred to init().
mProvider = getFactory().createWebView(this, new PrivateAccess());
}
}
getFactory() is implemented as:
private static synchronized WebViewFactoryProvider getFactory() {
return WebViewFactory.getProvider();
}
getProvider() is implemented as:
static synchronized WebViewFactoryProvider getProvider() {
// For now the main purpose of this function (and the factory abstraction) is to keep
// us honest and minimize usage of WebViewClassic internals when binding the proxy.
if (sProviderInstance != null) return sProviderInstance;
sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
if (sProviderInstance == null) {
if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
sProviderInstance = new WebViewClassic.Factory();
}
return sProviderInstance;
}
getFactoryByName() is implemented as:
private static WebViewFactoryProvider getFactoryByName(String providerName) {
try {
if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName);
Class<?> c = Class.forName(providerName);
if (DEBUG) Log.v(LOGTAG, "instantiating factory");
return (WebViewFactoryProvider) c.newInstance();
} catch (ClassNotFoundException e) {
Log.e(LOGTAG, "error loading " + providerName, e);
} catch (IllegalAccessException e) {
Log.e(LOGTAG, "error loading " + providerName, e);
} catch (InstantiationException e) {
Log.e(LOGTAG, "error loading " + providerName, e);
}
return null;
}
and here is where it uses Reflection. If an exception occurs during instantiating the custom class, WebViewClassic.Factory() will be used instead. Here is how it is implemented:
static class Factory implements WebViewFactoryProvider, WebViewFactoryProvider.Statics {
#Override
public String findAddress(String addr) {
return WebViewClassic.findAddress(addr);
}
#Override
public void setPlatformNotificationsEnabled(boolean enable) {
if (enable) {
WebViewClassic.enablePlatformNotifications();
} else {
WebViewClassic.disablePlatformNotifications();
}
}
#Override
public Statics getStatics() { return this; }
#Override
public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) {
return new WebViewClassic(webView, privateAccess);
}
#Override
public GeolocationPermissions getGeolocationPermissions() {
return GeolocationPermissionsClassic.getInstance();
}
#Override
public CookieManager getCookieManager() {
return CookieManagerClassic.getInstance();
}
#Override
public WebIconDatabase getWebIconDatabase() {
return WebIconDatabaseClassic.getInstance();
}
#Override
public WebStorage getWebStorage() {
return WebStorageClassic.getInstance();
}
#Override
public WebViewDatabase getWebViewDatabase(Context context) {
return WebViewDatabaseClassic.getInstance(context);
}
}
Now go back to mProvider = getFactory().createWebView(this, new PrivateAccess()); where getFactory() is either the custom class (by reflection) or WebViewClassic.Factory.
WebViewClassic.Factory#createWebView() returns WebViewClassic which is a sub-type of mProvider's type.
WebViewClassic#addJavascriptInterface is implemented as:
/**
* See {#link WebView#addJavascriptInterface(Object, String)}
*/
#Override
public void addJavascriptInterface(Object object, String name) {
if (object == null) {
return;
}
WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
arg.mObject = object;
arg.mInterfaceName = name;
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
}
I think, this is what you are looking for :)
This is more of a comment than an answer, but I can't add a stacktrace in comments. So here it goes:
When setting a breakpoint in an Object that servers as a JavaScript Interface implementation, this is a sample stack-trace I get:
16> WebViewCoreThread#830034675584, prio=5, in group 'main', status: 'RUNNING'
at com.mediaarc.player.books.model.pagesource.service.EPubPageSourceService$JS.JSReady(EPubPageSourceService.java:1752)
at android.webkit.JWebCoreJavaBridge.nativeServiceFuncPtrQueue(JWebCoreJavaBridge.java:-1)
at android.webkit.JWebCoreJavaBridge.nativeServiceFuncPtrQueue(JWebCoreJavaBridge.java:-1)
at android.webkit.JWebCoreJavaBridge.handleMessage(JWebCoreJavaBridge.java:113)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:814)
at java.lang.Thread.run(Thread.java:841)
It starts in Java (Thread.run --> handleMessage). Then it disappears into Native code (nativeServiceFuncPtrQueue) and it comes out again in Java (nativeServiceFuncPtrQueue --> JSReady).
This stack is from a Nexus 10 running 4.3.
There is something going on in the Native Layer that moves the execution from within a call to nativeServiceFuncPtrQueue directly to the Java method of the JavaScriptInterface instance in Java.
Nowadays, the JavaScriptInterface need to annotate each method that it publishes to JavaScript (#JavaScriptInterface method annotation). Maybe this generates some JNI bridges on the fly calling from Native into Java.
I wonder how this stack-trace would have looked like on an older device where the #JavaScriptInterface annotations were not necessary.
from Understanding Android's webview addjavascriptinterface : "The method WebView.addJavascriptInterface sends a message to an instance of WebViewCore:
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg); In WebViewCore.java there are a bunch of overloaded methods called sendMessage , but we don't really need to know which exactly is being called, since they do pretty much the same thing. There's even a nice comment to give us a hint that we're in the right place! All of them are delegating to an instance of EventHub which is some inner class. This method turns out to be synchronized, and is sending a message to an instance of Handler, which is a good indication that this is probably running in another thread, but for completeness sake, let's find out!
That Handler is instantiated in EventHub.transferMessages which is called from WebViewCore.initialize . There are a few more hops here, but eventually I found out that this is called from run in WebCoreThread (subclass of Runnable), which is instantiated along with a new Thread right here ." instantiated along with a new Thread right here ."
synchronized (WebViewCore.class) {
if (sWebCoreHandler == null) {
// Create a global thread and start it.
Thread t = new Thread(new WebCoreThread());
t.setName(THREAD_NAME);
t.start();
try {
WebViewCore.class.wait();
} catch (InterruptedException e) {
Log.e(LOGTAG, "Caught exception while waiting for thread " +
"creation.");
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
}
In other words, this could be the chain of calls in my opinion:
android.webkit.WebViewClassic
4159 #Override
4160 public void More ...addJavascriptInterface(Object object, String name) {
4161
4162 if (object == null) {
4163 return;
4164 }
4165 WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
4166
4167 arg.mObject = object;
4168 arg.mInterfaceName = name;
4169
4170 // starting with JELLY_BEAN_MR1, annotations are mandatory for enabling access to
4171 // methods that are accessible from JS.
4172 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
4173 arg.mRequireAnnotation = true;
4174 } else {
4175 arg.mRequireAnnotation = false;
4176 }
4177 mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
4178 }
android.webkit.WebViewCore
static class JSInterfaceData {
827 Object mObject;
828 String mInterfaceName;
829 boolean mRequireAnnotation;
830 }
java.lang.Object
37 public class Object {
38
39 private static native void registerNatives();
40 static {
41 registerNatives();
42 }
Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class. The actual result type is Class where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:
Number n = 0;
Class<? extends Number> c = n.getClass();
Returns: The Class object that represents the runtime class of this object. See also: The Java Language Specification, Third Edition (15.8.2 Class Literals)
64
65 public final native Class<?> getClass();
From a Dalvik's perspective I think you are just registering a JNI callback via findClass like this from JNIHelp.c :
/*
* Register native JNI-callable methods.
*
* "className" looks like "java/lang/String".
*/
int jniRegisterNativeMethods(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
LOGV("Registering %s natives\n", className);
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
LOGE("Native registration unable to find class '%s', aborting\n",
className);
abort();
}
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
LOGE("RegisterNatives failed for '%s', aborting\n", className);
abort();
}
(*env)->DeleteLocalRef(env, clazz);
return 0;
}
In conclusion my idea is derived from Native Libraries:
//Get jclass with env->FindClass
so maybe FindClass could be used instead of getClass...