Does addJavascriptInterface() rely upon getClass()? - android

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...

Related

Using PixelCopy to take a screenshot [duplicate]

What is the use of anonymous classes in Java? Can we say that usage of anonymous class is one of the advantages of Java?
By an "anonymous class", I take it you mean anonymous inner class.
An anonymous inner class can come useful when making an instance of an object with certain "extras" such as overriding methods, without having to actually subclass a class.
I tend to use it as a shortcut for attaching an event listener:
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
Using this method makes coding a little bit quicker, as I don't need to make an extra class that implements ActionListener -- I can just instantiate an anonymous inner class without actually making a separate class.
I only use this technique for "quick and dirty" tasks where making an entire class feels unnecessary. Having multiple anonymous inner classes that do exactly the same thing should be refactored to an actual class, be it an inner class or a separate class.
Anonymous inner classes are effectively closures, so they can be used to emulate lambda expressions or "delegates". For example, take this interface:
public interface F<A, B> {
B f(A a);
}
You can use this anonymously to create a first-class function in Java. Let's say you have the following method that returns the first number larger than i in the given list, or i if no number is larger:
public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}
And then you have another method that returns the first number smaller than i in the given list, or i if no number is smaller:
public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}
These methods are almost identical. Using the first-class function type F, we can rewrite these into one method as follows:
public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}
You can use an anonymous class to use the firstMatch method:
F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
This is a really contrived example, but its easy to see that being able to pass functions around as if they were values is a pretty useful feature. See "Can Your Programming Language Do This" by Joel himself.
A nice library for programming Java in this style: Functional Java.
Anonymous inner class is used in following scenario:
1.) For Overriding(subclassing), when class definition is not usable except current case:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}
2.) For implementing an interface, when implementation of interface is required only for current case:
interface InterfaceA{
public void methodA();
}
class B{
InterfaceA a = new InterfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}
3.) Argument Defined Anonymous inner class:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
I use them sometimes as a syntax hack for Map instantiation:
Map map = new HashMap() {{
put("key", "value");
}};
vs
Map map = new HashMap();
map.put("key", "value");
It saves some redundancy when doing a lot of put statements. However, I have also run into problems doing this when the outer class needs to be serialized via remoting.
They're commonly used as a verbose form of callback.
I suppose you could say they're an advantage compared to not having them, and having to create a named class every time, but similar concepts are implemented much better in other languages (as closures or blocks)
Here's a swing example
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here...
}
});
Although it's still messily verbose, it's a lot better than forcing you to define a named class for every throw away listener like this (although depending on the situation and reuse, that may still be the better approach)
You use it in situations where you need to create a class for a specific purpose inside another function, e.g., as a listener, as a runnable (to spawn a thread), etc.
The idea is that you call them from inside the code of a function so you never refer to them elsewhere, so you don't need to name them. The compiler just enumerates them.
They are essentially syntactic sugar, and should generally be moved elsewhere as they grow bigger.
I'm not sure if it is one of the advantages of Java, though if you do use them (and we all frequently use them, unfortunately), then you could argue that they are one.
GuideLines for Anonymous Class.
Anonymous class is declared and initialized simultaneously.
Anonymous class must extend or implement to one and only one class or interface resp.
As anonymouse class has no name, it can be used only once.
eg:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
Yes, anonymous inner classes is definitely one of the advantages of Java.
With an anonymous inner class you have access to final and member variables of the surrounding class, and that comes in handy in listeners etc.
But a major advantage is that the inner class code, which is (at least should be) tightly coupled to the surrounding class/method/block, has a specific context (the surrounding class, method, and block).
new Thread() {
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("Exception message: " + e.getMessage());
System.out.println("Exception cause: " + e.getCause());
}
}
}.start();
This is also one of the example for anonymous inner type using thread
An inner class is associated with an instance of the outer class and there are two special kinds: Local class and Anonymous class. An anonymous class enables us to declare and instantiate a class at same time, hence makes the code concise. We use them when we need a local class only once as they don't have a name.
Consider the example from doc where we have a Person class:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
and we have a method to print members that match search criteria as:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
where CheckPerson is an interface like:
interface CheckPerson {
boolean test(Person p);
}
Now we can make use of anonymous class which implements this interface to specify search criteria as:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
Here the interface is very simple and the syntax of anonymous class seems unwieldy and unclear.
Java 8 has introduced a term Functional Interface which is an interface with only one abstract method, hence we can say CheckPerson is a functional interface. We can make use of Lambda Expression which allows us to pass the function as method argument as:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
We can use a standard functional interface Predicate in place of the interface CheckPerson, which will further reduce the amount of code required.
i use anonymous objects for calling new Threads..
new Thread(new Runnable() {
public void run() {
// you code
}
}).start();
Anonymous inner class can be beneficial while giving different implementations for different objects. But should be used very sparingly as it creates problem for program readability.
One of the major usage of anonymous classes in class-finalization which called finalizer guardian. In Java world using the finalize methods should be avoided until you really need them. You have to remember, when you override the finalize method for sub-classes, you should always invoke super.finalize() as well, because the finalize method of super class won't invoke automatically and you can have trouble with memory leaks.
so considering the fact mentioned above, you can just use the anonymous classes like:
public class HeavyClass{
private final Object finalizerGuardian = new Object() {
#Override
protected void finalize() throws Throwable{
//Finalize outer HeavyClass object
}
};
}
Using this technique you relieved yourself and your other developers to call super.finalize() on each sub-class of the HeavyClass which needs finalize method.
You can use anonymous class this way
TreeSet treeSetObj = new TreeSet(new Comparator()
{
public int compare(String i1,String i2)
{
return i2.compareTo(i1);
}
});
Seems nobody mentioned here but you can also use anonymous class to hold generic type argument (which normally lost due to type erasure):
public abstract class TypeHolder<T> {
private final Type type;
public TypeReference() {
// you may do do additional sanity checks here
final Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public final Type getType() {
return this.type;
}
}
If you'll instantiate this class in anonymous way
TypeHolder<List<String>, Map<Ineger, Long>> holder =
new TypeHolder<List<String>, Map<Ineger, Long>>() {};
then such holder instance will contain non-erasured definition of passed type.
Usage
This is very handy for building validators/deserializators. Also you can instantiate generic type with reflection (so if you ever wanted to do new T() in parametrized type - you are welcome!).
Drawbacks/Limitations
You should pass generic parameter explicitly. Failing to do so will lead to type parameter loss
Each instantiation will cost you additional class to be generated by compiler which leads to classpath pollution/jar bloating
An Anonymous Inner Class is used to create an object that will never be referenced again. It has no name and is declared and created in the same statement.
This is used where you would normally use an object's variable. You replace the variable with the new keyword, a call to a constructor and the class definition inside { and }.
When writing a Threaded Program in Java, it would usually look like this
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
The ThreadClass used here would be user defined. This class will implement the Runnable interface which is required for creating threads. In the ThreadClass the run() method (only method in Runnable) needs to be implemented as well.
It is clear that getting rid of ThreadClass would be more efficient and that's exactly why Anonymous Inner Classes exist.
Look at the following code
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
This code replaces the reference made to task in the top most example. Rather than having a separate class, the Anonymous Inner Class inside the Thread() constructor returns an unnamed object that implements the Runnable interface and overrides the run() method. The method run() would include statements inside that do the work required by the thread.
Answering the question on whether Anonymous Inner Classes is one of the advantages of Java, I would have to say that I'm not quite sure as I am not familiar with many programming languages at the moment. But what I can say is it is definitely a quicker and easier method of coding.
References: Sams Teach Yourself Java in 21 Days Seventh Edition
The best way to optimize code. also, We can use for an overriding method of a class or interface.
import java.util.Scanner;
abstract class AnonymousInner {
abstract void sum();
}
class AnonymousInnerMain {
public static void main(String []k){
Scanner sn = new Scanner(System.in);
System.out.println("Enter two vlaues");
int a= Integer.parseInt(sn.nextLine());
int b= Integer.parseInt(sn.nextLine());
AnonymousInner ac = new AnonymousInner(){
void sum(){
int c= a+b;
System.out.println("Sum of two number is: "+c);
}
};
ac.sum();
}
}
One more advantage:
As you know that Java doesn't support multiple inheritance, so if you use "Thread" kinda class as anonymous class then the class still has one space left for any other class to extend.

Test void method using mokito

How do I test below method using mockito
public void showArg(String ss) {
if(ss == null) {
throw new NullPointerException();
}else if(ss.equals("")) {
throw new IllegalArgumentException();
}
// Log.d("",""+ss);
if(ss.equals("xyz")) {
this.show();
}else {
getResult(0);
}
}
In this example, there is nothing to be mocked. I just want to test the that is appropriate methods are called based on i/p.
If you want to verify that this method was called (assuming it was public), I suggest using a spy...
MyClass spy = Mockito.spy( myActualObject );
spy.showArg("xyz");
Mockito.verify(spy).show();
Spying (instead of mocking) means to take an actual object and "spy" on it, by wrapping it in another instance. This way you can call actual methods, but also check what was called and even modify what some methods will do, similar to mocking (the difference is, that a mock does not have an underlying "real" object, while a spy has).
As already mentioned you should use a spy to test such code. Additionaly looking at your code you should also test whether appropiate exceptions are thrown.
Code testing border cases can be looking like this:
#Test(expected = NullPointerException.class)
public void shouldThrowNullPointerExceptionWhenNullStringProvided() {
showArg(null);
}
#Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegarArgumentExceptionWhenEmptyStringProvided() {
showArg("");
}

Verify a static method was called by another static method in PowerMock

I have a Tool class with two static methods, doSomething(Object) and callDoSomething(). The names are intuitive in that callDoSomething delegates its call to doSomething(Object);
public class Tool
{
public static void doSomething( Object o )
{
}
public static void callDoSomething()
{
doSomething( new Object());
}
}
I have a Test class for Tool and I'd like to verify if doSomething(Object) was called (I want to do Argument Matching too in the future)
#RunWith( PowerMockRunner.class )
#PrepareForTest( { Tool.class } )
public class ToolTest
{
#Test
public void toolTest()
{
PowerMockito.mockStatic( Tool.class );
Tool.callDoSomething();// error!!
//Tool.doSomething();// this works! it gets verified!
PowerMockito.verifyStatic();
Tool.doSomething( Mockito.argThat( new MyArgMatcher() ) );
}
class MyArgMatcher extends ArgumentMatcher<Object>
{
#Override
public boolean matches( Object argument )
{
return true;
}
}
}
Verify picks up doSomething(Object) if it's called directly. I've commented this code out above. Verify does NOT pick up doSomething(Object) when using callDoSomething, (this is the code shown above). This is my error log when running the code above:
Wanted but not invoked tool.doSomething(null);
However, there were other interactions with this mock.
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:192)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:60)
at Tool.doSomething(Tool.java)
at ToolTest.toolTest(ToolTest.java:22)
... [truncated]
I'd like to avoid making any changes to the Tool class. My question is, how can I verify doSomething(Object) was called from callDoSomething(), as well as perform some argument matching on doSomething's param
It sounds like you want to use a static spy (partial mock). The section of the PowerMock documentation that talks about mocking static has a note in the second bullet that could be easily missed:
(use PowerMockito.spy(class) to mock a specific method)
Note, in your example you're not actually mocking the behavior, just verifying the method is called. There's a subtle but important difference. If you don't want doSomething(Object) to be called you'd need to do something like this:
#Test
public void toolTest() {
PowerMockito.spy(Tool.class); //This will call real methods by default.
//This will suppress the method call.
PowerMockito.doNothing().when(Tool.class);
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
Tool.callDoSomething();
//The rest isn't needed since you're already mocking the behavior
//but you can still leave it in if you'd like.
PowerMockito.verifyStatic();
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
}
If you still want the method to fire though, just remove the two lines for doNothing(). (I added a simple System.out.println("do something " + o); to my version of Tool.java as an additional verification of doNothing().)
You can do your validation with this:
public class Tool{
public static boolean isFromCallDoSomethingMethod= false;
public static void doSomething(Object o){
}
public static void callDoSomething() {
doSomething(new Object());
isFromCallDoSomethingMethod= true;
}
}
You can do the verification as:
if(Tool.isFromCallDoSomethingMethod){
//you called doSomething() from callDoSomething();
}
REMEMBER
Don't forget to do the validation if you call the doSomething() from another way that is not from callDoSomething(), you can do this by ussing Tool.isFromCallDoSomethingMethod = false
Is this what you want?

Class not found when unmarshalling when passing Parcelable through Messenger to remote service

I have a Parcelable object which I use to pass it from Activity to remote service. When I pass it using AIDL interface, everything sounds fine.
Recently, I try to pass it through Messenger from Activity.
// TEST TEST TEST!
StockInfo stockInfo0 = new StockInfo(Code.newInstance("code0"), Symbol.newInstance("symbol0"));
StockInfo stockInfo1 = new StockInfo(Code.newInstance("code1"), Symbol.newInstance("symbol1"));
StockInfo stockInfo2 = new StockInfo(Code.newInstance("code2"), Symbol.newInstance("symbol2"));
List<StockInfo> stockInfos = new ArrayList<StockInfo>();
stockInfos.add(stockInfo0);
stockInfos.add(stockInfo1);
stockInfos.add(stockInfo2);
StockInfosEx stockInfosEx = new StockInfosEx(stockInfos, "abc");
msg.obj = stockInfosEx;
try {
mService.send(msg);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I'm getting the following exception in remote service.
02-21 22:55:16.546: E/Parcel(8365): Class not found when
unmarshalling: com.example.testonmessenger.StockInfosEx, e:
java.lang.ClassNotFoundException:
com.example.testonmessenger.StockInfosEx
I was wondering, what can get wrong in between? Here is my Parcelable object.
public class StockInfosEx implements Parcelable {
public final List<StockInfo> stockInfos;
public final String searchedString;
public StockInfosEx(List<StockInfo> stockInfos, String searchedString) {
this.stockInfos = stockInfos;
this.searchedString = searchedString;
}
////////////////////////////////////////////////////////////////////////////
// Handling Parcelable nicely.
public static final Parcelable.Creator<StockInfosEx> CREATOR = new Parcelable.Creator<StockInfosEx>() {
public StockInfosEx createFromParcel(Parcel in) {
return new StockInfosEx(in);
}
public StockInfosEx[] newArray(int size) {
return new StockInfosEx[size];
}
};
private StockInfosEx(Parcel in) {
stockInfos = new ArrayList<StockInfo>();
in.readTypedList(stockInfos, StockInfo.CREATOR);
searchedString = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedList(stockInfos);
parcel.writeString(searchedString);
}
// Handling Parcelable nicely.
////////////////////////////////////////////////////////////////////////////
}
To get complete source code, kindly download from https://www.dropbox.com/s/n69yuhddpb8vedz/testonmessenger.zip
Not Workable Approach (Because our Parcelable is custom, not part of Framework like Rect)
Activity
msg.obj = stockInfosEx;
Remote Service
StockInfosEx stockInfosEx = (StockInfosEx)msg.obj;
Workable Approach
Activity
msg.getData().putParcelable("data", stockInfosEx);
Remote Service
msg.getData().setClassLoader(StockInfosEx.class.getClassLoader());
StockInfosEx stockInfosEx = (StockInfosEx)msg.getData().getParcelable("data");
Now, after I read back the documentation of msg.obj (http://developer.android.com/reference/android/os/Message.html#obj) again, only I understand what it really mean by Parcelable of a framework class
An arbitrary object to send to the recipient. When using Messenger to
send the message across processes this can only be non-null if it
contains a Parcelable of a framework class (not one implemented by the
application). For other data transfer use setData(Bundle).
Note that Parcelable objects here are not supported prior to the FROYO
release.
You're probably not using the right ClassLoader. You need to keep track of the ClassLoader that is marshalling the class in the first place, and use THAT ClassLoader to unmarshall it.
When unmarshalling, you're using current thread's ClassLoader, which is not your UIThread but Android system thread, and as such, has no info about your custom classes.
I used a static class that contained my ClassLoader to solve this (similar approaches can be used without having it to be static).
Something like:
ClassLoaderHelper.setClassLoader(Thread.currentThread().getContextClassLoader());
Then when unmarshalling:
public final void readFromParcel(final Parcel in) {
id = in.readString();
appInfo = in.readParcelable(ClassLoaderHelper.getClassLoader());
...
}
See this other question for more detailed information (probably a duplicate btw).
I'm getting the following exception in remote service.
If you are truly getting this from the remote service, it is because the remote service app does not contain that class. If you are going to use custom Parcelable classes, both the client and the server must have the same class definition.
If, however, your stack trace feels like your Parcelable is being accessed from a core OS process, then you cannot pass Parcelable objects via obj reliably. I have only ever used obj on Message for in-process object passing, never for cross-process messages.

Is there a way to use a DexClassLoader without using reflection *everywhere*?

I have a library that I plan on using in dex form. I want to compile directly against this library, but not export it. Instead I want to drop it in my resources and use a class loader to actually instantiate it.
So here's my library:
public class Foo {
public doFoo(String message) {
}
public doFoo(int count, String message) {
}
}
Now I want to call doFoo(). A lot. More than it's probably reasonable to use reflection for. Right now it works with:
public class FooConsumer {
private final DexClassLoader fooLoader;
public FooConsumer(DexClassLoader fooLoader) {
this.fooLoader = fooLoader;
}
public void go() {
Class<?> fooClass = fooLoader.loadClass("com.library.Foo");
Object fooInstance = fooClass.newInstance();
Method fooMethodDoFoo = fooClass.getMethod("doFoo", String.class);
fooMethodDoFoo.invoke(fooInstance, "Hello World");
}
This is obviously fugly. Especially since I haven't included any of the exception handling, as there are half a dozen throwables to catch in there. I could cache a bunch of stuff, helping me with speed a bit, but not a lot.
Normally I'd have both aware of a third library that has an interface, but the library has some static methods and I can't edit it anyway. It'd be really nice if I could do something like:
public class FooConsumer {
private FooAccessor accessor;
public FooConsumer(DexClassLoader fooLoader) {
Object fooInstance = fooLoader.loadClass("com.library.Foo").newInstance();
Log.i("TEST", "fooInstance: " + fooInstance);
this.accessor = new FooAccessor(fooInstance);
}
public void go() {
accessor.doFoo("Hello World");
}
private static class FooAccessor {
private Foo fooInstance;
public FooAccessor(Object instance) {
fooInstance = (Foo)instance;
}
public void doFoo(String message) {
fooInstance.doFoo(message);
}
}
}
See what I did there? The inner class is just a wrapper around the Foo object, I've linked against it, but not exported it, and all is good in the world. But it doesn't work. In logcat I get
I/TEST: fooInstance: com.library.Foo#413b1b68
E/AndroidRuntime: java.lang.NoClassDefFoundError: com.library.Foo
...
Is there a way to have FooAccessor use the class loader I passed in? Or is the use of class loaders a damnation into reflection hell.
You might want to take a look at this gist.
https://gist.github.com/nickcaballero/7045993
It uses reflection to merge the new DexClassLoader to in-stock BaseDexClassLoader.

Categories

Resources